2016-03-19 11 views
2
// Some initialization code 

dup2(fd[0], fileno(stdin)); 

// This process is receiving the output of "ls -1" 

while (scanf("%[^\n]s", someCharArray) > 0) { 
    scanf("%*c"); 
    printf("%s\n", someCharArray); 
} 

Dadurch werden alle Dateien erfolgreich gedruckt. Die Schleife wird jedoch nie beendet. Wenn ich scanf("%*c") wegnehmen, wird es beendet, aber nur der erste Dateiname wird gedruckt.Warum wird meine scanf while-Schleife nicht beendet, wenn Zeilenumbrüche verwendet werden?

Ich würde erwarten, dass der Verbrauch des Newline-Charakters die äußere scanf vorbereiten wird, um den nächsten Dateinamen zu scannen, was es zu tun scheint. Aber nachdem der letzte Dateiname gescannt wurde, erwarte ich, dass der verschachtelte scanf nichts scannt. Dann die äußere scanf auch nichts zu scannen. Und die while-Schleife wird beendet.

Warum passiert das?

+5

Das 's' am Ende Ihrer Conversion-Spezifizierer tut nicht, was Sie denken, dass es tut. – EOF

+0

Sie möchten vielleicht z. [Diese 'scanf'- (und Familien-) Referenz] (http://en.cppreference.com/w/c/io/fscanf). –

+2

Ich hätte gedacht, nur 'fgets' zu verwenden und das Ausschneiden der neuen Zeile wäre einfacher. – WhozCraig

Antwort

2

Schleife wird nicht beendet, da auf weitere Eingaben gewartet wird.

Sie können

  1. senden ein Paar \n\n so scanf("%[^\n]... 0 zurück, da es die zweite \n oder

  2. schließen stdin (bei einer Implementierung spezifischer Art und Weise), so scanf() Rückkehr zum Scannen nicht EOF , eine negative Zahl.

Besser zu verwenden fgets(). @WhozCraig Es ist zwar immer noch unklar, unter welcher Bedingung die Schleife enden soll (außer stdin Schließung).

while (fgets(someCharArray, sizeof someCharArray, stdin)) { 
    // Lop off potential trailing \n if desired 
    someCharArray[strcspn(someCharArray, "\n")] = '\0'; 

    printf("%s\n", someCharArray); 
} 

Hinweis: Die "s" in scanf("%[^\n]s", someCharArray) hat keinen Zweck - es fallen. Auch dieses Format ohne Breite beschränkt nicht die maximale Anzahl an gescannten Zeichen nach someCharArray und sollte nicht im Qualitätscode verwendet werden.


ich die verzehr des Zeilenende-Marke erwarten würde das äußere Scanf bereiten den nächsten Dateinamen zu scannen, das ist, was es zu tun zu sein scheint.

Ja - das stimmt. In der früheren Version scanf("%[^\n]... gibt es keine Begrenzung für die Anzahl der gescannten Zeichen, die zu undefiniertem Verhalten (UB) führen können. Warum also sollte sich der Rest des Codes verhalten?

Aber nachdem der letzte Dateiname gescannt wurde, erwarte ich, dass der verschachtelte Scanf nichts scannt.

Wenn die letzten endgültigen Dateinamen ein '\n', nachdem es hat, scanf("%*c"); wird es verbrauchen. Wenn der letzte Dateiname kein folgendes Zeichen enthält, wartet scanf("%*c"); geduldig auf einen Charakter. Wenn der Eingangsstrom in der Nähe war, wird EOF zurückgegeben, anstatt zu warten. Code meldet/testet das Ergebnis scanf("%*c"); nicht, so dass wir raten müssen.

Dann der äußere scanf auch nichts zu scannen. Und die while-Schleife wird beendet.

True, wenn das erste Zeichen zu scannen ein '\n' ist, wird es in stdin bleiben und scanf() zurückkehren 0. wenn stdin geschlossen ist, scanf() die negative Zahl EOF zurück.