TL; DR : o EOF não é um caractere, é uma macro usada para avaliar o retorno negativo de uma função de leitura de entrada. Pode-se usar Ctrl + D para enviar o caractere EOT
, o que forçará a função retornar -1
Todo programador deve ter RTFM
Vamos nos referir ao "C A Reference Manual", de Harbison e Steele, 4ª ed. de 1995, página 317:
O inteiro negativo EOF é um valor que não é uma codificação de um "real
caractere "... Por exemplo, fget (seção 15.6) retorna EOF quando
no final do arquivo, porque não há "caractere real" para ser lido.
Essencialmente EOF
não é um caractere, mas sim um valor inteiro implementado em stdio.h
para representar -1
. Assim, a resposta de kos está correta, mas não se trata de receber entradas "vazias". Nota importante é que aqui o EOF serve como comparação valor de retorno (de getchar()
), para não significar um caractere real. O man getchar
suporta isso:
VALOR DE RETORNO
fgetc (), getc () e getchar () retornam o caractere lido como não assinado
char cast para um int ou EOF no final do arquivo ou erro.
gets () e fgets () retornam s em sucesso e NULL em erro ou quando terminar
de arquivo ocorre enquanto nenhum caractere foi lido.
ungetc () retorna c em sucesso, ou EOF em erro.
Considere o loop while
- seu objetivo principal é repetir a ação se a condição entre parênteses for verdadeira . Olhe de novo:
while ((c = getchar ()) != EOF)
Basicamente diz para continuar fazendo coisas se c = getchar()
retornar código de sucesso ( 0
ou acima; é uma coisa comum, experimente executar um comando bem-sucedido, então echo $?
e depois falha echo $?
e ver números Retorna ). Portanto, se conseguirmos obter caractere e associar a C, o código de status retornado será 0, a falha será -1. EOF
é definido como -1
. Portanto, quando ocorre a condição -1 == -1
, os loops param. E quando isso acontecerá? Quando não há mais caracteres para obter, quando c = getchar()
falha. Você poderia escrever while ((c = getchar ()) != -1)
e ainda assim funcionaria
Além disso, vamos voltar ao código real, aqui está um trecho de stdio.h
/* End of file character.
Some things throughout the library rely on this being -1. */
#ifndef EOF
# define EOF (-1)
#endif
Códigos ASCII e EOT
Embora o caractere EOF não seja um caractere real, no entanto, existe um caractere EOT
(Fim da Transmissão), que tem um valor decimal ASCII de 04; ele está vinculado ao atalho Ctrl + D (representado também como meta caractere ^D
). O fim do caractere de transmissão usado para significar o fechamento de um fluxo de dados quando os computadores eram usados para controlar as conexões telefônicas, portanto, o nome do "fim da transmissão".
Portanto, é possível enviar esse valor ascii para o programa, anote o $''
que é o EOT:
skolodya@ubuntu:$ ./a.out <<< "a,b,c $''"
digits = 1 0 0 0 1 0 0 0 0 0, white space = 2, other = 9
Assim, podemos dizer que existe, mas não é imprimível
Nota lateral
Muitas vezes esquecemos que no passado os computadores não eram tão versáteis - os designers têm que usar todas as teclas do teclado disponíveis. Assim, o envio do caractere EOT
com o CtrlD ainda está "enviando um caractere", não diferente de digitar maiúscula A, ShiftA, você ainda dá ao computador uma entrada com as teclas disponíveis. Assim EOT é um personagem real no sentido de que ele vem do usuário, é legível por computador (embora não seja imprimível, não visível por humanos), ele existe na memória do computador
Comentário do Byte Commander
Se você tentar ler de / dev / null, isso deve retornar um EOF também,
certo? Ou o que eu chego lá?
Sim, exatamente correto, porque em /dev/null
não há nenhum caractere real a ser lido, portanto, c = getchar()
retornará -1
code e o programa será encerrado imediatamente. Novamente, o comando não retorna EOF. EOF é apenas variável constante igual a -1, que usamos para comparar o código de retorno da função getchar . EOF
não existe como caractere, é apenas um valor estático dentro de stdio.h
.
Demo:
# cat /dev/null shows there's no readable chars
DIR:/xieerqi
skolodya@ubuntu:$ cat /dev/null | cat -A
# Bellow is simple program that will open /dev/null for reading. Note the use of literal -1
DIR:/xieerqi
skolodya@ubuntu:$ cat readNull.c
#include<stdio.h>
void main()
{
char c;
FILE *file;
file = fopen("/dev/null", "r");
if (file)
{
printf ("Before while loop\n");
while ((c = getc(file)) != -1)
putchar(c);
printf("After while loop\n");
fclose(file);
}
}
DIR:/xieerqi
skolodya@ubuntu:$ gcc readNull.c -o readNull
DIR:/xieerqi
skolodya@ubuntu:$ ./readNull
Before while loop
After while loop
Outro prego no caixão
Às vezes, tenta-se provar que o EOF é um personagem com um código como este:
#include <stdio.h>
int main(void)
{
printf("%c", EOF);
return 0;
}
Problema com isso é que o tipo de dados char pode ser um valor assinado ou não assinado. Além disso, eles são os menores tipos de dados endereçáveis, o que os torna muito úteis em microcontroladores, onde a memória é limitada. Então ao invés de declarar int foo = 25;
é comum ver em microcontroladores com pouca memória char foo = 25;
ou algo parecido. Além disso, os caracteres podem ser assinados ou não assinados .
Pode-se verificar que o tamanho em bytes com um programa como este:
#include <stdio.h>
int main(void)
{
printf("Size of int: %lu\n",sizeof(int));
printf("Sieze of char: %lu\n",sizeof(char));
//printf("%s", EOF);
return 0;
}
skolodya@ubuntu:$ ./EOF
Size of int: 4
Sieze of char: 1
Qual é exatamente o ponto? O ponto é que o EOF é definido como -1, mas o tipo de dados char pode imprimir valores inteiros .
OK. . Então, e se tentarmos imprimir char como string?
#include <stdio.h>
int main(void)
{
printf("%s", EOF);
return 0;
}
Obviamente, um erro, mas mesmo assim, o erro nos dirá algo interessante:
skolodya @ ubuntu: $ gcc EOF.c -o EOF
EOF.c: Na função "main": EOF.c: 4: 5: aviso: o formato "% s" espera
argumento do tipo "char *", mas o argumento 2 tem tipo "int"
[-formato =]
printf ("% s", EOF);
Valores hexadecimais
Imprimir EOF como um valor hexadecimal fornece FFFFFFFF
, um valor de 16 bits (8 bytes), dois complementos de -1
.
#include <stdio.h>
int main(void)
{
printf("This is EOF: %X\n", EOF);
printf("This is Z: %X\n",'Z');
return 0;
}
Saída:
DIR:/xieerqi
skolodya@ubuntu:$ ./EOF
This is EOF: FFFFFFFF
This is Z: 5A
Outra coisa curiosa ocorre com o seguinte código:
#include <stdio.h>
int main(void)
{
char c;
if (c = getchar())
printf ("%x",c);
return 0;
}
Se alguém pressionar Shift + A , obtemos o valor hexadecimal 41, obviamente igual ao da tabela ASCII. Mas para Ctrl + D , temos ffffffff
, novamente - o valor de retorno de getchar()
armazenado em c
.
DIR:/xieerqi
skolodya@ubuntu:$ gcc EOF.c -o ASDF.asdf
DIR:/xieerqi
skolodya@ubuntu:$ ./ASDF.asdf
A
41
DIR:/xieerqi
skolodya@ubuntu:$ ./ASDF.asdf
ffffffff
Consulte outros idiomas
Observe que outras linguagens evitam essa confusão, porque elas operam ao avaliar um status de saída de função, não comparando-o com uma macro.
Como se lê um arquivo em Java?
File inputFile = new File (filename);
Scanner readFile = new Scanner(inputFile);
while (readFile.hasNext())
{ //more code bellow }
Que tal python?
with open("/etc/passwd") as file:
for line in file:
print line