2017-03-12 10 views
1

Für mein Programm habe ich eine schnelleVerwenden EOF in der Mitte einer Eingabezeile?

> 

und dann mein Programm liest aus stdin nach stdout. Die Eingabeaufforderung wird ausgeführt, wenn EOF nicht erreicht wurde. Ich habe festgestellt, wenn ich etwas eingeben, wie zum Beispiel:

> bee 

Wenn ich einmal STRG-D drücken, passiert nichts. Wenn ich erneut CTRL-D drücke, erscheint meine Eingabeaufforderung erneut. Und nur wenn ich es ein drittes Mal drücke, endet mein Programm aufgrund von EOF. Bedeutet das, dass ein Problem in meinem Code vorliegt? Oder ist das normales Verhalten?

Heres eine vereinfachte Version von meinem Code:

(fopen used) 
(print prompt) 
while((fgets(tester, 1026, input)) != NULL) { 
    if(there is a # in tester) { 
    (print prompt)   
    continue; 
    } 
} 
+1

Problem in welchem ​​Code? – Shark

+0

Die 'Strg + D' (Linux) oder' Strg + Z' (Windows) müssen der erste Tastendruck nach einer 'Newline' sein. Trotzdem habe ich ähnliche Kuriositäten bemerkt, die ich nicht lösen konnte. –

+1

Dieser Pseudocode-Mix kompiliert nicht, und der einzige Teil, der zu analysieren scheint, hat einen Klammer-Mismatch. Bitte poste ein minimales, vollständiges Beispiel. – dlatikay

Antwort

0

In einem Unix-Terminal, CTRL-D tut nichts mehr oder weniger als sofort alle Bytes in den Terminals Eingangspuffer anhängig senden.


Hintergrund:

Normalerweise, wenn Sie Dinge in Ihrem Terminal eingeben, wird das Zeug Zeile gepuffert, so dass Sie eine Linie Bearbeitung halten können, bis Sie mit ihm zufrieden sind, und dann senden der laufende Prozess durch Eingabe eines Newline (oder STRG-D, der Unterschied ist nur, dass STRG-D am Ende kein Newline-Zeichen hinzufügt).

Jetzt erkennen Prozesse das Ende eines Eingabedatenstroms, indem sie überprüfen, ob der Aufruf read() irgendetwas zurückgibt. Wenn Sie also STRG-D in einem leeren Eingabepuffer drücken, wird der Aufruf read() mit nichts zurückgegeben, und der Prozess denkt, dass "keine Bytes mehr aus diesem Stream kommen, ich sollte es besser nicht versuchen". Afaik, gibt es keine andere Möglichkeit, auf das Ende eines Eingabestroms zu prüfen, so dass alle Programme, die EOF auf stdin erkennen, dies entweder direkt oder über die Standard-C-Bibliothek tun. Das ist das, was Sie getan haben, als Sie fgets() angerufen haben.


Ihr Fall:

  1. Die erste CTRL-D sendet einfach die drei Zeichen "Biene", um Ihren Prozess. Der read() Aufruf innerhalb Ihres fgets() Aufrufs gibt diese drei Zeichen zurück und Ihre fgets() Implementierung prüft auf ein Zeilenumbruchzeichen. Da es keinen findet und sein eigener Ausgabepuffer noch nicht voll ist, ruft er sofort weitere Zeichen mit einem anderen read() Aufruf ab.

  2. Das zweite CTRL-D sendet nichts, da Sie seit dem letzten CTRL-D keine anderen Zeichen eingegeben haben. Der write() Aufruf kehrt ohne Ausgabe zurück, die fgets() sieht, dass es null Zeichen erhielt, und ruft es eine EOF-Bedingung auf. Es gibt also die (meist gepufferte) Zeichenkette "bee" an Sie zurück.

    Ihr Programm überprüft möglicherweise, ob diese Zeichenfolge ein #-Zeichen enthält. Aber seine Schleife kann nicht enden, bis ein fgets() Aufruf NULL zurückgibt (es gibt keine break Anweisung, die Schleife vorläufig zu verlassen).

  3. Die dritte CTRL-D-Datei sendet null Bytes an Ihren Prozess.Dies führt dazu, dass der erste read()-Aufruf des zweiten fgets()-Aufrufs Null-Bytes zurückgibt (die Schleife wird nach einer erfolgreichen ersten Iteration erneut eingegeben). Die Implementierung fgets() sieht die leeren Ergebnisse und da es feststellt, dass es noch keine Bytes empfangen hat, gibt es NULL zurück. Ihre Schleifenbedingung sieht die NULL und beendet die Schleife, die wiederum Ihr main() zurückgibt, den Prozess verlassend.


TL; DR:

Ja, das ist völlig Verhalten erwartet, obwohl es eher kontraintuitiv erscheint. Das ist UNIX: Es ist KISS, nicht unbedingt intuitiv.