TL; DR : 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+ Dpara enviar EOT
caracteres que forçam o retorno da função-1
Todo programador deve RTFM
Vamos nos referir ao "CA Reference Manual", de Harbison e Steele, 4ª ed. a partir de 1995, página 317:
O número inteiro negativo EOF é um valor que não é uma codificação de um "caractere real". . . Por exemplo, fget (seção 15.6) retorna EOF quando no final do arquivo, porque não há "caractere real" a ser lido.
Essencialmente, EOF
não é um caractere, mas um valor inteiro implementado stdio.h
para representar -1
. Portanto, a resposta de kos está correta na medida em que isso é válido, mas não se trata de receber entradas "vazias". Nota importante é que aqui o EOF serve como comparação de valor de retorno (de getchar()
), para não significar um caractere real. Os man getchar
suportes que:
VALOR DE RETORNO
fgetc (), getc () e getchar () retornam o caractere lido como uma conversão de caracteres não assinada para um int ou EOF no final do arquivo ou erro.
gets () e fgets () retornam s em caso de sucesso e NULL em erro ou quando o final do arquivo ocorre enquanto nenhum caractere foi lido.
ungetc () retorna c em caso de sucesso ou EOF em caso de erro.
Considere o while
loop - seu objetivo principal é repetir a ação se a condição entre colchetes for verdadeira . Olhe novamente:
while ((c = getchar ()) != EOF)
Basicamente, diz continuar fazendo coisas se c = getchar()
retornar um código bem-sucedido ( 0
ou acima; é uma coisa comum, tente executar o comando bem-sucedido echo $?
e, em seguida, falhe echo $?
e veja os números que eles retornam). Portanto, se conseguirmos obter o caractere e atribuir a C, o código de status retornado será 0, a falha será -1. EOF
define-se como -1
. Portanto, quando a condição -1 == -1
ocorre, os loops são interrompidos. E quando isso vai acontecer? Quando não há mais caráter para obter, quando c = getchar()
falha. Você poderia escrever while ((c = getchar ()) != -1)
e ainda 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 possui valor decimal ASCII de 04; está vinculado ao atalho Ctrl+ D(representado também como meta caractere ^D
). O caractere de fim da transmissão costumava significar o fechamento de um fluxo de dados quando os computadores eram usados para controlar as conexões telefônicas, daí a denominação "fim da transmissão".
Portanto, é possível enviar esse valor ascii para o programa dessa maneira, observe o $'\04'
que é o EOT:
skolodya@ubuntu:$ ./a.out <<< "a,b,c $'\04'"
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
Muitas vezes esquecemos que no passado os computadores não eram tão versáteis - os designers precisam usar todas as teclas do teclado disponíveis. Portanto, o envio de EOT
caractere com CtrlD ainda está "enviando um caractere", não muito diferente da digitação de letras maiúsculas A, ShiftA, você ainda fornece ao computador uma entrada com as teclas disponíveis. Portanto, a EOT é um personagem real, no sentido de que é proveniente do usuário, é legível por computador (embora não seja imprimível, não é visível por humanos), existe na memória do computador
Comentário do Byte Commander
Se você tentar ler de / dev / null, isso também deve retornar um EOF, certo? Ou o que eu chego lá?
Sim, exatamente certo, porque /dev/null
não existe um caracter real a ser lido, portanto, ele c = getchar()
retornará o -1
código e o programa será encerrado imediatamente. Novamente, o comando não retorna EOF. O EOF é apenas uma variável constante igual a -1, que usamos para comparar o código de retorno da função getchar . EOF
não existe como personagem, é apenas um valor estático por dentro 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 EOF é um personagem com um código como este:
#include <stdio.h>
int main(void)
{
printf("%c", EOF);
return 0;
}
O problema é que o tipo de dados char pode ser um valor assinado ou não assinado. Além disso, eles são o menor tipo de dados endereçável, o que os torna muito úteis em microcontroladores, onde a memória é limitada. Então, em vez de declarar int foo = 25;
, é comum ver em microcontroladores com pouca memória char foo = 25;
ou algo semelhante. Além disso, os caracteres podem ser assinados ou não assinados .
Pode-se verificar se 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 é a questão ? O ponto é que o EOF é definido como -1, mas o tipo de dados char pode imprimir valores inteiros .
ESTÁ BEM . . .so 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'
[-Wformat =] printf ("% s", EOF);
Valores hexadecimais
Imprimir EOF como um valor hexadecimal fornece FFFFFFFF
, um valor de 16 bits (8 bytes), o complemento de dois de a -1
.
#include <stdio.h>
int main(void)
{
printf("This is EOF: %X\n", EOF);
printf("This is Z: %X\n",'Z');
return 0;
}
Resultado:
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 pressionar Shift+ A, obtemos o valor hexadecimal 41, obviamente o mesmo da tabela ASCII. Mas para Ctrl+ D, temos ffffffff
novamente o valor de retorno 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 outro idioma evita essa confusão, porque eles operam na avaliação do status de saída de uma 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 }
E o python?
with open("/etc/passwd") as file:
for line in file:
print line
-1
é equivalente a EOF. Ele é definido no/usr/include/stdio.h
como uma constante macro