2012-08-14 7 views
7

Hier ist mein Code. Ich betreibe es in Ubuntu mit Terminal. Wenn ich im Terminal ein (CtrlD) eintippte, stoppte das Programm nicht, aber wartete weiter auf meine Eingabe.ctrl-d hat die while nicht gestoppt (getchar()! = EOF) Schleife

Ist das nicht CtrlD gleich EOF in Unix?

Vielen Dank.

#include<stdio.h> 

main() { 
    int d; 
    while(d=getchar()!=EOF) { 
     printf("\"getchar()!=EOF\" result is %d\n", d); 
     printf("EOF:%d\n", EOF); 
    } 
     printf("\"getchar()!=EOF\" result is %d\n", d); 
} 
+1

Das ist keine Rekursion. Es ist nur eine Endlosschleife, bis Sie die Eingabe beenden. Recursion = Funktion, die sich direkt oder nach einer anderen Anzahl von Zwischenschritten aufruft. –

+0

Kompiliert, dass mit gcc, schlug '^ D' die Schleife für mich. –

+0

@JonLin Einfach eingeben^D .Es funktioniert auch für mich. Wenn die Eingabe jedoch (a^D) ist, wurde die Schleife nicht angehalten. – Sam

Antwort

11

EOF ist kein Zeichen. Das EOF ist ein Makro, das getchar() zurückgibt, wenn es das Ende der Eingabe erreicht oder auf eine Art von Fehler stößt. Die ^D ist kein "EOF-Zeichen". Was unter Linux passiert, wenn Sie in einer Zeile auf^D drücken, ist, dass es den Stream schließt und der getchar() Aufruf das Ende der Eingabe erreicht und das EOF Makro zurückgibt. Wenn Sie ^D irgendwo in der Mitte einer Zeile eingeben, wird der Stream nicht geschlossen, daher gibt getchar() Werte zurück, die gelesen wurden, und Ihre Schleife wird nicht beendet.

Siehe die stdio section of the C faq für eine bessere Beschreibung.

Zusätzlich:

Auf moderne Systemen ist es nicht reflektiert ein tatsächliches End-of-Datei Zeichen in einer Datei gespeichert; es ist ein Signal, dass keine Zeichen mehr verfügbar sind.

+0

Ich lese sorgfältig die Website. Meiner Meinung nach, wenn ich '^ D' irgendwo in der Mitte einer Zeile tippe, wird Bash '^ D' angehen. Daher hat das C-Programm keinen Befehl zum Schließen des Streams erhalten. Wenn ich '^ D' in eine Zeile eintippe, erhält das C-Programm den richtigen Befehl. Habe ich recht? – Sam

+1

@qingfeng Es gibt ein bisschen mehr über '^ D' hier: http://www.c-faq.com/stdio/eofval.html Aber ja, der Stream wird nicht geschlossen, es sei denn, es ist in einer Zeile für sich. Kurze Erklärung hier: http://StackOverflow.com/a/1516177/851273 –

+6

Wenn das Terminal im kanonischen Modus ist, werden Linien nicht über das TTY-Gerät übertragen, bis Sie Enter drücken. Durch Drücken der konfigurierten EOF-Taste (standardmäßig^D) werden die Daten sofort übertragen und alle darauf wartenden "Lesevorgänge" werden mit der Anzahl der verfügbaren Zeichen zurückgegeben. Wenn die Zeile bereits Daten enthält, handelt es sich um eine normale, von Null verschiedene Länge. Wenn die Zeile leer ist, führt dies zu einem Lesen der Länge Null, bei dem es sich um die * Definition * des Dateiende-Status für einen Dateideskriptor handelt. Daher wird die stdio-Ebene sie als EOF-Status interpretieren. –

6

Zusätzlich zu Jon Lins Antwort über EOF bin ich mir nicht sicher, ob der von Ihnen geschriebene Code das ist, was Sie beabsichtigt haben. Wenn Sie den Wert zurück von getchar in der Variablen d sehen wollen, müssen Sie Ihre while Aussage ändern:

while((d=getchar())!=EOF) { 

Dies liegt daran, die Ungleichheitsoperator höhere Priorität als Zuordnung hat. In Ihrem Code wäre also d immer entweder 0 oder 1.

+0

Es ist sehr freundlich von Ihnen, so akribisch zu sein. Aber ich möchte nur bestätigen, dass der Ausdruck "d = getchar()! = EOF" 0 oder 1 ist. – Sam

+0

@Sam: Sie können deutlich machen, dass Sie das Ergebnis des Vergleichs schreiben: 'while ((d = (getchar()! = EOF))! = 0) 'oder as 'while ((= (getchar()! = EOF))), damit der Compiler keine Warnungen an Sie richtet. Die gebräuchlichere Alternative ist 'while ((d = getchar())! = EOF)', die das Ergebnis von 'getchar()' zu 'd' zuordnet und dann mit EOF vergleicht. Das vermeidet Compiler-Warnungen. Viele moderne Compiler werden eine Warnung für das, was Sie geschrieben haben, generieren. –

Verwandte Themen