Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

polska

fgets não lê

Mensagens Recomendadas

polska

Boas pessoal, estava a fazer um programa quando dei com um problema que não consegui resolver.. O fgets não lê nenhuma vez, é simplesmente passado a frente, alguém me pode explicar porquê?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void minusculas(char * ptr)
{
   int i = 0;
   while(ptr[i] != '\0')
   {
       if(ptr[i] >= 'A' && ptr[i] <= 'Z')
           ptr[i] = ptr[i] + ('a'-'A'); //ou += 32
       i++;
   }
}

int main()
{
   int x, x1, i, j;
   char chaves[20][101], frase[101], *tokens;

   scanf("%d", &x);
   for(i=0; i<x; i++)
   {
       scanf("%s", chaves[i]);
       minusculas(chaves[i]);
   }


   scanf("%d", &x1);
   for(i=0; i<x1; i++)
   {
       fgets(frase, sizeof(frase[0]), stdin);
   }

   return 0;
}


Corrige um sábio e ele mais sábio ficará. Corrige um ignorante e um inimigo ganharás.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
HappyHippyHippo

ficou "lixo" dos scanf's anteriores.

limpa o buffer de leitura com a linha:

while (getchar() != '\n');

Editado por HappyHippyHippo

IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
polska

ficou "lixo" dos scanf's anteriores.

limpa o buffer de leitura com a linha:

while (getchar() != '\n');

Eu experimentei mas não funcionou...

Não mistures fgets() com scanf().

Não quero usar o gets.. Mas também não posso ler int's com o fgets certo?

Editado por polska

Corrige um sábio e ele mais sábio ficará. Corrige um ignorante e um inimigo ganharás.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
HappyHippyHippo

ler int com fgets:

char buffer[256];
int value;

fgets(buffer, 256, stdin); // ler do buffer do stream de entrada para um buffer de memória
sscanf(buffer, "%d", &value); // interpretar do buffer de memória o inteiro que pretendes

ps:

já agora, o segundo elemento do fgets é do tamanho do buffer

o que tu tens não faz sentido:

fgets(frase,             // ler para frase
     sizeof(frase[0]),  // frase[0] == char => sizeof (frase[0]) == 1 byte
     stdin);

Editado por HappyHippyHippo
  • Voto 1

IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
mogers

Eu concordo com o Pmg que é melhor não misturares scanf com fgets.

Mas se tiveres a fazer algo simples como esse programa, uma coisa que podes fazer é

// o fgets não funcionava porque o buffer de entrada continha o '\n' depois de inserir o número.
scanf("%d\n", &x1);    // o '\n' vai fazer com que o scanf consuma o newline se existir
for(i=0; i<x1; i++)
   fgets(frase, 100, stdin);

Como disse, é preferivel evitar isto porque o scanf vai limpar todos os newlines consecutivos. Exemplo: se tiveres a ler de um ficheiro do género

4



string 4

o scanf vai ignorar as linhas em branco a seguir ao número e o 1º fgets no ciclo lê a "string 4" em vez de ler a primeira linha em branco.

Já agora, se a função minusculas recebe um ponteiro, usa-o à vontade sem indices:

void minusculas(char* ptr)
{
   while (*ptr) // equivalente ao k tinhas ptr[i] != '\0' ou ptr[i] != 0
   {
       if (*ptr >= 'A' && *ptr <= 'Z')
           *ptr = *ptr - 'A' + 'a';
       ptr++;
   }
}

  • Voto 1

"What we do for ourselves dies with us. What we do for others and the world, remains and is immortal.", Albert Pine

Blog pessoal : contém alguns puzzles, algoritmos e problemas para se resolver com programação.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
polska

ler int com fgets:

char buffer[256];
int value;

fgets(buffer, 256, stdin); // ler do buffer do stream de entrada para um buffer de memória
sscanf(buffer, "%d", &value); // interpretar do buffer de memória o inteiro que pretendes

ps:

já agora, o segundo elemento do fgets é do tamanho do buffer

o que tu tens não faz sentido:

fgets(frase,			 // ler para frase
  sizeof(frase[0]),  // frase[0] == char => sizeof (frase[0]) == 1 byte
  stdin);

tens razão, não faz sentido nenhum ahah :D ...

fgets(frase, 101, stdin);
   sscanf(frase, "%d", &x);
   for(i=0; i<x; i++)
   {
    scanf("%s", chaves[i]);
    minusculas(chaves[i]);
   }

   fgets(frase, 101, stdin);
   sscanf(frase, "%d", &x1);

   for(i=0; i<x1; i++)
   {
    fgets(frase, 101, stdin);
    minusculas(frase);

    for(j=0; j<x; j++)
    {
	    if(strcmp(chaves[j], frase) == 0)
		    count[j]++;
    }
   }

Ao correr, eu leio por exemplo 3 strings (x), mas depois a leitura do x1 passa á frente e vai logo ler a "frase" .. Eu segui com breakpoints e ao dar por exemplo 3 ao valor x, o ciclo for de 0 a < x não parava.. Isto confundiu-me todo, primeiro não está a funcionar direito, depois a execução normal sem ser pelo debug é diferente ... :D

Eu concordo com o Pmg que é melhor não misturares scanf com fgets.

Mas se tiveres a fazer algo simples como esse programa, uma coisa que podes fazer é

// o fgets não funcionava porque o buffer de entrada continha o '\n' depois de inserir o número.
scanf("%d\n", &x1);	// o '\n' vai fazer com que o scanf consuma o newline se existir
for(i=0; i<x1; i++)
fgets(frase, 100, stdin);

Como disse, é preferivel evitar isto porque o scanf vai limpar todos os newlines consecutivos. Exemplo: se tiveres a ler de um ficheiro do género

4



string 4

o scanf vai ignorar as linhas em branco a seguir ao número e o 1º fgets no ciclo lê a "string 4" em vez de ler a primeira linha em branco.

Já agora, se a função minusculas recebe um ponteiro, usa-o à vontade sem indices:

void minusculas(char* ptr)
{
while (*ptr) // equivalente ao k tinhas ptr[i] != '\0' ou ptr[i] != 0
{
	if (*ptr >= 'A' && *ptr <= 'Z')
		*ptr = *ptr - 'A' + 'a';
	ptr++;
}
}

O scanf com '\n' não funcionou :s

Eu por acaso ainda parei um bocado a pensar antes de usar os indicies, mas acabei por usar mesmo xD ..

Editado por polska

Corrige um sábio e ele mais sábio ficará. Corrige um ignorante e um inimigo ganharás.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
HappyHippyHippo
fgets(frase, 101, stdin);
   sscanf(frase, "%d", &x);
   for(i=0; i<x; i++)
   {
           scanf("%s", chaves[i]);    // <------------ falta este
           while (getchar() != '\n'); // <------------ limpar o buffer de leitura
           minusculas(chaves[i]);
   }

   fgets(frase, 101, stdin);
   sscanf(frase, "%d", &x1);

   for(i=0; i<x1; i++)
   {
           fgets(frase, 101, stdin);
           minusculas(frase);

           for(j=0; j<x; j++)
           {
                   if(strcmp(chaves[j], frase) == 0)
                           count[j]++;
           }
   }


IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
polska

fgets(frase, 101, stdin);
sscanf(frase, "%d", &x);
for(i=0; i<x; i++)
{
		scanf("%s", chaves[i]);	// <------------ falta este
		while (getchar() != '\n'); // <------------ limpar o buffer de leitura
		minusculas(chaves[i]);
}

fgets(frase, 101, stdin);
sscanf(frase, "%d", &x1);

for(i=0; i<x1; i++)
{
		fgets(frase, 101, stdin);
		minusculas(frase);

		for(j=0; j<x; j++)
		{
				if(strcmp(chaves[j], frase) == 0)
						count[j]++;
		}
}

Obrigado :)


Corrige um sábio e ele mais sábio ficará. Corrige um ignorante e um inimigo ganharás.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pmg

O scanf com '\n' não funcionou :s

Pois nao.

O "%d\n" no scanf() o que faz é

1) tratar a parte "%d"

1.1) opcionalmente ignorar espacos em branco (faz parte da definicao do %d)

1.2) 'apanhar' um numero inteiro (opcional + ou -, digitos)

2) tratar a parte "\n"

2.1) ignorar espacos em branco

3) terminar

Se introduzires "<ESPACO><4><2><ENTER><ESPACO><ENTER><ENTER><ENTER><ENTER><ENTER><ENTER><f><o><o>" em 1.1) o primeiro <ESPACO> é ignorado; em 1.2) o <4><2> é apanhado; em 2.1) o primeiro <ENTER>, o segundo <ESAPCO>, e or <ENTER>s todos a seguir sao ignorados; em 3) o 'f' ja nem pode ser ignorado nem apanhado por isso o scanf() termina (deixando o <f> e as letras seguintes no buffer prontos para a proxima leitura)

Se nao tivesses escrito o <f><o><o> o scanf() estava ainda no modo de esperar por qualquer coisa para saber se havia de ignora-la ou nao. Nao quer dizer que nao funcionou (mais ou menos); o que aconteceu foi que nao recebeu sinal para terminar.

Editado por pmg
  • Voto 1

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
mogers

O scanf com '\n' não funcionou :s

Em que input é que não funcionou? Como disse, serve para coisas simples e se o input for "bem comportado".


"What we do for ourselves dies with us. What we do for others and the world, remains and is immortal.", Albert Pine

Blog pessoal : contém alguns puzzles, algoritmos e problemas para se resolver com programação.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
polska

Em que input é que não funcionou? Como disse, serve para coisas simples e se o input for "bem comportado".

6

palavra1

palavra2

palavra3

palavra4

palavra5

palavra6

3

exemplo frase 1

exemplo frase 2

exemplo frase 3

(não me lembro das palavras chave nem das frases, mas o input que me lembro era com essa estrutura..)


Corrige um sábio e ele mais sábio ficará. Corrige um ignorante e um inimigo ganharás.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
mogers

int main() {
char chaves[50][100], frases[50][100];
int i, nc, nf;
scanf("%d\n", &nc);
for (i = 0 ; i < nc ; i++) {
	fgets(chaves[i], 100, stdin);  // fgets coloca o \n na string
	printf("%d: %s", i, chaves[i]);
}
scanf("%d\n", &nf);
for (i = 0 ; i < nf ; i++) {
	fgets(frases[i], 100, stdin);
	printf("%d: %s", i, frases[i]);
}
return 0;
}

output

0: palavra1

1: palavra2

2: palavra3

3: palavra4

4: palavra5

5: palavra6

0: exemplo frase 1

1: exemplo frase 2

2: exemplo frase 3


"What we do for ourselves dies with us. What we do for others and the world, remains and is immortal.", Albert Pine

Blog pessoal : contém alguns puzzles, algoritmos e problemas para se resolver com programação.

Partilhar esta mensagem


Ligação 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

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.