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

x3minater

Leitura de Ficheiro - "enquanto encontrar \n"

15 mensagens neste tópico

Boas,

to aqui com um problema na leitura de um ficheiro... o meu objectivo é ler uns certos dados que estão num ficheiro do estilo:

Nome: Justiniana Albertina
Telefone: 99 120 23 30

Nome: Justino Felizberto
Telefone: 09 909 09 90

...

No entanto os dados podem estar separados por um qualquer numero de "enters" (\n), o meu problema e passar por esses \n ate encontra alguma coisa diferente de \n.

como eu to a fzr é assim:

main()

bla bla bla

while(fgets(linha, 200, fp) != NULL){

sscanf(linha," %c", &x);

if(x != '\n'){

(le os valores)
}

}

posso fazer assim ou tenho de usar strcmp() ? ou outra maneira de fazer (igualmente simples)?

Fikem bem, obrigado pela ajuda desde ja

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Em vez de testares o x (que é sempre != '\n'), testa o sscanf()

int main(void) {
    /* bla bla bla */
    while(fgets(linha, 200, fp) != NULL) {
        if(sscanf(linha," %c", &x) == 1) {
            /* (le os valores) */
        }
    }
    return 0;
}

Nunca uses scanf() sem testar o valor devolvido!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Em vez de testares o x (que é sempre != '\n'), testa o sscanf()

int main(void) {
    /* bla bla bla */
    while(fgets(linha, 200, fp) != NULL) {
        if(sscanf(linha," %c", &x) == 1) {
            /* (le os valores) */
        }
    }
    return 0;
}

Nunca uses scanf() sem testar o valor devolvido!

sim isso de ver o retorno do sscanf vejo sempre, n pus aki pk n achei relevante

mas e se eu quiser ler uma coisa que tmb se ja apenas um char numa linha do estilo:


G
ew 31 
re dfr



t5 
d

ele vai-me retornar 2 depois de ler a linha so com o G? (g + \n)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

>> if (sscanf(linha, " %c", &x) == 1)

mas e se eu quiser ler uma coisa que tmb se ja apenas um char numa linha do estilo:

[...]

ele vai-me retornar 2 depois de ler a linha so com o G? (g + \n)

Não. O scanf() devolve o número de "assignments" que fez (ou EOF em erro ou fim de ficheiro).

Neste caso, como só tem uma variável, ele devolve ou 0 ou 1:

Se não conseguir fazer o "assignment" devolve 0 e não altera o valor anterior de x

val = sscanf("\n\n\n\n", " %c", &x);
/* val é igual a 0 */ }

Se conseguir, devolve 1 e mete 'N' na variável x

val = sscanf("\n\n\n\n\nNome: Justiniana Albertina", " %c", &x);
/* val é igual a 1 */ }

Outro exemplo, com mais valores:

Supoe que estavas a ler linhas com dois valores "flotaing point" cada uma

double x, y;
val = sscanf("12,34 56.78\n", "%lf%lf", &x, &y);
if (val != 2) { /* ERRO */ }

Repara que neste exemplo está uma virgula onde devia estar um ponto (12,34).

Depois do scanf, x vai ter 12 e y vai ter o que tinha antes.

Se, em vez duma string literal tivesse a ler dum stream, o stream ficava a "apontar" para a virgula.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

ok, ja consegui fazer.  :P

Entao e se eu quiser ler apenas 2 valores duma linha e a linha tiver mais que 2...  n posso usar o sscanf pa ver isso?

Fikem bem

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
se eu quiser ler apenas 2 valores duma linha e a linha tiver mais que 2...  n posso usar o sscanf pa ver isso?

Podes!

E o que é que fazes aos valores depois do segundo?

Para o sscanf (e o scanf) não interessa nada o número de linhas do input porque eles ignoram os espaços em branco e o ENTER, o TAB, o ESPAÇO e outros caracteres (dependendo do locale) são espaços em branco :P

Explica bem o que queres, com exemplos das linhas e dos dados que queres lá ir buscar, e do código que já escreveste.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Podes!

E o que é que fazes aos valores depois do segundo?

Para o sscanf (e o scanf) não interessa nada o número de linhas do input porque eles ignoram os espaços em branco e o ENTER, o TAB, o ESPAÇO e outros caracteres (dependendo do locale) são espaços em branco :P

Explica bem o que queres, com exemplos das linhas e dos dados que queres lá ir buscar, e do código que já escreveste.

Aos valores a mais nao vou fazer nada, apenas fazer um printf a dizer que tem valores a mais.

ex:

Albertina    999090909    34

Esse 34 n vai servir pa nada, apenas tá la a mais e eu teria de dizer que essa linha tem um erro.

como é que eu fazia algo desse genero?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Lês 3 valores com o scanf; mas esperas só 2 :cheesygrin:

Se o scanf fizer 3 assignments e porque a linha tem erro

int n;
char nome[10];
int x;
char dummy[2];
/* ... */
n = sscanf(linha, "%9s%d%1s", nome, &x, dummy);
if (n == 2) /* all ok */;
else /* erro */;

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Lês 3 valores com o scanf; mas esperas só 2 :D

Se o scanf fizer 3 assignments e porque a linha tem erro

int n;
char nome[10];
int x;
char dummy[2];
/* ... */
n = sscanf(linha, "%9s%d%1s", nome, &x, dummy);
if (n == 2) /* all ok */;
else /* erro */;

lol, desculpa, não me espliquei bem :cheesygrin:

É assim, na linha é suposto tarem 2 valores. Mas, se tiverem lá mais 1, ou mais 3 ou mais 50 (não sei quantos mais valores podem lá tar) akilo dá uma mensagem de erro!

por isso tinha de fazer:

n = sscanf(linha, "%9s%d", nome, &x,);
if (n == 2) /* all ok */;
else /* erro */;

mas isso n faz nada se tiver elementos a mais...so se tiver de menos =\

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Compara lá o que eu escrevi com o que tu escreveste :cheesygrin:

n = sscanf(linha, "%9s%d%1s", nome, &x, dummy);
n = sscanf(linha, "%9s%d", nome, &x,);

Sem contar com a virgula a mais na tua linha (que deve ser erro do copy/paste) eu tenho 3 variáveis no sscanf e tu tens 2.

No meu código, o programa vai para a parte do erro (o else) quando n tem 0, 1, ou 3; no teu código n só pode ser 0 ou 1.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

No meu código, o programa vai para a parte do erro (o else) quando n tem 0, 1, ou 3; no teu código n só pode ser 0 ou 1.

exactamente. Mas agora, se eu quiser verificar se a linha tem (por exemplo) 4 elementos? Como eu disse em cima:

Mas, se tiverem lá mais 1, ou mais 3 ou mais 50 (não sei quantos mais valores podem lá tar) do que supostamente deveria tar, akilo dá uma mensagem de erro!

Porque o que eu fiz, como tu disseste, so vai po else se for 0 ou 1... eu queria que fosse pa la sempre que fosse != 2... mas fazendo:

n = sscanf(linha, "%9s%d", nome, &x);
if (n != 2) /* erro */;
else /* all ok */;

só faz a mesma coisa que quando tem valores a menos (0 e 1) :s

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
n = sscanf("Joaquina\n", "%9s%d%1s", nome, &x, dummy); /* n == 1 */
n = sscanf("Joaquina 42\n", "%9s%d%1s", nome, &x, dummy); /* n == 2 */
n = sscanf("Joaquina 42 65\n", "%9s%d%1s", nome, &x, dummy); /* n == 3; dummy == "6" */
n = sscanf("Joaquina 42 muito mais valores aqui\n", "%9s%d%1s", nome, &x, dummy); /* n == 3; dummy == "m" */

n = sscanf("Joaquina\n", "%9s%d", nome, &x); /* n == 1 */
n = sscanf("Joaquina 42\n", "%9s%d", nome, &x); /* n == 2 */
n = sscanf("Joaquina 42 65\n", "%9s%d", nome, &x); /* n == 2 */
n = sscanf("Joaquina 42 muito mais valores aqui\n", "%9s%d", nome, &x); /* n == 2 */

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

n = sscanf("Joaquina\n", "%9s%d%1s", nome, &x, dummy); /* n == 1 */
n = sscanf("Joaquina 42\n", "%9s%d%1s", nome, &x, dummy); /* n == 2 */
n = sscanf("Joaquina 42 65\n", "%9s%d%1s", nome, &x, dummy); /* n == 3; dummy == "6" */
n = sscanf("Joaquina 42 muito mais valores aqui\n", "%9s%d%1s", nome, &x, dummy); /* n == 3; dummy == "m" */

n = sscanf("Joaquina\n", "%9s%d", nome, &x); /* n == 1 */
n = sscanf("Joaquina 42\n", "%9s%d", nome, &x); /* n == 2 */
n = sscanf("Joaquina 42 65\n", "%9s%d", nome, &x); /* n == 2 */
n = sscanf("Joaquina 42 muito mais valores aqui\n", "%9s%d", nome, &x); /* n == 2 */

:-[

Não tava a preceber lol

Agora ja funciona  :D muito obrigado!

PS: só uma cena, o que é esse %ls? A mim deu-me warning a dizer que n estava definido esse formato  :confused:...

PS2: como o dummy é um char [2] não há o risco de começar a escrever em memoria não declarada?  (stupid question probably lol)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

lol

não é ls (com L minuscúlo), é 1s (dígito um) :(

e como dummy está declarado como char[2], tem espaço para um caracter "normal" e o '\0' para "terminar" a string. Com o "%1s" (dígito um) o scanf nunca vai escrever nada em memória que não pertença a dummy.

PS. Mas este método de leitura de valores é fraquito. Se os valores estão minimamente estruturados (se são ficheiros criados por outros programas) pode ser usado, mas se os valores dependerem muito do utilizador final, talvez seja melhor fazer um "parser".

Por exemplo a Joaquina (ou lá que nome era) já teve o número de telefone com espaços

Nome: Justiniana Albertina

Telefone: 99 120 23 30

Outra pessoa podia escrever a Justiniana como

Nome: Justiniana Albertina

Telefone: 991 202 330

onde o Telefone agora tem 3 grupos numéricos em vez de 4 no exemplo anterior.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

lol

não é ls (com L minuscúlo), é 1s (dígito um) :)

e como dummy está declarado como char[2], tem espaço para um caracter "normal" e o '\0' para "terminar" a string. Com o "%1s" (dígito um) o scanf nunca vai escrever nada em memória que não pertença a dummy.

:(

lol, deve ser por tar a ler isto no Ubuntu  :P

PS. Mas este método de leitura de valores é fraquito. Se os valores estão minimamente estruturados (se são ficheiros criados por outros programas) pode ser usado, mas se os valores dependerem muito do utilizador final, talvez seja melhor fazer um "parser".

Por exemplo a Joaquina (ou lá que nome era) já teve o número de telefone com espaços

Outra pessoa podia escrever a Justiniana comoonde o Telefone agora tem 3 grupos numéricos em vez de 4 no exemplo anterior.

No meu caso não iria ser um problema (foi so um exemplo que dei).

Obrigadao pela ajuda  :thumbsup:

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