TL; DR : EOF ist kein Zeichen, sondern ein Makro zur Bewertung der negativen Rückgabe einer Eingabe-Lesefunktion. Man kann Ctrl+ verwenden D, um EOT
Zeichen zu senden , die die Funktionsrückgabe erzwingen-1
Jeder Programmierer muss RTFM
Wir verweisen auf "CA Reference Manual" von Harbison und Steele, 4. Aufl. ab 1995, Seite 317:
Die negative Ganzzahl EOF ist ein Wert, der keine Codierung eines "echten Zeichens" ist. . . Zum Beispiel gibt fget (Abschnitt 15.6) am Ende der Datei EOF zurück , da kein "echtes Zeichen" zu lesen ist.
Im Wesentlichen EOF
handelt es sich nicht um ein Zeichen, sondern um einen ganzzahligen Wert , der stdio.h
zur Darstellung implementiert ist -1
. Somit ist die Antwort von kos soweit richtig, aber es geht nicht darum, "leere" Eingaben zu erhalten. Wichtiger Hinweis ist, dass hier EOF als Rückgabewert (des getchar()
) Vergleichs dient, nicht um ein tatsächliches Zeichen zu kennzeichnen. Das man getchar
unterstützt das:
RÜCKGABEWERT
fgetc (), getc () und getchar () geben das als vorzeichenloses Zeichen gelesene Zeichen am Ende der Datei oder des Fehlers an einen int oder EOF zurück.
get () und fgets () geben s bei Erfolg zurück und NULL bei Fehler oder wenn das Dateiende eintritt, während keine Zeichen gelesen wurden.
ungetc () gibt bei Erfolg c oder bei Fehler EOF zurück.
Betrachten Sie die while
Schleife - ihr Hauptzweck besteht darin, die Aktion zu wiederholen, wenn die Bedingung in den Klammern erfüllt ist . Schau nochmal:
while ((c = getchar ()) != EOF)
Grundsätzlich heißt es, mach weiter, wenn c = getchar()
erfolgreicher Code zurückgegeben wird ( 0
oder höher; es ist übrigens üblich, einen erfolgreichen Befehl auszuführen , dann echo $?
und dann fehlgeschlagen echo $?
und die zurückgegebenen Zahlen zu sehen). Wenn wir also erfolgreich Zeichen erhalten und C zuordnen, ist der zurückgegebene Statuscode 0, fehlgeschlagen -1. EOF
ist definiert als -1
. Wenn ein Zustand -1 == -1
eintritt, werden die Schleifen daher gestoppt. Und wann wird das passieren? Wenn kein Charakter mehr zu bekommen ist, wenn er c = getchar()
fehlschlägt. Sie könnten schreiben while ((c = getchar ()) != -1)
und es würde immer noch funktionieren
Kehren wir auch zum eigentlichen Code zurück. Hier ist ein Auszug aus stdio.h
/* End of file character.
Some things throughout the library rely on this being -1. */
#ifndef EOF
# define EOF (-1)
#endif
ASCII-Codes und EOT
Obwohl das EOF-Zeichen kein tatsächliches Zeichen ist, gibt es ein EOT
(Ende der Übertragung) Zeichen mit dem ASCII-Dezimalwert 04; Es ist mit der Verknüpfung Ctrl+ verknüpft D(auch als Metazeichen dargestellt ^D
). Das Ende der Übertragung wird verwendet, um das Schließen eines Datenstroms vor langer Zeit anzuzeigen, als Computer zur Steuerung von Telefonverbindungen verwendet wurden, daher die Benennung "Ende der Übertragung".
Es ist also möglich, diesen ASCII-Wert wie $'\04'
folgt an das Programm zu senden. Beachten Sie Folgendes: 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
Wir können also sagen, dass es existiert, aber es ist nicht druckbar
Randnotiz
Wir vergessen oft, dass Computer in der Vergangenheit nicht so vielseitig waren - Designer müssen jede verfügbare Tastaturtaste verwenden. Das Senden eines EOT
Zeichens mit StrgD bedeutet also immer noch "Senden eines Zeichens", ähnlich wie bei der Eingabe von Großbuchstaben A und ShiftA. Sie geben dem Computer dennoch eine Eingabe mit verfügbaren Schlüsseln. Somit ist EOT ein realer Charakter in dem Sinne, dass es vom Benutzer stammt, vom Computer lesbar ist (obwohl es nicht druckbar ist, für Menschen nicht sichtbar), es existiert im Computerspeicher
Kommentar von Byte Commander
Wenn Sie versuchen, aus / dev / null zu lesen, sollte dies auch einen EOF zurückgeben, oder? Oder was bekomme ich dort?
Ja, genau richtig, da /dev/null
darin kein tatsächlich zu lesendes Zeichen vorhanden ist. Daher c = getchar()
wird -1
Code zurückgegeben und das Programm wird sofort beendet. Wieder gibt der Befehl EOF nicht zurück. EOF ist nur eine konstante Variable gleich -1, mit der wir den Rückkehrcode der Funktion getchar vergleichen . EOF
existiert nicht als Zeichen, es ist nur ein statischer Wert im Inneren 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
Ein weiterer Nagel im Sarg
Manchmal wird versucht zu beweisen, dass EOF ein Zeichen mit einem Code wie diesem ist:
#include <stdio.h>
int main(void)
{
printf("%c", EOF);
return 0;
}
Das Problem dabei ist, dass der Datentyp char ein vorzeichenbehafteter oder vorzeichenloser Wert sein kann. Darüber hinaus sind sie der kleinste adressierbare Datentyp, was sie in Mikrocontrollern mit begrenztem Speicher sehr nützlich macht. Anstatt zu deklarieren int foo = 25;
, ist es üblich, in Mikrocontrollern mit kleinem Speicher char foo = 25;
oder ähnlichem zu sehen. Außerdem können Zeichen signiert oder nicht signiert sein .
Mit einem Programm wie diesem könnte man die Größe in Bytes überprüfen:
#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
Was genau ist der Punkt? Der Punkt ist, dass EOF als -1 definiert ist, der Datentyp char jedoch ganzzahlige Werte drucken kann .
IN ORDNUNG . . Was ist, wenn wir versuchen, char als Zeichenfolge zu drucken?
#include <stdio.h>
int main(void)
{
printf("%s", EOF);
return 0;
}
Offensichtlich ein Fehler, aber dennoch wird uns ein Fehler etwas Interessantes sagen:
skolodya @ ubuntu: $ gcc EOF.c -o EOF
EOF.c: In Funktion 'main': EOF.c: 4: 5: Warnung: Format '% s' erwartet Argument vom Typ 'char *', aber Argument 2 hat Typ 'int'
[-Wformat =] printf ("% s", EOF);
Hex-Werte
Das Drucken von EOF als Hex-Wert ergibt FFFFFFFF
einen 16-Bit-Wert (8 Byte), zwei Komplimente von a -1
.
#include <stdio.h>
int main(void)
{
printf("This is EOF: %X\n", EOF);
printf("This is Z: %X\n",'Z');
return 0;
}
Ausgabe:
DIR:/xieerqi
skolodya@ubuntu:$ ./EOF
This is EOF: FFFFFFFF
This is Z: 5A
Eine andere merkwürdige Sache tritt mit dem folgenden Code auf:
#include <stdio.h>
int main(void)
{
char c;
if (c = getchar())
printf ("%x",c);
return 0;
}
Wenn man Shift+ drückt A, erhält man den Hex-Wert 41, offensichtlich wie in der ASCII-Tabelle. Aber für Ctrl+ Dhaben wir ffffffff
wieder - den Rückgabewert von getchar()
gespeichert 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
Beziehen Sie sich auf andere Sprachen
Beachten Sie, dass andere Sprachen diese Verwirrung vermeiden, da sie einen Funktions-Exit-Status auswerten und nicht mit einem Makro vergleichen. Wie liest man eine Datei in Java?
File inputFile = new File (filename);
Scanner readFile = new Scanner(inputFile);
while (readFile.hasNext())
{ //more code bellow }
Wie wäre es mit Python?
with open("/etc/passwd") as file:
for line in file:
print line
-1
entspricht EOF. Es ist/usr/include/stdio.h
als Makrokonstante definiert