GideonRavenor schrieb:
End of File, also das ASCII Steuerzeichen 0x04
Das ist ein Missverständnis. Keiner verwendet mehr dieses Steuerzeichen für diesen Zweck – und ich bin nicht alt genug, um sagen zu können, ob das jemals der Fall war. Was du mit Strg+D meinst, funktioniert anders. Ich kenne auch Literatur („The UNIX Programming Environment“, Kernighan und Pike, S. 45) aus den 1970ern, die Strg+D schon anders beschreibt.
Strg+D bewirkt eigentlich einen Flush.
Das kannst du mal so ausprobieren: Starte einfach mal „cat
“ und gib einen Text ein gefolgt von Enter. Was siehst du? Der fette Block hier soll einen Cursor symbolisieren.
$ cat
hallo welt
hallo welt
█
Okay, das Enter hat den von dir eingegebenen String „beendet“, genauer gesagt, das Line Buffering wurde beendet. Was ist währenddessen in „cat
“ passiert? Es hat vorher im Syscall „read()
“ blockiert und auf deine Eingabe gewartet. Sobald du Enter gedrückt hast, ist dieser Syscall zurückgekehrt und hat damit „cat
“ den String (mitsamt Enter) übergeben.
So weit, so langweilig. Jetzt mit Strg+D. Du hast also „hallo“ eingegeben und dann nichts weiter.
$ cat
hallo█
Jetzt drückst du Strg+D.
$ cat
hallohallo█
„cat
“ kehrte jetzt ebenfalls aus dem Syscall „read()
“ zurück. Lesen konnte es diesmal nur „hallo“ und kein Enter/Newline, deshalb sind die beiden „hallo“ direkt hintereinander.
Jetzt kommt der Knackpunkt. Drückst du in dieser Situation nochmal Strg+D, dann kehrst du zum Prompt zurück:
$ cat
hallohallo$ █
Warum? Wieder ist „cat
“ aus „read()
“ zurückgekehrt. Diesmal aber hat „read()
“ gesagt: „Ich konnte 0 Bytes lesen.“ Und das ist nach Konvention die Situation, wenn „End of file“ erreicht ist.
Du siehst, dass du in keiner Situation ein tatsächliches Strg+D liest. Das bekommst du gar nicht mit. Der Terminalemulator ist normalerweise so eingestellt, dass bei Strg+D geflusht wird und sonst nichts weiter großartig passiert. (– edit: Aha, siehe tracks Link unten: Eigentlich macht das wohl der Terminaltreiber, nicht der Emulator. Wieder was gelernt.)
So, jetzt ist „read()
“ ein Syscall, also die unterste und direkteste Ebene, mit der du mit dem Kernel sprechen kannst. Benutzt du sowas wie „getchar()
“, dann ist das echte „read()
“ ziemlich weit wegabstrahiert worden. Der darunterliegende Mechanismus bleibt aber derselbe.
Guck’ dir nochmal die Doku zu „getchar()
“ an. Da steht:
RETURN VALUE
fgetc(), getc() and getchar() return the character read as an
unsigned char cast to an int or EOF on end of file or error.
Du liest also ein Byte, er liefert dir aber einen Integer zurück. Das heißt, negative Werte sind möglich (und auch Werte über 255, aber das interessiert hier nicht). Die Konstante „EOF
“ ist definiert als eine negative Zahl. Auf das musst du prüfen.
Hier wäre eine Miniversion von „cat
“:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | #include <stdio.h>
int
main()
{
int c;
while ((c = getchar()) != EOF)
{
printf("%c", c);
}
return 0;
}
|
– edit: Gerade gefunden, hier meine Erklärung von vor ~4 Jahren: http://forum.ubuntuusers.de/post/4775552/ 😉