TL; DR : EOF non è un carattere, è una macro utilizzata per valutare il ritorno negativo di una funzione di input-reading. Si può usare Ctrl+ Dper inviare un EOT
carattere che forzerà il ritorno della funzione-1
Ogni programmatore deve RTFM
Facciamo riferimento al "Manuale di riferimento CA", di Harbison e Steele, 4a ed. dal 1995, pagina 317:
L'intero negativo EOF è un valore che non è una codifica di un "carattere reale". . . Ad esempio fget (sezione 15.6) restituisce EOF alla fine del file, perché non esiste un "carattere reale" da leggere.
Essenzialmente EOF
non è un carattere, ma piuttosto un valore intero implementato stdio.h
per rappresentare -1
. Pertanto, la risposta di kos è corretta, ma non si tratta di ricevere input "vuoti". Nota importante è che qui EOF funge da confronto del valore di ritorno (di getchar()
), non per indicare un carattere reale. I man getchar
supporti che:
VALORE DI RITORNO
fgetc (), getc () e getchar () restituiscono il carattere letto come cast di caratteri non firmato a un int o EOF alla fine del file o dell'errore.
gets () e fgets () restituiscono s in caso di successo e NULL in caso di errore o quando si verifica la fine del file mentre non sono stati letti caratteri.
ungetc () restituisce c in caso di successo o EOF in caso di errore.
Considera il while
ciclo: il suo scopo principale è ripetere l'azione se la condizione tra parentesi è vera . Guarda di nuovo:
while ((c = getchar ()) != EOF)
Fondamentalmente dice che continua a fare cose se c = getchar()
restituisce codice di successo ( 0
o superiore; è una cosa comune tra l'altro, prova a eseguire il comando di successo, quindi echo $?
e poi fallisce echo $?
e vedi i numeri che restituiscono). Quindi, se otteniamo correttamente il carattere e valutiamo C, il codice di stato restituito è 0, l'errore è -1. EOF
è definito come -1
. Pertanto, quando si -1 == -1
verifica la condizione , i loop si arrestano. E quando succederà? Quando non c'è più personaggio da ottenere, quando c = getchar()
fallisce. Potresti scrivere while ((c = getchar ()) != -1)
e funzionerebbe ancora
Inoltre, torniamo al codice attuale, ecco un estratto da stdio.h
/* End of file character.
Some things throughout the library rely on this being -1. */
#ifndef EOF
# define EOF (-1)
#endif
Codici ASCII ed EOT
Sebbene il carattere EOF non sia un carattere reale, tuttavia, esiste un carattere EOT
(End of Transmission), che ha un valore decimale ASCII di 04; è collegato a Ctrl+ Dscorciatoia (rappresentato anche come meta personaggio ^D
). Il carattere di fine trasmissione utilizzato per indicare la chiusura di un flusso di dati nel passato quando i computer venivano utilizzati per controllare le connessioni telefoniche, da cui la denominazione di "fine della trasmissione".
Quindi è possibile inviare quel valore ASCII al programma in questo modo, notare $'\04'
quale è l'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
Quindi, possiamo dire che esiste, ma non è stampabile
Nota a margine
Spesso dimentichiamo che in passato i computer non erano così versatili: i progettisti devono utilizzare tutti i tasti disponibili. Pertanto, l'invio di EOT
caratteri con CtrlD è ancora "invio di un carattere", non diversamente dalla digitazione della maiuscola A, ShiftA, si fa comunque dare al computer un input con i tasti disponibili. Quindi EOT è un vero personaggio nel senso che proviene da un utente, è leggibile dal computer (anche se non stampabile, non visibile dall'uomo), esiste nella memoria del computer
Commento di Byte Commander
Se provi a leggere da / dev / null, anche questo dovrebbe restituire un EOF, giusto? O cosa ci arrivo?
Sì, esattamente, perché in /dev/null
non c'è un carattere reale da leggere, quindi c = getchar()
restituirà il -1
codice e il programma verrà chiuso immediatamente. Ancora una volta il comando non restituisce EOF. EOF è solo una variabile costante uguale a -1, che usiamo per confrontare il codice di ritorno della funzione getchar . EOF
non esiste come personaggio, è solo un valore statico all'interno 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
Un altro chiodo nella bara
A volte si tenta di provare che EOF è un personaggio con un codice come questo:
#include <stdio.h>
int main(void)
{
printf("%c", EOF);
return 0;
}
Il problema è che il tipo di dati char può essere un valore con o senza segno. Inoltre, sono i tipi di dati indirizzabili più piccoli che li rendono molto utili nei microcontrollori, dove la memoria è limitata. Quindi invece di dichiarare int foo = 25;
è comune vedere nei microcontrollori con poca memoria char foo = 25;
o qualcosa di simile. Inoltre, i caratteri possono essere firmati o non firmati .
Si potrebbe verificare che la dimensione in byte con un programma come questo:
#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 è esattamente il punto? Il punto è che EOF è definito come -1, ma il tipo di dati char può stampare valori interi .
OK . . .e cosa succede se proviamo a stampare char come stringa?
#include <stdio.h>
int main(void)
{
printf("%s", EOF);
return 0;
}
Ovviamente un errore, ma comunque, ci dirà qualcosa di interessante:
skolodya @ ubuntu: $ gcc EOF.c -o EOF
EOF.c: nella funzione 'principale': EOF.c: 4: 5: avviso: il formato '% s' prevede l'argomento di tipo 'char *', ma l'argomento 2 ha digitare 'int'
[-Wformat =] printf ("% s", EOF);
Valori esadecimali
La stampa di EOF come valore esadecimale dà FFFFFFFF
, un valore di 16 bit (8 byte), due complimenti di a -1
.
#include <stdio.h>
int main(void)
{
printf("This is EOF: %X\n", EOF);
printf("This is Z: %X\n",'Z');
return 0;
}
Produzione:
DIR:/xieerqi
skolodya@ubuntu:$ ./EOF
This is EOF: FFFFFFFF
This is Z: 5A
Un'altra cosa curiosa si verifica con il seguente codice:
#include <stdio.h>
int main(void)
{
char c;
if (c = getchar())
printf ("%x",c);
return 0;
}
Se si preme Shift+ A, si ottiene il valore esadecimale 41, ovviamente uguale alla tabella ASCII. Ma per Ctrl+ D, abbiamo ffffffff
, ancora una volta - il valore restituito di getchar()
stored in 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
Fare riferimento ad altre lingue
Si noti che altre lingue evitano questa confusione, poiché operano sulla valutazione di uno stato di uscita della funzione, non sul confronto con una macro. Come si legge un file in Java?
File inputFile = new File (filename);
Scanner readFile = new Scanner(inputFile);
while (readFile.hasNext())
{ //more code bellow }
Che ne dici di Python?
with open("/etc/passwd") as file:
for line in file:
print line
-1
equivale a EOF. È definito/usr/include/stdio.h
come una costante macro