paulo1205
(usa Ubuntu)
Enviado em 17/07/2013 - 15:16h
Que eu saiba -- pelo menos pelo que diz a manpage -- o famigerado
fflush(stdin) passou a funcionar nas versões mais recentes da glibc, com o mesmo comportamento que tinha no DOS e Windows. Calculo que essa conversão foi feita por conveniência de ajudar quem está chegando ao C no Linux vindo do Windows, ou usando material didático escrito com os compiladores para MS-DOS em mente -- até porque tal comportamento não
contraria o padrão, mas apenas o
estende.
Eu sou um usuário histórico de BSDs que hoje usa Linux no trabalho por necessidade e em casa por conveniência (especificamente, a conveniência de ter plugins para o Firefox, e mais recentemente para poder usar o Steam no Linux, em vez de no Windows). Nos BSDs,
fflush() continua definida apenas para streams de saída, com um sentido não de descartar, mas de
efetivar as alterações feitas nesses streams, garantindo que irão dos buffers locais para o local de armazenamento permanente. Quando alguém quis uma função para
descartar dados, teve a prudência de lhe dar outro nome (
fpurge(), no caso dos BSDs, que foi inicialmente importada para o Linux com o mesmo nome, e depois renomeada no Linux para
__fpurge()).
Eu considero essa abordagem correta por causa de duas oposições de sentido: do sentido da orientação (escrita × leitura, ou "indo para o disco" × "vindo do disco") e do sentido semântico (preservar × descartar). A escolha do mundo DOS/Windows, seguida depois pelo GNU, é muito mais arbitrária e, por conta das oposições de sentido que mencionei, muito mais difícil de justificar filosoficamente. Mas não pode ser considerada
errada, já que não descumpre o que o padrão prescreve, mas somente o estende num aspecto em que ele não diz coisa alguma.
Mas independentemente da minha opinião sobre as duas abordagens, não uso mais qualquer uma delas em qualquer programa meu:
fflush(stdin) hoje passou a funcionar no Linux, mas continua (e espero mesmo que continue) a não funcionar no BSD, e
fpurge() sequer existe no Linux ou no mundo Microsoft.
Como eu disse antes, eu prefiro ficar dentro do que o padrão prescreve. Então, se eu quiser pular espaços na leitura de dados, eu vou especificamente escrever código padrão que deixe isso bem claro. Não é tão difícil. Quando uso C, existem várias técnicas que eu uso:
* Ler sempre linhas inteiras com
fgets(), e pular os eventuais espaços no início da string antes de copiar os dados para o array de caracteres onde eles ficarão definitivamente guardados, suprimrindo também, no momento da cópia, eventuais espaços no final da linha.
* Em linhas com múltiplos dados pre-formatados, ler linhas inteiras com
fgets() para um buffer intermediário, e extrair desse buffer os campos de interesse usando
sscanf(). Isso tem a vantagem, se comparado com usar diretamente
scanf(), de que linhas que eventualmente não estejam no formato esperado não vão deixar o stream de entrada num estado inconsistente, e fica fácil fazer outras tentativas de extração dos campos desejados com outras strings de formatação, e até mesmo identificar e descartar informação não desejada.
* Usar strings de formatação mais seguras (e complexas) na própria
scanf(). Em particular, essas strings raramente usam "%s", mas em seu lugar ocorrem espaços e "%[...]".
* Ler caráter a caráter com
fgetc().