TL; DR : EOF no es un carácter, es una macro utilizada para evaluar el retorno negativo de una función de lectura de entrada. Se puede usar Ctrl+ Dpara enviar EOT
caracteres que forzarán el retorno de la función-1
Todo programador debe RTFM
Consultemos el "Manual de referencia de CA", de Harbison y Steele, 4ª ed. desde 1995, página 317:
El entero negativo EOF es un valor que no es una codificación de un "carácter real". . . Por ejemplo, fget (sección 15.6) devuelve EOF cuando está al final del archivo, porque no hay un "carácter real" para leer.
Esencialmente EOF
no es un personaje, sino más bien un valor entero implementado stdio.h
para representar -1
. Por lo tanto, la respuesta de kos es correcta en lo que respecta a eso, pero no se trata de recibir una entrada "vacía". Nota importante es que aquí EOF sirve como valor de retorno (de getchar()
) comparación, no para indicar un carácter real. Los man getchar
apoyos que:
VALOR DEVUELTO
fgetc (), getc () y getchar () devuelven el carácter leído como una conversión de caracteres sin firmar a un int o EOF al final del archivo o error.
gets () y fgets () devuelven s en caso de éxito y NULL en caso de error o cuando se produce el final del archivo mientras no se han leído caracteres.
ungetc () devuelve c en caso de éxito o EOF en caso de error.
Considere el while
ciclo: su propósito principal es repetir la acción si la condición entre paréntesis es verdadera . Mirar de nuevo:
while ((c = getchar ()) != EOF)
Básicamente dice que siga haciendo cosas si c = getchar()
devuelve un código exitoso ( 0
o superior; es algo común por cierto, intente ejecutar un comando exitoso, echo $?
luego falla echo $?
y vea los números que devuelven). Entonces, si obtenemos con éxito el carácter y asignamos a C, el código de estado devuelto es 0, el error es -1. EOF
se define como -1
. Por lo tanto, cuando se -1 == -1
produce la condición , los bucles se detienen. ¿Y cuándo sucederá eso? Cuando no hay más personajes para obtener, cuando c = getchar()
falla. Podrías escribir while ((c = getchar ()) != -1)
y aún funcionaría
Además, volvamos al código real, aquí hay un extracto 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 y EOT
Aunque el carácter EOF no es un carácter real, existe un carácter EOT
(Fin de transmisión) que tiene un valor decimal ASCII de 04; está vinculado a Ctrl+ Dacceso directo (representado también como meta carácter ^D
). El carácter de fin de transmisión utilizado para significar el cierre de una secuencia de datos cuando las computadoras se usaban para controlar las conexiones telefónicas, de ahí el nombre de "fin de transmisión".
Por lo tanto, es posible enviar ese valor ASCII al programa así, tenga en cuenta $'\04'
cuál es el 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
Por lo tanto, podemos decir que existe, pero no es imprimible
Nota al margen
A menudo olvidamos que en el pasado las computadoras no eran tan versátiles: los diseñadores tienen que hacer uso de todas las teclas disponibles. Por lo tanto, enviar EOT
caracteres con CtrlD sigue siendo "enviar un carácter", no muy diferente de escribir mayúscula A, ShiftA, aún puede hacer que la computadora ingrese con las teclas disponibles. Por lo tanto, EOT es un personaje real en el sentido de que proviene del usuario, es legible por computadora (aunque no imprimible, no visible para los humanos), existe en la memoria de la computadora
Comentario del comandante de bytes
Si intentas leer desde / dev / null, eso también debería devolver un EOF, ¿verdad? ¿O qué consigo allí?
Sí, exactamente correcto, porque /dev/null
no hay ningún carácter real para leer, por lo tanto c = getchar()
, devolverá el -1
código y el programa se cerrará de inmediato. De nuevo el comando no devuelve EOF. EOF es una variable constante igual a -1, que usamos para comparar el código de retorno de la función getchar . EOF
no existe como personaje, es solo un valor estático en su interior stdio.h
.
Manifestación:
# 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
Otro clavo en el ataúd
A veces se intenta demostrar que EOF es un personaje con un código como este:
#include <stdio.h>
int main(void)
{
printf("%c", EOF);
return 0;
}
El problema con eso es que el tipo de datos char puede ser un valor con signo o sin signo. Además, son el tipo de datos direccionable más pequeño que los hace muy muy útiles en microcontroladores, donde la memoria es limitada. Entonces, en lugar de declarar int foo = 25;
, es común ver en microcontroladores con poca memoria char foo = 25;
o algo similar. Además, los caracteres pueden estar firmados o sin firmar .
Se podría verificar que el tamaño en bytes con un 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
Cuál es exactamente el punto ? El punto es que EOF se define como -1, pero el tipo de datos char puede imprimir valores enteros .
OKAY . . ¿Qué pasa si intentamos imprimir char como cadena?
#include <stdio.h>
int main(void)
{
printf("%s", EOF);
return 0;
}
Obviamente un error, pero no obstante, el error nos dirá algo interesante:
skolodya @ ubuntu: $ gcc EOF.c -o EOF
EOF.c: En la función 'main': EOF.c: 4: 5: advertencia: el formato '% s' espera un argumento del tipo 'char *', pero el argumento 2 tiene escriba 'int'
[-Wformat =] printf ("% s", EOF);
Valores hexadecimales
Imprimir EOF como un valor hexadecimal da FFFFFFFF
, un valor de 16 bits (8 bytes), dos cumplidos 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;
}
Salida:
DIR:/xieerqi
skolodya@ubuntu:$ ./EOF
This is EOF: FFFFFFFF
This is Z: 5A
Otra cosa curiosa ocurre con el siguiente código:
#include <stdio.h>
int main(void)
{
char c;
if (c = getchar())
printf ("%x",c);
return 0;
}
Si uno presiona Shift+ A, obtenemos el valor hexadecimal 41, obviamente igual que en la tabla ASCII. Pero para Ctrl+ D, tenemos ffffffff
, nuevamente, el valor de retorno de getchar()
almacenado en 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 otros idiomas
Tenga en cuenta que otro lenguaje evita esta confusión, porque operan evaluando el estado de salida de una función, no comparándola con una macro. ¿Cómo se lee un archivo en Java?
File inputFile = new File (filename);
Scanner readFile = new Scanner(inputFile);
while (readFile.hasNext())
{ //more code bellow }
¿Qué tal python?
with open("/etc/passwd") as file:
for line in file:
print line
-1
es equivalente a EOF. Se define/usr/include/stdio.h
como una constante macro