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

polska

fgets não lê

Recommended Posts

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.

Share this post


Link to post
Share on other sites
HappyHippyHippo

ficou "lixo" dos scanf's anteriores.

limpa o buffer de leitura com a linha:

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

Edited by HappyHippyHippo

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

Share this post


Link to post
Share on other sites
pmg

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


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!

Share this post


Link to post
Share on other 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?

Edited by polska

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

Share this post


Link to post
Share on other 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);

Edited by HappyHippyHippo
  • Vote 1

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

Share this post


Link to post
Share on other 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++;
   }
}

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

Share this post


Link to post
Share on other 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 ..

Edited by polska

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

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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.

Edited by pmg
  • Vote 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!

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other sites

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

×

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.