C stdin clearen; fflush unter Linux?
Hallo, mein Programm läuft unter Windows. Dort nehme ich fflush um stdin zu leeren.
Unter Linux geht das so nicht, und ich weiß nicht, wie ich es sonst machen soll.
https://onlinegdb.com/H1TLXWIzL
Gibt man z.B. immer 222 ein, so kommt direkt danach die Ausgabe "Test" (So ist es richtig)
Gibt man aber immer nur eine 2 ein, so geschieht das erst alle 2 Zeilen. (Falsch)
Laut Debugger bin ich stuck in der while Schleife, welche stdin leer machen soll. Hat wer ne Idee wie ich das beheben kann?
#include <stdio.h>
#include <stdlib.h>
int test(){
char input[3];
for(;;){
fgets(input, 3, stdin);
if(input[0] == '1'){
return atoi(input);
}
printf("Test\n");
while ((getchar()) != '\n');
/*fflush(stdin);*/
}
}
int main() {
int inp;
inp = test();
printf("%d", inp);
return 0;
}
nvm, Code ist jetzt richtig formatiert.
4 Antworten
- fflush() geht auch bei Eingabe-Streams...
- aber getchar() kommt nur mit nem Zeichen oder mit EOF zurück, wenn der Stream nicht non-blocking ist...
- https://stackoverflow.com/questions/580013/how-do-i-perform-a-non-blocking-fopen-on-a-named-pipe-mkfifo
- n EOF kommt na klar erst ganz am Ende... :) also wenn der Stream am Eingang geschlossen ist...
- was geht denn bei fflush() nicht? dass es mehr als nur die laufende Zeile flush-t?
oh... ich seh grad: wenn dein fgets() ein '\n' liest, dann kannste auf das nächste na klar lange warten...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
for (;;) {
printf("wassup? "); fflush(stdout);
char buf[3]; fgets(buf, 3, stdin);
if (buf[0]=='1') printf("\tread %d\n",atoi(buf));
if (!strchr(buf,'\n')) for (;;) { int ch=getchar(); if (ch=='\n' || ch<0) break; }
}
return 0;
}
so?
oben schrieb ich:
oh... ich seh grad: wenn dein fgets() ein '\n' liest, dann kannste auf das nächste na klar lange warten...
hast es übersehn? oder isses unverständlich?
Ist ja eine interessante Diskussion.
Was ich nicht verstehe, wer soll denn bei einem Server Eingaben von STDIN veranlassen?
Sorry, es muss sich auf dem Server kompilieren und ausführen lassen :)
fflush(stdin) ist undefiniert im Verhalten, selbst wenn es bei manchem Compiler funktioniert. Es ist auch egal, welche Platform man vor sich hat.
Die einzige Möglichkeit ist erschöpfendes Lesen des Buffers bis zum nächsten \n, wenn man portabel sein möchte.
Es würde reichen, auf den Linux Servern zu laufen.
Was könnte ich verändern, damit es funktioniert? Weil eigentlich lese ich doch stdin bis zum \n aus...
Ändere Deien Logik etwas:
Nutze fgets() zusammen mit einem Linebuffer, der ausreichend groß für eine Zeile ist. Dadurch gewährleistest Du, daß die gesamte Zeile bis \n eingelesen wird.
Auf das fflush() kannst Du hierdurch gänzlich verzichten.
Schiefgehen würde das dann lediglich, wenn das erste \n erst nach mehr Zeichen erscheint, als in den Linebuffer passen (bzw. Linebuffer-1).
Geht leider nicht :) Eingabelänge darf nicht beschränkt werden ...
Ich könnte aber mit getchar und realloc alles einlesen, oder?
Du kannst auch mit fgets() in chunks arbeiten - nur bei Deinem Beispiel interessiert Du Dich doch anscheinend nur für eine dreistellige Zahl?
Alternative wäre dann nur noch den C-Standard zu verlassen.
Ja, eine 2 stellige Zahl sogar nur :D
Ich verstehe aber nicht, warum es mit nur bei 1 Stelligen Eingaben so ein Scheiß macht...
fgets(input, 3, stdin);
bedeutet ja nicht anderes als lese bis zu 2 Zeichen aus stdin nach input.
Danach liest Du bis zum nächsten \n, egal ob es konsumiert wurde oder nicht.
Achso... es wurde konsumiert und deswegen hat getchar() auf eine Eingabe gewartet... macht Sinn :D
Schauen wir mal:
if ( strchr(input , '\n') == NULL ) while ( getchar()!= '\n') ;
Wenn fgets() also noch kein \n gesehen hat und die Zeile nicht komplett aus dem Eigabepuffer gelesen wurde, konsumiere alle Zeichen bis \n.
So sollte das wohl besser klappen.
P.S.: Deswegen sagte ich, es ist im Zweifelsfall einfacher eien ganze Zeile zu konsumieren, solange die Zeilenlänge nicht exobitant ist. Input könnte ja 8K sein, o.ä. .
Guter Gedanke, aber unser Prof sieht das nicht so :D
Wer weiß, vielleicht gibt ja mal jemand genau ein Zeichen zu viel ein...
Schon klar, wenn aber so penibel, dann verarbeite bitte auch alle Rückgabewerte entsprechend.
Wenn schon, denn schon.
if ( fgets(input, 3, stdin) == NULL ){/*Fehlerbehandlung */}
fgets hat einen Rückgabewert, der betrachtet werden muß. getchar ebenso etc. pp. .
Das Ganze portabel und sauber hinzubekommen ist ein absoluter Krampf.
Verwende am besten Systembibliotheken oder anstelle von einer Zeile mit fflush(stdin) das hier:
stdin = freopen(NULL, "r", stdin);
Vergiss dabei die Fehlerbehandlung nicht und behalte den Performanceoverhead im Auge.
fflush geht jedenfalls nicht auf den Linux Servern, auf den es laufen muss :D
Auch mit folgender Funktion klappt es nicht: