Jump to content

Ler uma string formatada usando sscanf


Recommended Posts

Posted

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 🙂

Posted

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[]

Posted

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

Posted

@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.

Posted

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.

Posted

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...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.