fflush(stdin);

13. Re: fflush(stdin);

Diego da Silva de Medeiros
diegotosco

(usa Slackware)

Enviado em 09/09/2006 - 08:43h

Voltando ao assunto de limpeza de buffers, existe alguma função que limpa o buffer de socket? Fiz um servidor de jogo da velha, e em algumas vezes é necessário mandar várias strings seguidas, mas não juntas numa só, pois elas possuem flags necessários à execução do programa.

Por falar em socket, vocês conhecem algum tutorial que tenha exemplos de usos das funções recv() e send? Ou algum script?

Muito obrigado desde já.


  


14. Sockets...

Enzo de Brito Ferber
EnzoFerber

(usa FreeBSD)

Enviado em 09/09/2006 - 10:16h

Cara, para 'limpar' o buffer de sockets, não existe uma função e sim uma ação: você tem que fechar o descritor e depois abrir denovo. Sobre enviar e receber com recv() e send() vai um pequeno fragmento de script:

int t;
int fd;
struct sockaddr_in servidor;
struct sockaddr_in cliente;
struct hostent *server;
char server_name[50];
char msg_rec[50];
char msg_env[50];
...
fd = socket(AF_INET, SOCK_STREAM, 0);
...
printf("Enderco do servidor: "); __fpurge(stdin);
scanf("%[^\n]", server_name);
server = gethostbyname(server_name);
... //faz uma checagem de erro aqui if(!server)...
servidor.sin_family = AF_INET;
servidor.sin_port = htons(65000);
servidor.sin_addr = *(struct in_addr*)server->h_addr;
memset(servidor.sin_zero, 0x0, 8);
connect(fd, (struct sockaddr*)&servidor, sizeof(struct sockaddr);
printf("Mensagem a enviar: "); __fpurge(stdin);
scanf("%[^\n]", msg_env);
send(fd, msg_env, strlen(msg_env), 0);
...
t = recv(fd, msg_rec, 50, 0);
msg_rec[t] = '{TTEXTO}';
...

Qualquer coisa me manda um email:
enzo@veloxmail.com.br

Espero ter ajudado,
Slackware_10


15. Grrrrrrrrrrrrrrrrr #!@*@*#

Bruno Moreira Guedes
__KERNEL__

(usa Arch Linux)

Enviado em 22/10/2007 - 15:00h

Vocês não sabem que raiva eu tenho e alguns professores mal informados de faculdades porcausa disso... E dos cadas da Microsoft que escreveram uma libc em desconformidade com os padrões.
Se vocês lerem as man pages do fflush, verão que a função dele é sincronizar o buffer de um stream de escrita com o arquivo do disco, sem o fechamento do file-descriptor do arquivo(ou seja, chamar realmente o write()).
No nosso amigo que segue pra caramba os padrões(Windows), o fflush meche também em buffers de streams de leitura. Ele simplesmente pula a linha caso o stream esteja no fim dela.

Exemplificando... Você tem o seguinte arquivo como stdin(sim, isso pode ser o que você digita):

|123 234\n
hahaha haq ha au ha uah uah\n
123 123\n

Considere o | como sendo a posição de leitura do stream. Quando você der um scanf("%d",ponteiroDeInt), ele vai ficar assim:
123| 234\n
hahaha haq ha au ha uah uah\n
123 123\n

Repetindo o processo do scanf com %d, ele ficará assim:
123 234|\n
hahaha haq ha au ha uah uah\n
123 123\n

Caso você desse um fgets ou um gets(pura ignorancia), ele vai pegar a linha atual(da posição de leitura, ilustrada por | nestr exemplo) até o seu fim(\n, incluindo o mesmo).
Ou seja, o resultado será um \n.

Agora vamos esquecer o fgets ou o gets acima, pois eles não foram executados ainda. Em bibliotecas padrão que tem conformidade com o C89 e o C99, o fflush nem tem porque ser usado no stdin, pois ele é um buffer de leitura apenas. Já no nosso amigo windows, que não respeita padrões, ele faz o seguinte com teu buffer de leitura:

123 234\n
|hahaha haq ha au ha uah uah\n
123 123\n

Por isso, se você der um fgets após um scanf/fflush(stdin) no windows, você vai ter o resultado desejado, no windows não.

Graças a esta porcaria do windows, eu perdi algumas noites de sono.
Resumindo: Não digam besteiras do tipo "fflush limpa o buffer do teclado". Nem na porcaria do windows ele faz isso, pois se você fizer o teste colocando um scanf, depois um fflush e depois outro scanf, e na entrada digitar "234 234", você vai ver que ele não vai parar pra te perguntar o segundo numero.
Mas graças a essa porcaria que se criou essa cultura de usar fflushs de maneira louca por aí, pois os professores burros leram que tem que usar fflush em algum livro de algum winuser retardado, e repetem pros alunos sempre sem sequer explicar as razões.

Agora, sobre a pergunta do amigo que perguntou sobre limpar o buffer do teclado... Bom, isso é algo bem relativo. Se você quer que a entrada tenha um valor por linha, usando o scanf, você PODE(e não deve, pois existem outras alternativas) fazer essa limpeza de buffer mesmo. Para fazer isso, em Linux com glibc você usa __fpurge, em BSD fpurge, e em outros sistemas você FICA NA MÃO PORQUE ISSO NÃO É PADRÃO.

Existem "workarounds" para contornar esta situação. Nunca pesquisei para saber se há um método melhor, talvez haja, se souberem me digam...
Exemplo(supondo que c seja um array de 50 chars a ser lido, e a seja um inteiro, e a entrada sera algo como "250\nhahaha hehehe hohoho\n"):

scanf("%d\n",&a);
fgets(c,50,stdin);
/** Aqui você terá problemas de compatibilidade com RWindows e Mac, porcausa do line separator deles que não é um simples \n*/
------------------ ou -----------------
scanf("%d",&a);
fgets(c,50,stdin);
fgets(c,50,stdin);
/** Aqui a coisa ta mais feia, mas este é realmente pra funcionar em todos os sistemas */

A idéia do amigo que falou de dar um getchar() é interessante, porém se o cara colocar um espaço depois do número(lembre-se, usuário faz tudo), já "[*****]" o programa.
Um método que também já usei, é criar uma função void pulaLinha();
Ex:

void pulaLinha(){
while(getchar()!='\n');
}

Mas eu particularmente prefiro não usar, considero uma gambiarra tremenda, hehehe... Mas lembre-se que é mais "garantido" que o fgets, pois não para se receber um NULL(contrabarra(\) zero(0))
Acho que isso é tudo pessoal, foi bom escrever pra mim desabafar... Já perdi uma noite porcausa dum código que tinha isso(fflush(stdin)), e funcionava no Windows e no Linux não... E eu estava pensando que o gets/fgets fossem as "chamadas despadronizadas" da libc do Windows.


16. Já foi respondido, mas...

Juliano Atanazio
julianometal

(usa Ubuntu)

Enviado em 22/03/2008 - 16:00h

A solução apresentada realmente funciona.
Porém, acho que não funcionaria no sistema inferior (o da M$).

Uma solução universal:

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


17. Re: fflush(stdin);

Stanley Sathler
stanley_sathler

(usa XUbuntu)

Enviado em 20/10/2009 - 13:17h

DiegoTosco, sei que já foi respondido, mas eis minha explicação:
-
Antes de mais nada, compile o seguinte source:
#include <stdio.h>
main(){
char ch1, ch2;
printf("Insira o primeiro caractere:\n");
scanf("%c" ,&ch1);
printf("Insira outro caractere:\n");
scanf("%c" ,&ch2);
printf("Caracteres: '%c' e '%c'\n" ,ch1 ,ch2);}
-
Note que, como resposta final, terá:
Caracteres: 'a' e ' ' (no caso, usei os caracteres a e b como exemplo)
-
Isso ocorre por que ? Simples. O uso do buffer do teclado faz com que o uso do <ENTER> seja indispensável para o processamento final do programa (quando inserimos os caracteres). Portanto, ao inserir o caractere "a" (primeiro scanf) é necessário o uso do <ENTER> para continuar o programa, porém o <ENTER> também é reconhecido como um caractere. Então, como o primeiro scanf só lê apenas um caractere (a), o segundo scanf vê que ainda há um caractere disponível no buffer e o utiliza (no caso, o <ENTER>).
-
Para resolvermos isso, temos duas formas:
A primeira, é o uso do fflush(stdin);, citada aqui como principal foco.
A segunda maneira, é o uso da tecla "espaço" antes do caractere "%c" no segundo scanf (" %c", &ch2)
Esse espaço é usado para que a função "scanf" ignore todos os espaços em branco, New Lines e Tabs que encontrar. Então, no nosso caso, a utilização do espaço foi necessária para que o scanf retire do buffer todos os separadores ('\n', '\t' e ' ') que encontrar
-
-
Essa explicação foi retirado do livro "Linguagem C", de Luis Damas. Resumi para um melhor aproveitamento do espaço e entendimento do usuário.


18. Re: fflush(stdin);

Naygno Barbosa Noia
Naygno

(usa Debian)

Enviado em 19/08/2010 - 11:10h

Nossa as funções

__fpurge(stdin);
getchar();

Me ajudaram muito!



19. Re: fflush(stdin);

Mikuiba
Mikuiba

(usa KUbuntu)

Enviado em 19/07/2011 - 11:29h

Neste programa não vejo a necessidade de limpar o buffer, pois vc só tem entradas numéricas, a limpeza dp buffer faz-se necessária quando vc tem entradar alfanumericas ou seja , entra com números e depois com letras e numeros novamente e assim sucessivamente, mexi no seu programa e acho que a finalidade é apenas armazenar um número em uma variável vejo como ficou:

#include <stdio.h>

int main()
{

int numero;

int oper=10;

while(oper != 0 )
{
printf("\nDigite um numero: ");
scanf("%f",&numero);
fflush(stdin);

oper--;
}
getch();
}

Está funcionando, espero ter ajudado !!


20. Re: fflush(stdin);

André
andrezc

(usa Debian)

Enviado em 19/07/2011 - 18:23h

Coveiro do ano.


21. limpando o buffer com C++

Tarcisio Praciano-Pereira
tarcisiopraciano

(usa Debian)

Enviado em 03/09/2013 - 00:59h

se for receber um caractere:

cin.get(w).get();

equivale ao fflush(stdin) usado em gcc.

Tarcisio


22. getchar();

Alex Camargo
alexcamargoweb

(usa Linux Mint)

Enviado em 11/02/2014 - 08:15h

Estava com o mesmo problema em um menu com o switch, resolvi colocando um getchar(); após o scanf.

Estou compilando no linux.

printf("\tMenu\n\n0)Sair\n\n1)Inserir\n\n2)Imprimir\n\nOpção: ");
scanf("%d", &escolha);
getchar(); //coloquei para limpar o buffer do teclado, por isso estava passando direto


23. Re: fflush(stdin);

Dantas
augustold

(usa Arch Linux)

Enviado em 18/02/2014 - 14:37h

Vou aproveitar que o colega ressuscitou o tópico e dizer que além do __fpurge(stdin) mencionado na primeira página dá pra usar o setbuf(stdin, NULL) que é da biblioteca stdio.h e funciona tanto em GNU/Linux como Windows.


24. Re: fflush(stdin);

euteste da silva
foxbit3r

(usa Solaris)

Enviado em 18/02/2014 - 16:16h

O __KERNEL__ disse tudo.

Vocês não sabem que raiva eu tenho e alguns professores mal informados de faculdades porcausa disso... E dos cadas da Microsoft que escreveram uma libc em desconformidade com os padrões.
Se vocês lerem as man pages do fflush, verão que a função dele é sincronizar o buffer de um stream de escrita com o arquivo do disco, sem o fechamento do file-descriptor do arquivo(ou seja, chamar realmente o write()).
No nosso amigo que segue pra caramba os padrões(Windows), o fflush meche também em buffers de streams de leitura. Ele simplesmente pula a linha caso o stream esteja no fim dela.

Exemplificando... Você tem o seguinte arquivo como stdin(sim, isso pode ser o que você digita):

|123 234\n
hahaha haq ha au ha uah uah\n
123 123\n

Considere o | como sendo a posição de leitura do stream. Quando você der um scanf("%d",ponteiroDeInt), ele vai ficar assim:
123| 234\n
hahaha haq ha au ha uah uah\n
123 123\n

Repetindo o processo do scanf com %d, ele ficará assim:
123 234|\n
hahaha haq ha au ha uah uah\n
123 123\n

Caso você desse um fgets ou um gets(pura ignorancia), ele vai pegar a linha atual(da posição de leitura, ilustrada por | nestr exemplo) até o seu fim(\n, incluindo o mesmo).
Ou seja, o resultado será um \n.

Agora vamos esquecer o fgets ou o gets acima, pois eles não foram executados ainda. Em bibliotecas padrão que tem conformidade com o C89 e o C99, o fflush nem tem porque ser usado no stdin, pois ele é um buffer de leitura apenas. Já no nosso amigo windows, que não respeita padrões, ele faz o seguinte com teu buffer de leitura:

123 234\n
|hahaha haq ha au ha uah uah\n
123 123\n

Por isso, se você der um fgets após um scanf/fflush(stdin) no windows, você vai ter o resultado desejado, no windows não.

Graças a esta porcaria do windows, eu perdi algumas noites de sono.
Resumindo: Não digam besteiras do tipo "fflush limpa o buffer do teclado". Nem na porcaria do windows ele faz isso, pois se você fizer o teste colocando um scanf, depois um fflush e depois outro scanf, e na entrada digitar "234 234", você vai ver que ele não vai parar pra te perguntar o segundo numero.
Mas graças a essa porcaria que se criou essa cultura de usar fflushs de maneira louca por aí, pois os professores burros leram que tem que usar fflush em algum livro de algum winuser retardado, e repetem pros alunos sempre sem sequer explicar as razões.

Agora, sobre a pergunta do amigo que perguntou sobre limpar o buffer do teclado... Bom, isso é algo bem relativo. Se você quer que a entrada tenha um valor por linha, usando o scanf, você PODE(e não deve, pois existem outras alternativas) fazer essa limpeza de buffer mesmo. Para fazer isso, em Linux com glibc você usa __fpurge, em BSD fpurge, e em outros sistemas você FICA NA MÃO PORQUE ISSO NÃO É PADRÃO.

Existem "workarounds" para contornar esta situação. Nunca pesquisei para saber se há um método melhor, talvez haja, se souberem me digam...
Exemplo(supondo que c seja um array de 50 chars a ser lido, e a seja um inteiro, e a entrada sera algo como "250\nhahaha hehehe hohoho\n"):

scanf("%d\n",&a);
fgets(c,50,stdin);
/** Aqui você terá problemas de compatibilidade com RWindows e Mac, porcausa do line separator deles que não é um simples \n*/
------------------ ou -----------------
scanf("%d",&a);
fgets(c,50,stdin);
fgets(c,50,stdin);
/** Aqui a coisa ta mais feia, mas este é realmente pra funcionar em todos os sistemas */

A idéia do amigo que falou de dar um getchar() é interessante, porém se o cara colocar um espaço depois do número(lembre-se, usuário faz tudo), já "[*****]" o programa.
Um método que também já usei, é criar uma função void pulaLinha();
Ex:

void pulaLinha(){
while(getchar()!='\n');
}

Mas eu particularmente prefiro não usar, considero uma gambiarra tremenda, hehehe... Mas lembre-se que é mais "garantido" que o fgets, pois não para se receber um NULL(contrabarra(\) zero(0))
Acho que isso é tudo pessoal, foi bom escrever pra mim desabafar... Já perdi uma noite porcausa dum código que tinha isso(fflush(stdin)), e funcionava no Windows e no Linux não... E eu estava pensando que o gets/fgets fossem as "chamadas despadronizadas" da libc do Windows.


Quem está com preguiça de ler esse texto vai continuar usando fflush(stdin), que não limpa porcaria nenhuma de buffer de teclado.
Basta ler o manual da função para ver a verdade.
Pra isso que existe fgets, gets e as funções atol, atoi, atof e etc...

Parabéns __KERNEL__ !!!!



01 02 03



Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts