Was macht fflush(stdin) in der C-Programmierung? [duplicate]

Lesezeit: 5 Minuten

Benutzer-Avatar
C-Grafik

Ich bin sehr neu in der C-Programmierung und versuche zu verstehen, wie fflush(stdin) funktioniert wirklich.

Im folgenden Beispiel tut fflush(stdin) löscht den gesamten Puffer oder löscht es alles, was nach dem dritten Element eingegeben wurde? Was ich meine, ist, dass der Benutzer Kontonummer, Speicherplatz, Name, Speicherplatz und Kontostand eingibt. Stimmt das, dass ab diesem Zeitpunkt alles, was der Benutzer eingibt, gelöscht wird? fflush(stdin)? und stdin wird nicht leer sein.

Warum sage ich das, weil es in eine While-Schleife eintritt und beginnt, in die Textdatei zu schreiben.

Meine zweite Frage ist ob Ctrl-Z weist das Betriebssystem an, den Benutzer nicht mehr zur Eingabe von Eingaben aufzufordern?

printf( "Enter the account name and balance. (separated by spaces)\n" );
  printf( "Enter EOF to end input. (Ctrl-Z)\n" );
  printf( "? " );
  scanf( "%d%s%lf", &account, name, &balance );
  fflush(stdin);

  // write account, name and balance into file with fprintf
  while ( !feof( stdin ) )
  { 
     //fflush(stdin);
     fprintf( cfPtr, "%d %s %.2f\n", account, name, balance );
     printf( "? " );
     scanf( "%d%s%lf", &account, name, &balance );
  }

  fclose( cfPtr );

  • fflush(stdin); ist undefiniertes Verhalten. Tun Sie es nicht, kopieren Sie es nicht von denen, die es tun. stackoverflow.com/questions/2979209/using-fflushstdin

    – Jo

    7. April 2014 um 0:48 Uhr

  • @chrk Stimme dem Hinzufügen des ‘linux’-Tags nicht zu. Nichts in OPs Beitrag ist Linux-spezifisch.

    – chux – Wiedereinsetzung von Monica

    23. Oktober 2015 um 14:39 Uhr

  • @chrk Ja zurücksetzen. Tags sind für das Thema des Beitrags, nicht für die Art von Personen, die suchen.

    – chux – Wiedereinsetzung von Monica

    23. Oktober 2015 um 14:47 Uhr

Benutzer-Avatar
Emmet

Die Antwort darauf ist die fflush(stream) ist nur formal für Ausgabeströme definiert, also fflush(stdout) ist ok, aber fflush(stdin) ist nicht.

Der Zweck von fflush(stream) besteht darin, das Betriebssystem dazu zu bringen, alle Puffer in die zugrunde liegende Datei zu spülen. Als Beispiel für eine legitime Verwendung haben Schüler oft Probleme wie „Meine Eingabeaufforderung wird nicht angezeigt!“. wenn sie so etwas tun:

printf("Enter a number: ");

Sie finden jedoch, dass dies gut funktioniert:

printf("Enter a number:\n");

Natürlich wollen sie nach ihrer Eingabeaufforderung keinen Zeilenumbruch, also haben sie ein kleines Problem.

Der Grund dafür ist, dass die Ausgabe an stdout wird vom Betriebssystem gepuffert und das Standardverhalten besteht (häufig) darin, die Ausgabe nur dann tatsächlich in das Terminal zu schreiben, wenn ein Zeilenumbruch auftritt. Hinzufügen eines fflush(stdout) nach dem printf() löst das Problem:

printf("Enter a number: ");
fflush(stdout);

Nun, wenn man analog arbeitet, denken die Leute das oft fflush(stdin) sollte alle ungenutzten Eingaben verwerfen, aber wenn Sie ein wenig darüber nachdenken, macht das nicht viel Sinn. Was bedeutet es, einen Eingabepuffer zu „leeren“? Wo wird “gespült” zu? Wenn Sie einen Ausgabepuffer leeren, wird die Ausgabe an die zugrunde liegende Datei oder das Terminal gesendet, wo sie schließlich sowieso landen würde, aber wo würde Eingang „irgendwann trotzdem enden“? Es gibt keine Möglichkeit zu wissen! Wie soll sich verhalten, wenn die Eingabestromdaten aus einer Datei, einer Pipe oder einem Socket stammen? Es ist nicht überhaupt klar für Input-Streams, was das Verhalten von fflush() sein sollte, aber es ist für Ausgangsströme in allen Fällen sehr klar. Somit, fflush() ist nur für Ausgabestreams definiert.

Der Grund für die fehlerhafte Verwendung von fflush(stdin) Alltäglich geworden ist, dass vor vielen Jahren ein paar Betriebssysteme tat Implementieren Sie ein Schema, bei dem es so funktioniert hat, wie viele Leute es erwartet haben, und verwerfen Sie nicht verwendete Eingaben. Microsoft-DOS ist ein gutes Beispiel. Überraschenderweise sind moderne Versionen von Linux auch umsetzen fflush() für Eingangsströme.

Das Richtige, um mit „zusätzlichen“ unerwünschten Terminaleingaben umzugehen, ist, sie einfach zu lesen und nichts damit zu tun. Das ist fast so einfach wie anrufen fflush(stdin)funktioniert überall und verlässt sich nicht auf formal undefiniertes Verhalten.

Das C Standard sagt:

Wenn stream zeigt auf einen Ausgabestream oder ein Aktualisierungsstrom, in den die letzte Operation nicht eingegeben wurde, bewirkt die Flush-Funktion, dass alle ungeschriebenen Daten für diesen Strom, die an die Hostumgebung geliefert werden sollen, in die Datei geschrieben werden; andernfalls ist das Verhalten undefiniert.

POSIX sagt (bezieht sich auch explizit auf C Standard):

Wenn stream zeigt auf einen Ausgabestream oder ein Update-Stream, in den die letzte Operation nicht eingegeben wurde, soll fflush() bewirken, dass alle ungeschriebenen Daten für diesen Stream in die Datei geschrieben werden, …

Aber die Linux-Manpage sagt:

Für Ausgabestreams erzwingt fflush() ein Schreiben aller im Userspace gepufferten Daten für den gegebenen Ausgabe- oder Aktualisierungsstream über die zugrunde liegende Schreibfunktion des Streams. Bei Eingabestreams verwirft fflush() alle gepufferten Daten, die aus der zugrunde liegenden Datei abgerufen, aber nicht von der Anwendung verwendet wurden. Der offene Status des Streams bleibt davon unberührt.

  • Es kann nützlich sein, darauf hinzuweisen, dass dies (Linux bietet eine Definition für ansonsten undefiniertes Verhalten) eine implementierungsspezifische Erweiterung ist und von Personen vermieden werden sollte, die an portablem Code interessiert sind.

    – Das ist nicht mein richtiger Name

    7. April 2014 um 3:42 Uhr

  • @Emmet, wie du erwähnt hast, brauchst du fflush(stdout); aber es geht auch ohne. können Sie einen bestimmten Fall angeben, in dem der Puffer nicht so voll ist printf kann nicht auf dem Bildschirm drucken.

    – Abhishek Mähne

    15. Juni 2021 um 7:15 Uhr

  • @Emmet übrigens danke ich habe deine Erklärung vergessen fflush(stdin) ist genial, es ist nur eine klare Erklärung.

    – Abhishek Mähne

    15. Juni 2021 um 7:16 Uhr

fflush(stdin) ruft undefiniertes Verhalten auf.

fflush() ist nur für Ausgabeströme definiert. Sie sollten es nicht tun.


Unter Unix sendet Strg-Z ein TSTP-Signal (SIGTSTP), das standardmäßig bewirkt, dass der Prozess die Ausführung anhält.

1352740cookie-checkWas macht fflush(stdin) in der C-Programmierung? [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy