Ir para o conteúdo
waza

Limpar buffer do stdin

Mensagens Recomendadas

waza

Boas pessoal,

Bem, eu tenho usado sempre o rewind, pois o fflush não faz nada.

Faço bem em usar o rewind, ou será melhor adoptar outro método?

Obrigado ;)

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pmg

Não tens garantia de que o stream stdin seja "seekable". O rewind só pode ser usado em streams que são seekable. De acordo com a informação sobre fseek() do POSIX-1.2008 (agora não posso verificar o Standard do C) chamar fseek() (ou rewind()) com um stream que não é seekable, tem um comportamento definido pela implementação --- ou seja, não faz sempre a mesma coisa de compilador para compilador, de SO para SO, ...

A melhor maneira de lidar com dados vindos do utilizador é ler os dados com fgets() e depois tratá-los consoante as necessidades.


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
HappyHippyHippo

solução portável:

while (getchar() != '\n') /* void */;

podos fazer uma macro para simplificar:

#define CLEAR_STDIN (while (getchar() != '\n') /* void */;)

// ...

scanf("%d", &i);
CLEAR_STDIN;


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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pmg

solução portável:

while (getchar() != '\n') /* void */;

O grande problema desta solução é o EOF ...

Editado por pmg

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
pwseo

A solução do HappyHippyHippo tem outro problema, penso eu: se não existir nada no buffer, então a getchar() vai bloquear o programa até que haja novo input, não é? Para quem está a utilizar scanf() não tem problema porque habitualmente fica lá o '\n', mas para quem utilize fgets() e queira descartar um hipotético excesso de input penso que não dá.

Uma solução passaria por enfiar um caracter no stdin de forma a evitar o caso em que não há nada para ler e só depois correr o loop que limpa a stream:

void discard_input (void)
{
   int c;
   ungetc('a', stdin);
   while (c = getchar(), c != '\n' && c != EOF);
}

Que acham? (falta verificar erros da ungetc(), mas à partida funciona)

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
HappyHippyHippo

Que acham? (falta verificar erros da ungetc(), mas à partida funciona)

parece uma boa solução, mas quem usa fgets não anda a limpar a entrada :D


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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pwseo

parece uma boa solução, mas quem usa fgets não anda a limpar a entrada :D

Sim, é verdade que tipicamente isso não acontece, mas imagina que alguém, por algum motivo estranho, excede o teu buffer de 1024 caracteres -- o excesso não é lido pela fgets(), ficando no stdin. Imagina então que de seguida o teu programa pergunta se o utilizador deseja rm -rf / e o primeiro caracter pendurado no stdin é 'y' :P

De qualquer modo, isto também pode ser contornado usando algo como ncurses ou semelhante para interactivamente limitar os dados introduzidos pelo utilizador, mas a função que fiz é mais simples que incluir uma lib inteira (e é portável).

Editado por pwseo

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pmg

Com o fgets() convem que te certifiques se o input foi completamente lido. Para isso verifica se o ultimo caracter foi um '\n'.

Se foi um '\n' leste o input todo.

Se nao foi um '\n' ou ha mais input ou chegaste a EOF 'prematuro'. Uma coisa simples de fazer (mas nao necessariamente correcta) é ignorar os caracteres extra

while (fgets(buffer, sizeof buffer, stdin)) {
   len = strlen(buffer); /* len nao pode ser 0 com stdin's de texto */
   if (buffer[len - 1] != '\n') {
       /* leitura incompleta ou EOF prematuro */
       if (feof(stdin)) {
           /* EOF prematuro */;
       } else {
           int ch;
           while ((ch = getchar()) != '\n' && ch != EOF) /* void */; /* ignora caracteres extra */
           if (ch == EOF) /* EOF prematuro */;
       }
   }
   /* buffer tem os primeiros caracters do input, pode nao ter '\n' */
}

  • 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

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.