paulo1205
(usa Ubuntu)
Enviado em 17/10/2015 - 21:16h
programadorc escreveu:
Sou novo por aqui, mas gostaria de auxiliar em algumas dúvidas.
Primeiro
Vi uma das dúvidas referente a ocorrência de entradas onde limpar o buffer não é necessário em em outros momentos ser. Éo seguinte, a limpeza do buffer se faz necessária sempre que houver a entrada de um ou mais caracteres (dados alfanuméricos). Se for efetuada uma entrada numérica seja int, float ou double o buffer do teclado não fica sobrecarregado.
A coisa é um pouco diferente do que você disse. Permita-me fazer algumas correções.
Em primeiro lugar, é interessante deixar claro que você está falando de leitura com a função
scanf() -- que, por sinal é provavelmente _a_ função mais complexa da biblioteca padrão do C. Nesse contexto, é verdade que operações de leitura com conversão de dados numéricos desprezam espaços em branco (incluindo quebras de linha) que
antecedam o dado lido. Porém, espaços após o número permanecem no buffer e, portanto, não haverá garantia de buffer limpo após a leitura.
Outro ponto a observar é que é falso dizer que toda entrada de caracteres vai sofrer com problemas de coisas inesperadas no buffer. A conversão
%s de
scanf() é um exemplo de operação de leitura de texto que executa exatamente o mesmo procedimento de descarte de espaços em branco que as conversões de dados numéricos
antes de chegar aos caracteres que vai consumir.
Frequentemente a permanência de caracteres no buffer de entrada após uma operação de leitura é indesejada, e esses caracteres costumam ser chamados de “lixo no buffer de entrada”. Eu considero essa terminologia errônea, porque se um caráter aparece na entrada, não foi por descaso semelhante ao de alguém que joga lixo na rua, mas porque ele foi posto na entrada com alguma finalidade. A própria marca de fim de linha, como exemplo mais evidente, é
necessária para que muitas operações de leitura possam ser concluídas.
Um programador pode dizer que essa marca de fim linha e outros caracteres de espaços (ou de outro tipo qualquer) são “lixo” do seu ponto de vista, porque ele não está interessado nela, mas tão somente nos dados que vêm antes ou depois deles. Entretanto, funções como
scanf(),
fscanf(),
fgets() ou mesmo
getchar() foram criadas para poder tratar qualquer caso, e não apenas casos específicos de uma pessoa ou outra -- até porque seria impossível prever todos esses casos. O que é lixo para uma aplicação (por exemplo, que extrai apenas um conjunto de números de uma tabela escrita como texto e os usa para computar um resultado final) pode ser um dado crucial para outra aplicação (que, por exemplo, gere a assinatura digital da mesma tabela), e o mesmo conjunto de funções serve para atender as duas.
Para todo programador, em qualquer tipo de aplicação, é essencial conhecer bem como cada função funciona e quais recursos são oferecidos, pois ele terá de ser adaptar a elas (ou mudar de ferramenta).
Este efeito é comum em diversas linguagens de programação e não só em C. Em relação a dados do tipo char ocorre que após a confirmação da entrada com a tecla <Enter> o caractere "\0" do <Enter> fica mantido no buffer e desloca automaticamente a próxima entrada, fazendo-a saltar.
Você se confundiu de novo. O caráter correspondente à tecla ENTER é
'\n', não
'\0'. O
'\0' é usado por convenção nas funções da biblioteca padrão do C para marcar o final de uma string armazenada em memória. O que permanece no buffer de entrada -- quando permanece -- é o
'\n'.
Segundo
A limpeza de buffer realizada com fflush() ou __fpurge() apesar de funcionarem não são as melhores formas, são soluções particularizadas parecendo-se com certo tipo de "gambiarra". A forma padrão para limpar buffer que funciona em qualquer sistema operacional deve ser escrita como:
while ((getchar() != '\n') && (!EOF));
Erradíssimo, pois essa condição de controle será sempre falsa (
EOF é uma constante com valor -1, logo
!EOF vale zero, e qualquer coisa que faça uma operação lógica de “e” com zero dará zero).
Talvez você tenha tentado dizer isto aqui:
int ch; /* Note que é int, e não char!!! */
while((ch=getchar())!='\n' && ch!=EOF)
;
A instrução, em si só, é um excelente exercício de percepção lógica do que ocorre com o buffer, devendo ser usada sempre após um scanf(), por exemplo.
Falso. Primeiro porque você pode fazer com que
scanf() consuma a marca de fim de linha ou outros caracteres que você eventualmente queira descartar.
Segundo porque é possível que o buffer já esteja “limpo” (isto é, pronto para ler uma linha nova), e chamar uma rotina como a acima para esvaziar o buffer, nesse caso, vai começar a suprimir dados novos. Funçõs como
fpurge()/
__fpurge(), bem como
fflush() quando aplicada a stream de entrada, são, sim, gambiarras, mas elas têm condições de examinar internamente as estruturas de controle do stream para saber se ele está no estado consistente antes de começar a descartar coisas; o loop mostrado acima, não, podendo descartar o que não deve e se tornar uma gambiarra ainda pior.