Acabei de começar o livro K&R. Ele introduz um programa de loop getchar() putchar() para copiar caracteres da entrada para a saída até que EOF seja alcançado.
main()
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
}
Tentei mudar para um loop infinito e ver o que acontece quando tento imprimir EOF em vez disso. Aqui está o código:
#include <stdio.h>
int main() {
int c;
while(1) {
c = getchar();
if (c == EOF) {
printf("%d", c); // Since you cannot really use putchar() for EOF as it is -1
// break;
} else {
putchar(c);
}
}
putchar('\n');
return 0;
}
Exemplo de saída:
./a.out
a
a
-1
-1
df
df
-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1
Eu esperava que ele imprimisse -1 e então esperasse pela próxima entrada, mas descobri que ele continua imprimindo -1.
Se eu adicionar uma linha para quebrar o loop depois de imprimir EOF uma vez, ele imprime -1 uma vez e então sai do programa, o que é compreensível.
Mas não entendo por que, sem a instrução break, ele continua em loop e imprime -1.
A princípio, pensei que ele estivesse usando a saída -1 como entrada para o próximo loop (na verdade, os próximos 2 loops, já que -1 são 2 caracteres separados '-' e '1'), mas se for esse o caso, por que não vejo esse comportamento de loop infinito quando coloco qualquer outro caractere como 'a'? Isso deveria ter impresso 'a' continuamente, de acordo com minha lógica anterior.
Alguém pode ajudar a explicar o que está acontecendo?
De acordo com §7.23.1 ¶6 do padrão ISO C23 , a função
getchar
é uma "função de entrada de bytes".§7.23.3 ¶11 afirma o seguinte sobre o comportamento das funções de entrada de bytes:
§7.23.7.1 ¶3 afirma o seguinte sobre a função
fgetc
:Isso significa que, uma vez que o indicador de fim de arquivo tenha sido definido, todas as chamadas futuras para funções de entrada de bytes sempre falharão imediatamente, sem fazer nenhuma tentativa de ler mais dados. No entanto, o indicador de fim de arquivo pode ser limpo com a função
clearerr
. Depois de fazer isso, dependendo da plataforma, a próxima chamada para uma função de entrada de bytes pode ser bem-sucedida.Você pode limpar o EOF e o status de erro de um fluxo usando
clearerr
.getchar()
é equivalente agetc(stdin)
, então quando a entrada é o console, padrão em.Agora, um comportamento de erro lógico seria lembrar de atingir o fim do arquivo e retornar EOF sem fazer um
getc
. físico. Portanto, não há mais leitura do stdin. Lembre-se também de que, em vez do console, você poderia ter redirecionado do arquivo< ...
.@ikegami já mencionou
clearerr
limpar o estado de fim de arquivo. (Do qual eu esqueci.)A leitura de um arquivo de disco nunca espera; isso só acontece com dispositivos que retornam dados gerados de forma assíncrona, como terminais e conexões de rede.
Além disso,
stdio
tem sinalizadores naFILE
estrutura que indicam se ocorreu um erro ou se o EOF foi atingido. Uma vez que um desses sinalizadores é definido, a leitura do fluxo sempre retorna imediatamente. Você pode limpar esses sinalizadores com aclearerr()
função, mas se não usar isso,getchar()
continuará retornandoEOF
, mesmo que mais dados tenham sido gravados no arquivo.