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

Hipnoted

fflush(stdin) necessário?

15 mensagens neste tópico

Boas. É assim, eu considero-me um programador de C com bastantes conhecimentos mas há certos aspectos que tenho algumas dúvidas.

Já vi em alguns tópicos e colegas meus também a utilizam, a instrução fflush(stdin), que serve para limpar o buffer do teclado.

Eu nunca uso essa instrução e acho que são instruções dessas que fazem o código ficar muito extenso. Nunca tive qualquer problema nos programas que fiz...

Mas gostava de seber a vossa opinião, se realmente essa instrução vale a pena e as vantagens/desvantagens da mesma.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

A questão nem deve ser se vale a pena, mas sim se funciona. Pelas experiências que tenho feito, essa função não funciona em algumas versões do Linux nem em Mac OS X. No entanto já ouvi várias pessoas dizerem que funciona em Windows.

Mas se funcionasse sempre, por vezes era útil. Assim, normalmente recorro a um ciclo para limpar o buffer.

EDIT:

int fflush(FILE *stream)

On an output stream, fflush causes any buffered but unwritten data to be written; on an input stream, the effect is undefined. It returns EOF for a write error, and zero otherwise. fflush(NULL) flushes all output streams.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não fazia ideia que não funcionava em Linux (vou testar daqui a pouco, estou em Windows agora), eu recorro a ela por vezes.

No fundo resolve-te estes casos:

Pretendes ler um inteiro, e uma frase na linha seguinte.

Se fizeres simplesmente um scanf("%d",&i) e um fgets(), o fgets vai "apanhar" somente o '\n'. Com o fflush entre os dois limpas o resto da linha (após o inteiro).

A tua pergunta foi "se vale a pena"? Sei lá. Faz aquilo. Há muitas funções que não uso porque lhes dou a volta. É uma questão de necessidade, não programo a pensar "vou resolver isto com um fflush".

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

fflush é uma função muito util, mas normalmente uso-a para limpar o buffer de saida, e não o de entrada. Evita coisas como colocar um "\n" no fim do printf para mudar a linha. isso sim é muito má politica.

Quanto ao funcionar em Linux, nunca tive problemas... tenho de investigar isso...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não parece existir qualquer tipo de erro associado ao uso da função fflush em linux, pelo menos pelas mailling list que consultei muito por alto, e as man pages da funcção também não referem nada, tendo em conta que é uma função bastante velha. se alguém tem erros convém verificar a variável 'errno' e as man pages da função 'write' para ver o que aconteceu.

Agora quanto a limpar o buffer de entrada, convém saber que o sistema operativo tem sempre mais que fazer que atender aos pedidos dos programas ;), e normalmente esses tipo de pedidos são lançados para o buffer e atendidos mais tarde, o que quer dizer que se fizerem duas leituras seguidas pode ocorrer que a segunda leitura pode obter o valor introduzido na primeira.

Isso acontece em várias funções, tais como a função malloc que é uma função optimista. Normalmente dão origem a erros muito dificeis de detectar, resumindo aconselho o uso da função fflush para a leitura, e para tudo o resto.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não parece existir qualquer tipo de erro associado ao uso da função fflush em linux, pelo menos pelas mailling list que consultei muito por alto, e as man pages da funcção também não referem nada, tendo em conta que é uma função bastante velha. se alguém tem erros convém verificar a variável 'errno' e as man pages da função 'write' para ver o que aconteceu.

Eu não disse que existia um erro na função. O que eu disse é que essa função não faz aquilo que vocês dizem que faz.

If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.

If stream is a null pointer, the fflush function performs this flushing action on all streams for which the behavior is defined above.

A função fflush destina-se a manipular output streams, e quando lhe dão uma input stream o seu comportamente é indefinido. Aliás, no Mac OS X existe a função fpurge que se destina precisamente a limpar um buffer. Se a fflush fizesse isso, por que razão existiria outra função? Não há nada que nos garanta que a função fflush vá funcionar, pois os standards não obrigam a que tal aconteça.

A citação que eu coloquei foi retirada do seguinte documento: http://www.nirvani.net/docs/ansi_c.pdf

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Tens razão em relação aos standards, mas o habito é uma coisa muito má, e tenho o habito de me referir mais às man pages do que aos documentos standard uma vez que são essas man pages que definem o comportamento da função, é claro que é só para esse sistema/implementação.

Mas também como disse antes normalmente uso a função para limpar o buffer se saida, que é uma output stream. Bem neste caso estou sem argumentos ;), sempre usei a função fflush com o buffer de entrada quando as leituras estavam a dar problemas e isso resolvia os problemas e ajudava a fazer o debug.

Peace.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Normalmente o acrescentar de um "getchar();" antes da proxima leitura resolve os problemas todos.

Salvo, é claro, alguns casos especiais, como terem ficado vários caracteres por ler mas isso não é normal acontecer.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

A definição parece mudar conforme a fonte:

http://www.cplusplus.com/ref/cstdio/fflush.html - Em streams de input, limpa o conteúdo do buffer; em streams de output escreve o conteúdo do buffer no destino.

http://man.he.net/man3/fflush - distingue entre o fflush e o fpurge: dizem que o fflush só pode ser usado em outputs e que o fpurge pode ser usado em ambos, tendo as funções fins diferentes. Parece ser esta a definição ANSI C e ISO C.

EDIT: (muito tempo depois) depende do compilador :D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

olha eu acho que funciona sim é tao pequena... usei ela no meu primeiro programa em c  na faculade , fica mais organizado eu acho util fflush(stdin)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ena mais arqueologia :)

O que passei a usar e que creio funcionar sempre é o código:

char lixo = '\0';

//....
//depois de uma leitura limpar o buffer
while((lixo = getchar()) != '\n' && lixo != EOF);

Tipicamente tenho esse código em funções de leitura e evito estar a escrever isso constantemente, uso apenas as funções de leitura.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Podes sempre adicionar um espaço no teu scanf:

Exemplo:

char b;

scanf(" %c",&b);

O espaço que tens entre " e %c faz o mesmo que o fflush mas poupas umas linhas de código e tens compatibilidade em Linux e Windows :)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Podes sempre adicionar um espaço no teu scanf:

Exemplo:

char b;

scanf(" %c",&b);

O espaço que tens entre " e %c faz  o mesmo que o fflush mas poupas umas linhas de código e tens compatibilidade em Linux e Windows :)

Isso só funciona para caracteres como o \n, espaço, \t e afins. Não é propriamente uma solução para limpar o buffer de entrada.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

em windows uso o fflush(stdin);

e em linux uso __fpurge(stdin);

e também uso o tal espaço entre " e % do scanf....

e assim nunca tenho problemas com o buffer...

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