• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Nazgulled

Ler uma string formatada usando sscanf

13 mensagens neste tópico

O que pretendo fazer aqui era muito facil se o C tivesse expressões regulares já nas bibliotecas standard, mas não tem. Portanto, o que pretendo, é ler uma string no stdin e depois verificar se ela tem uma certa formatação e que retorne verdadeiro, se não retorne falso.

O objectivo é ler o seguinte: 1,5,"algumtexto",h

Ou seja, inteiro vírgula inteiro aspas string aspas virgula caracter

O caracter no fim, como devem ter percebido, só pode ser apenas um e ser ou 'h' ou 'v'.

O meu código funciona, e está algo tipo:

if(sscanf(args, "%d,%d,\"%[^\"]\",%2s", &x, &y, text, ori) == 4) {
// VERDADEIRO
} else {
// FALSO
}

Isto funciona de certa forma... vou começar a explicar pela parte do fim, o %2s, eu podia muito bem colocar aki %1s, para apenas aceitar um k é o k eu quero, so k neste caso, se o utilizador fizesse algo tipo 1,5,"algumtexto",hd, a string "ori" iria ser igual a "h", truncando o "d", mas não deixava de ser um input incorrecto, pk só kero pemitir apenas 1 caracter. ou seja, terei de truncar no minimo a 2 caracters e dentro do if (se for verdadeiro), fazer outra validação a perguntar se strlen(ori) é = 1, só assim consigo validar 1 caracter.

Na parte do texto, não me esta aceitar espaços, ou seja, isto: 1,5,"algum texto",h não funciona, dá erro de segmentation fault axo, n me lembro bem, ms dá um erro qualquer. E se eu fizer algo do genero: 1,5,"algum",texto",h também vai funcionar, porque ele vai ser = 4, leu todos os parametros, mas a variavel text vai tar vazia e a ori não vai ter o valor correcto, ou seja, dentro do if verdadeiro, tenho de fazer mais uma validação para me certificar que a variavel text tem algo...

Se fizer todas estas validações funciona (menos po espaço que so descobri hj que não funcionava e ainda vou ter de ver porquê), mas eu gostava de fazer isto de maneira mais simples e sem estas validações extra. Se houver por ai algum master em C e que entenda melhor o funcionamento do sscanf() ou se existir função melhor... agradecia :)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

faz:

if(sscanf(args, "%d,%d,\"%[^\"]\",%c", &x, &y, text, ori) == 4) {

// VERDADEIRO

} else {

// FALSO

}

isso resolvete o problema de so leres um caracter depois da string, %c lê apenas um caracter, quanto ao outro problema de fazer 1,5,"algum texto",h e dar segmentation fault é porque a tua variável text não deve ter espaco suficiente para guardar essa string...

Quanto ao outro problema de o utilizador meter 2 strings seguidas e isso nao funcionar, isso e mais dificil de tratar, das duas uma: ou dizes ao utilizador para usar o formato correcto e se estoirar temos pena, ou entao se queres fazer o programa mais robusto, aconselho-te a :

ler os dois inteiros e as duas virgulas iniciais com o sscanf,

meter um while depois a ler a partir da posicao da primeira ASPA até encontrares o \0 da string e vais guardando isso num array à parte e depois processas esse array como entenderes.

Para encontrares a posicao da primeira aspa podes usar a funcao strchr que te procura a primeira ocorrencia de um dado caracter dentro duma string e devolvete a posicao dele ou NULL se nao encontrar ( faz man strchr na shell pa saberes mais) .

Tu depois podes tratar essa string como entenderes, podes por exemplo para um input do tipo

1,5,"ola""mundo",h

ao fazeres isto ficavas com

"ola""mundo",h

no teu array a tratar

e podias por exemplo substituir as duas aspas do meio por espacos, ou mesmo transformar em "ola mundo"

, por fim, para sakares o teu ultimo caracter é ires à ultima posicao escrita pelo teu while (deve apontar po \0) e andares um para trás, lês o H e dps andas outro pa trás e metes lá o \0 ... e ficas com o H separado da string, e como meteste outro \0 antes do ultimo kk funcao k vá ler akilo vai ler apenas "ola""mundo"

Nao é a maneira mais elegante, mas é simples... se queres complicar podes sp usar um parser sintatico tipo o LEX ...

Ah e esquecime de dizer que tanto quanto sei as libs do C têm exp. regulares, procura por regexp.h ... nunca usei isso mas talvez possa fazer o que queres mais elegantemente...

Fika[]

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

offtopic: es de MCC ou LESI? :)

quanto ao teu problema, não te posso ajudar muito, porque eu tambem tenho de fazer esse trabalho, e por isso não te vou dar a minha solução.

aconselho-te apenas a usares o getchar, várias vezes, porque é a melhor coisa que podes usar. por exemplo, no final, podes verificar se houve mais algum input, fazendo um getchar no fim. se for o '\n', está ok, senão não está ok... o getchar tambem te resolve o problema dos espaços no meio da string. tens apenas de criar um filtro para os caracteres que sao aceites, e podes adicionar o espaço

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

@theproject

1) sim, eu sei que podia usar o %c, mas não sei porquê, isso não me estava a funcionar e dava um erro estupido na compilação, por isso, optei pelo %s.

2) a variavel de texto tem 256 caracteres, tem mais que suficiente para "algum texto", o problema dos espaços, deve ter noutro sitio...

3) sim, fazer isso dessa forma parece melhor porque assim permitir ler qualquer tipo de caracteres após as apas.. vou ver isso mais logo e optar pela melhor forma.

@untouchables

mcc, mas vou mudar pa lesi :X

também não quero soluções, quero ajuda em como resolver o problema e eu próprio tentar resolver os problemas, ou não aprendo nada. e usar o getchar, a mim, sinceramente, não me parece a opção mais viável para que o formato de input seja validado 100% correcto, é só o que me parece e pessoalmente, não o quero usar. quer dizer, eu usei-o para ler a string toda, o sscanf é só para validar o input.

e tu, tas em lesi ou mcc? e qt tiveste no tp2? so por curiosidade.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Eu acho que leria tudo com fgets e de seguida faria tratamento de strings normal com strcmp e caracter a caracter quando necessário.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

offtopic: tou em MCC. tive 17, e tu?

eu uso constantemente o getchar, mas pode ser que haja formas melhores de o fazer...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

depende exactamente do que se qusier fazer, também uso o getchar pa muitas cenas, mas não constantemente... e és caloiro ou nem por isso? é que se fores, ainda nos conhecemos e nem sabemos :) eu tive 19.

quanto ao problema, ja quase que o resolvi, so falta mesmo ler espaços, ms ao contrario do que obtia antes quando tinha um espaço (segmentation fault) agora, a leitura da string para ali no espaço... e fiz tudo mais ou menos como disse o theproject, li os 2 inteiros e o resto como string, dps verifiquei se nas devidas posições, tinha aspas, virgula e um unico caracter que correspondesse ou h ou v. e assim funciona bem.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

sim, sou caloiro! chamo-me Jorge, sabes quem sou? e tu, quem es?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

ah, ja sei! es o gajo do fato dos slipknot :)

sou aquele gajo k hoj estava a tua frente na aula de PI, tas a ver?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

lololol... ainda te lembras disso.

ya, ja sei quem és... :)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

pois, lembro... já procurei muitas vezes por 1 fato assim e não encontrei, e tu tens um :/ lol

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

vamo-nos deixar de off topics, mandie-te uma pm com o meu mail do msn se kiseres, continuamos la com a conversa...

para o resto, agradecia que me tentassem ajudar, so me falta que com o sscanf() consiga ler espaços tb para uma string, ja tentei com%[] mas não funciona, no entanto se fizer tipo %[^_], já funciona, apanha tudo, menos, claro está, o underscore. mas eu queri todos mesmo...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora