Limpando buffer de entrada: Como fazer corretamente? [RESOLVIDO]

1. Limpando buffer de entrada: Como fazer corretamente? [RESOLVIDO]

rob
robgeek

(usa Debian)

Enviado em 22/10/2014 - 21:51h

Boa noite!

Preciso fazer um programa que fica lendo coisas até que seja digitado a letra N(não). Para ler o caracter, usei a função getchar o problema é que o programa está se comportando de maneira estranha.
#include <stdio.h>

int main( )
{
char x = 'S';

while(x != 'N') {
fflush( stdin );
x = getchar( );
x = toupper( x );

if(x == 'S') {
printf("Valor valido.\n");//Aqui será o resto do código.
}
else{
printf("Valor invalido, tente novamente.\n");
}
}

printf("Fim!\n");

return 0;
}


Saída de teste no terminal:
rob@robgeek:~$ gcc -o teste trabalho.c
rob@robgeek:~$ ./teste
k
Valor invalido, tente novamente.
Valor invalido, tente novamente.
u
Valor invalido, tente novamente.
Valor invalido, tente novamente.
s
Valor valido.
Valor invalido, tente novamente.
s
Valor valido.
Valor invalido, tente novamente.
n
Valor invalido, tente novamente.
Fim!
rob@robgeek:~$


Por que ele está fazendo isso? Sei que tem a ver com o buffer, no entanto não consegui limpá-lo de forma correta. Este programa precisa rodar no Windows também.

Obrigado!


  


2. Re: Limpando buffer de entrada: Como fazer corretamente? [RESOLVIDO]

Thiago Henrique Hüpner
Thihup

(usa Manjaro Linux)

Enviado em 22/10/2014 - 22:18h

Amigo , olhe esse tópico :

http://www.vivaolinux.com.br/topico/C-C++/Qual-e-a-melhor-maneira-de-limpar-o-buffer/

Em resumo vc faria isso:


#include <stdio.h>
 
void limparBuffer(void){
 
   int c;
   while((c = getchar()) != '\n' && c != EOF);
 
}
 
int main(){
 
   int a,b,c;
    
   a = getchar();
   limparBuffer();
    
   b = getchar();
   limparBuffer();
    
   c = getchar();
   limparBuffer();   
    
   printf("%i\n%i\n%i\n",a,b,c);
    
   return 0;
}



Esse codigo roda em todas as plataformas (pelo que eu saiba).

E te recomendaria fazer um do{}while();

Pq vc vai ter que executar aqueles passos pelo menos uma vez,e o do{}while faz justamente isso.

Qualquer dúvida é só perguntar

Espero ter ajudado

[]'s

T+


3. Re: Limpando buffer de entrada: Como fazer corretamente? [RESOLVIDO]

rob
robgeek

(usa Debian)

Enviado em 22/10/2014 - 22:34h

Obrigado por responder, cara!
Você sabe me dizer por que com fflush() não funciona como esperado? Por que tem que ser do jeito que você sugeriu? Enfim, a diferença entre eles?


4. Re: Limpando buffer de entrada: Como fazer corretamente? [RESOLVIDO]

Thiago Henrique Hüpner
Thihup

(usa Manjaro Linux)

Enviado em 22/10/2014 - 22:39h

Amigo , quer ler como funciona ou quer ver um video ?
Hehe

Olha aki :

https://www.youtube.com/watch?v=W-X2_v4Oyx8

Aki é explicado pq não é legal usar o fflush()(Windows) ou o __purge() (Linux)

Espero ter ajudado

[]'s

T+


5. Re: Limpando buffer de entrada: Como fazer corretamente? [RESOLVIDO]

rob
robgeek

(usa Debian)

Enviado em 22/10/2014 - 22:59h

Vou olhar sim, cara.

Obrigado!


6. Re: Limpando buffer de entrada: Como fazer corretamente? [RESOLVIDO]

Thiago Henrique Hüpner
Thihup

(usa Manjaro Linux)

Enviado em 22/10/2014 - 23:05h

Se ajudei , marque a melhor resposta

Espero ter ajudado

[]'s

T+


7. Re: Limpando buffer de entrada: Como fazer corretamente? [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 23/10/2014 - 01:21h

Thihup escreveu:

Amigo , quer ler como funciona ou quer ver um video ?
Hehe

Olha aki :

https://www.youtube.com/watch?v=W-X2_v4Oyx8

Aki é explicado pq não é legal usar o fflush()(Windows) ou o __purge() (Linux)

Espero ter ajudado

[]'s

T+


Assisti ao vídeo. É interessante, mas recomendo cautela, porque o autor comete alguns erros e fala diversas coisas imprecisas. Deixei lá alguns comentários, e reproduzo alguns deles aqui porque se aplicam ao que foi dito ao longo da discussão.

Parabéns por ter indicado que fflush(stdin) é um abuso do padrão do C. Não é muita gente que entende isso -- por incrível que pareça.


getchar() devolve valor do tipo int, não do tipo char. Se você usar uma variável char para recebê-lo, pode tornar inviável distinguir entre o byte com valor 255 (ou -1, dado que o default do char na plataforma Intel é ser equivalente a signed char) e o marcador EOF (que é um inteiro com valor -1).


Quando se lê caráter-a-caráter, com getchar(), fgetc() ou mesmo scanf("%c"...), é errado considerar '\n' como lixo. “Lixo” geralmente é o que se tem quando, após ler alguma coisa com scanf(), tenta-se ler outra coisa com uma função que não pule espaços em branco (a biblioteca do C considera '\n' como espaço em branco). A maioria das pessoas não conhece realmente o comportamento de scanf(), que eu considero uma das funções mais complicadas da biblioteca padrão. É uma infelicidade que ela seja uma das primeiras coisas a serem mostradas, sem o devido cuidado, a novatos em C.


Sua função de “limpeza” tem (...) um problema: se o buffer já estiver limpo, você vai obrigar o usuário a gerar lixo que a função possa limpar, ou vai considerar como lixo possíveis dados que talvez devessem ser consumidos de modo útil pelo programa.


“Limpar lixo” é um problema porque a própria ideia de “lixo” é problemática. O padrão fala de streams (fluxos) de dados, e deliberadamente não impõe muitas restrições sobre que dados podem estar nesses fluxos. Fica a cargo de cada programa tratar devidamente os dados que recebe e dispor corretamente os dados que produz. E isso é bom, porque dá liberdade para que se consiga escrever um programa que trate qualquer tipo de dados. O custo, porém, dessa liberdade é a necessidade de saber bem o que se está fazendo.



8. Re: Limpando buffer de entrada: Como fazer corretamente? [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 23/10/2014 - 12:40h

A melhor forma que eu vislumbro de fazer o programa em questão é a seguinte.

#include <stdio.h>

int main(void) {
char x;
do {
/*
Note o espaço em branco na string de formatação de
scanf(), antes do ‘%c’. Ele é uma forma prevista no
padrão para limpar espaços em branco (incluindo fins
de linha) remanescentes no buffer de uma leitura an-
terior.
*/
if(scanf(" %c", &x)!=1){
fprintf(stderr, "Erro de leitura.\n");
exit(1);
}
/*
Neste ponto, pode haver espaços em branco após a
leitura do caráter não-branco. Outras futuras ope-
rações de leitura terão de adotar tratamento seme-
lhante de descarte.
*/
x=toupper(x);
if(x=='S') {
printf("Valor valido.\n");
/* Aqui será o resto do código. */
}
else{
printf("Valor invalido, tente novamente.\n");
/*
Nao faz muito sentido, né? Se for 'N",
não vai tentar novamente.
*/
}
} while(x!='N');
printf("Fim!\n");
return 0;
}







Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts