Ich lerne gerade C mit dem Buch von Kernighan und Ritchie; Ich bin in den Grundlagen des vierten Kapitels (“Funktionen und Programmstruktur”). Neulich wurde ich neugierig auf die sleep() Funktion, also habe ich versucht, es so zu verwenden:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
printf(" I like cows.");
sleep(5);
return 0;
}
Das Problem ist die Ausgabe des Programms, so wie es aussieht tut es das sleep() zuerst und dann die printf(), mit anderen Worten, es wartet fünf Sekunden und gibt dann die Zeichenfolge aus. Also dachte ich, vielleicht kommt das Programm zu sleep() so schnell, dass es nicht zulässt printf() seine Arbeit so erledigen lassen, wie ich es will, das heißt, den String drucken und dann schlafen.
Wie kann ich die Zeichenfolge anzeigen und das Programm dann in den Ruhezustand versetzen? Der Compiler ist GCC 3.3.5 (propolice) in OpenBSD 4.3.
Robert Glück
printf() schreibt an stdout (der Standardausgabestrom), der normalerweise zeilengepuffert ist. Der Puffer wird von der Zeit nicht geleert sleep wird aufgerufen, sodass nichts angezeigt wird, wenn das Programm beendet wird, werden alle Streams automatisch geleert, weshalb es direkt vor dem Beenden gedruckt wird. Das Drucken eines Zeilenumbruchs führt normalerweise dazu, dass der Stream geleert wird, alternativ können Sie die verwenden fflush Funktion:
int main(void)
{
printf(" I like cows.\n");
sleep(5);
return 0;
}
oder:
int main(void)
{
printf(" I like cows.");
fflush(stdout);
sleep(5);
return 0;
}
Wenn Sie in einen Stream drucken, der nicht zeilengepuffert ist, wie dies der Fall sein kann, wenn stdout umgeleitet wird oder Sie in eine Datei schreiben, wird es wahrscheinlich nicht funktionieren, einfach einen Zeilenumbruch zu drucken. In solchen Fällen sollten Sie verwenden fflush wenn Sie möchten, dass die Daten sofort geschrieben werden.
Der Grund, warum das Hinzufügen eines \n zur Zeichenfolge funktioniert, ist, dass printf an die Konsole zeilengepuffert ist. Wenn Sie es jedoch in eine Datei umleiten, reicht dies möglicherweise nicht aus, da ein anderes Pufferschema verwendet wird.
– Paul Tomblin
3. Dezember 2008 um 18:48 Uhr
Eine interessante Frage ist dann, wie können Sie feststellen, welchen Puffermodus Ihr aktueller Dateizeiger verwendet?
– Vinko Vrsalović ♦
3. Dezember 2008 um 18:54 Uhr
@Paul, richtig, deshalb habe ich gesagt, dass es so sein wird normalerweise verursachen, dass der Stream gespült wird, aber ich werde weitermachen und klären.
– Robert Gamble
3. Dezember 2008 um 18:55 Uhr
@Vinko, es gibt keine Standardfunktion, die Ihnen sagt, was der Puffermodus für einen Stream ist, aber viele Implementierungen haben ihre eigenen Funktionen (glibc hat zum Beispiel __flbf und __fbufsize).
– Robert Gamble
3. Dezember 2008 um 19:14 Uhr
@RobertGamble, nun, das hatte ich gelernt fflush (stdout) ist undefiniertes Verhalten.
– Kiste Kiste Kiste Kiste
9. Februar 2016 um 14:32 Uhr
Paul Tomblin
Ihr Problem ist, dass printf (und alles andere, das die stdio-Bibliothek zum Schreiben in stdout (Standardausgabe) verwendet) gepuffert wird – zeilengepuffert, wenn es an die Konsole geht, und größengepuffert, wenn es an eine Datei geht. Wenn Sie eine fflush(stdout); nach dem printf, es wird tun, was Sie wollen. Sie könnten versuchen, Ihrer Zeichenfolge einfach einen Zeilenumbruch (‘\n’) hinzuzufügen, und das würde das Richtige tun, solange Sie die Standardausgabe nicht in eine Datei umleiten.
Ich bin mir nicht 100% sicher, aber ich denke stderr nicht gepuffert, was zu Verwirrung führen kann, da Sie möglicherweise die Ausgabe sehen, die Sie erstellt haben stderr vor der Ausgabe, die Sie zuvor vorgenommen haben stdout.
printf wird nicht gepuffert, der Stream, in den es schreibt, ist es.
– Robert Gamble
3. Dezember 2008 um 18:47 Uhr
stderr ist normalerweise ungepuffert (obwohl es zeilengepuffert sein kann).
– Robert Gamble
3. Dezember 2008 um 19:04 Uhr
Warum funktioniert der Zeilenumbruch (‘\n’)?
– Gonidelis
9. April 2019 um 22:24 Uhr
@johngonidelis, weil es, wie ich bereits sagte, zeilengepuffert ist. Wenn es das Ende einer Zeile sieht, löscht es den Puffer.
– Paul Tomblin
10. April 2019 um 12:50 Uhr
Vinko Vrsalović
Pufferung bedeutet, dass die gesamte Ausgabe an einem Ort (Puffer genannt) gespeichert und ausgegeben wird, nachdem eine bestimmte Datenmenge darin vorhanden ist. Dies geschieht aus Effizienzgründen.
Einige (die meisten?) Implementierungen löschen den Puffer nach einem Zeilenumbruch beim Schreiben auf die Konsole, also können Sie es auch versuchen
printf(" I like cows.\n");
anstelle des Aufrufs von fflush()
Ich habe die Zeitbegegnung wie folgt implementiert;
for (int i = 1; i <= 60; i++) {
printf("%02d", i);
fflush(stdout);
sleep(1);
printf("\b\b");
}
13112300cookie-checkWarum druckt printf() nichts vor sleep()?yes