fflush (stdin) - nicht die übliche Frage ;-)



  • Hallo zusammen,

    Ich möchte nicht irgendwelche Zeilenumbrüche aus dem Eingabepuffer loswerden oder Ähnliches.

    Meine Fragestellung betrifft folgende Situation:

    Ich habe ein Progrämmlein, das eine Art Liste ausgibt. Dafür habe ich eine gewisse Scrollfunktion gebastelt, die (unter Linux) mit ioctl einzelne Tastendrücke abfängt und somit eben das Scrollen per Pfeiltasten / PgUp etc. ermöglicht.

    Das Problem:
    Kommt der Nutzer auf die Idee, auf CursorDown einzuschlafen, wird er von Drölfundzwanzig Minuten langem Piepsen geweckt, weil der brave Rechenknecht die Eingaben aus dem Tastaturpuffer in einer Schleife abarbeitet. Meine Scrollfunktion piept, wenn das Ende der Liste erreicht ist.

    Mein Wunsch:
    Ich hätte gerne eine relativ verlässlich funktionierende Möglichkeit, "zuviele" Tastatureingaben im Puffer zu unterdrücken, sozusagen soll - als Beispiel - bei 50 unverarbeiteten Eingaben die 51. weggeschmissen werden, bis der Puffer auf 49 unverarbeitete runtergekämpft wurde. Da fflush() ja eigentlich nur für's "Rausschubsen" auf Ausgabestreams gedacht sei, werde ich das Gefühl nicht los, dass meine fflush(stdin)-nach-jeder-angenommenen-Eingabe-Lösung suboptimal ist. Ganz abgesehen davon, dass der Knecht sich trotzdem wundpiepst.

    Ob eine Lösung mit

    setvbuf (stdin, NULL, _IONBF, 0);
    setvbuf (stdin, NULL, _IOFBF, BUFSIZ);
    

    wirklich empfehlenswert ist, wage ich nicht zu beurteilen... Vielleicht hat ja jemand nen Ansatz für mich?



  • Die fflush-Lösung wird unter Linux eh nicht funktionieren, das ist eine reine Microsoft-Erfindung. Überprüf mal den Rückgabewert und errno; du wirst EOF bekommen, und errno wird auf EBADF gesetzt sein.

    Es gibt - und da bewegen wir uns jetzt auf gefährlichen Pfaden - von Solaris her in GNUs glibc eine Funktion __fpurge in <stdio_ext.h>, die den Buffer eines Streams wegschmeißt. In der Manpage steht dazu richtigerweise

    man __fpurge schrieb:

    NOTES
    Usually it is a mistake to want to discard input buffers.

    Du musst dementsprechend mit schiefen Blicken rechnen, wenn du so etwas machst. Ich würde mich an deiner Stelle eher in Richtung non-blocking I/O mit read umsehen - du könntest $GANZ_VIEL Zeichen anfordern und nur die ersten 50 benutzen.



  • PrettyC schrieb:

    setvbuf (stdin, NULL, _IONBF, 0);
    setvbuf (stdin, NULL, _IOFBF, BUFSIZ);
    

    Der 2.Aufruf von setvbuf ist nicht durch den Standard spezifiziert, da setvbuf nur als 1.Operation nach Öffnen der Datei aufgerufen werden soll, er kann also das machen, was du beabsichtigst oder auch nicht.



  • Die phantasievolle Version mit einem gewissen Puffer, einer getchar()-Schleife zum Befüllen des Puffers, Wegwerfen der noch anstehenden Eingaben und ungetc() des befüllten Puffers ist wahrscheinlich etwas abenteuerlich, oder?



  • seldon schrieb:

    Die fflush-Lösung wird unter Linux eh nicht funktionieren, das ist eine reine Microsoft-Erfindung. Überprüf mal den Rückgabewert und errno; du wirst EOF bekommen, und errno wird auf EBADF gesetzt sein.

    Warum sollte fflush eine reine Microsoft-Erfindung sein?
    Im C89 Standard findet fflush (stdio.h). gcc kennt fflush auch.
    In K&R wird fflush ebenfalls beschrieben.
    Oder was hast Du gemeint?



  • Shiba schrieb:

    Oder was hast Du gemeint?

    fflush(stdin) hat er gemeint.



  • Der Final Draft sagt zu fflush() folgendes:
    Zitat:
    7.19.5.2 The fflush function
    Synopsis

    #include <stdio.h>
    int fflush(FILE *stream);
    Description

    If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.

    If stream is a null pointer, the fflush function performs this flushing action on all streams for which the behavior is defined above.

    Returns

    The fflush function sets the error indicator for the stream and returns EOF if a write error occurs, otherwise it returns zero.

    Daraus folgt, das fflush(stdin) ein undefiniertes verhalten an den tag legt.

    Bei mir gibt's nach einem fflush (stdin); ein "Illegal Seek" als Fehlermeldung.
    gcc unter linux. Daraus schlussfolgere ich mal, dass mit stdin nicht viel passiert ist - deckt sich auch mit dem gefühlten Ergebnis.
    Blöd gefragt - das liegt mir nämlich - außer "Kühlschrank auf, Ausräumen, Durchzählen, Einräumen, Kühlschrank zu" gibt's keine Möglichkeit, den "Füllstand" des Eingabepuffers zu erfahren, richtig?



  • Das einräumen wird schwierig, denn ungetc() garantiert nur ein Zeichen zum zurückschieben.
    Es kann aber mit mehreren Zeichen funktionieren.



  • DirkB schrieb:

    Das einräumen wird schwierig

    Das ist dann unpraktisch, weil ich auf eine abgewandelte getchar()-Funktion aus einer shared library zurückgreifen soll, um die Eingaben zu verarbeiten. Demzufolge habe ich auf die Funktionsweise weiter keinen Einfluss, muss mich sozusagen darauf verlassen, dass der Tastaturpuffer in etwa so aussieht wie vor dem Durchzählen 🙂



  • , weil der brave Rechenknecht die Eingaben aus dem Tastaturpuffer in einer Schleife abarbeitet. Meine Scrollfunktion piept, wenn das Ende der Liste erreicht ist
    ...
    sozusagen soll - als Beispiel - bei 50 unverarbeiteten Eingaben die 51. weggeschmissen werden, bis der Puffer auf 49 unverarbeitete runtergekämpft wurde.

    ganz einfach: 💡 zähle die zeichen 💡
    😮



  • [quote="PrettyC"]

    Der Final Draft sagt zu fflush() folgendes:
    Zitat:
    7.19.5.2 The fflush function
    Synopsis
    .....

    Ich hab das stdin nicht erfasst und einfach nur verstanden, dass fflush eine MS-Besonderheit sein sollte.
    Aber das hat Seldon ja nicht gemeint, sondern das ein fflush auf diesen Inputstream eine nicht standardkonforme MS-Spezialität ist.


Anmelden zum Antworten