C stdin clearen; fflush unter Linux?


03.02.2020, 21:36

nvm, Code ist jetzt richtig formatiert.

4 Antworten

  1. fflush() geht auch bei Eingabe-Streams...
  2. aber getchar() kommt nur mit nem Zeichen oder mit EOF zurück, wenn der Stream nicht non-blocking ist...
  3. https://stackoverflow.com/questions/580013/how-do-i-perform-a-non-blocking-fopen-on-a-named-pipe-mkfifo

codinginc 
Beitragsersteller
 03.02.2020, 21:42

fflush geht jedenfalls nicht auf den Linux Servern, auf den es laufen muss :D

Auch mit folgender Funktion klappt es nicht:

void clean_stdin(void)
{
    int c;
    do {
        c = getchar();
    } while (c != '\n' && c != EOF);
}
0
RIDDICC  03.02.2020, 22:15
@codinginc
  1. n EOF kommt na klar erst ganz am Ende... :) also wenn der Stream am Eingang geschlossen ist...
  2. was geht denn bei fflush() nicht? dass es mehr als nur die laufende Zeile flush-t?
0
RIDDICC  03.02.2020, 22:21
@codinginc

oh... ich seh grad: wenn dein fgets() ein '\n' liest, dann kannste auf das nächste na klar lange warten...

0
RIDDICC  03.02.2020, 22:25
@codinginc
#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?

1
codinginc 
Beitragsersteller
 03.02.2020, 22:33
@RIDDICC

Aber was war jetzt der Unterschied zu meinem Ansatz? du machst doch eigentlich genau das selbe :O

0
RIDDICC  03.02.2020, 22:38
@codinginc

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?

1
codinginc 
Beitragsersteller
 03.02.2020, 22:40
@RIDDICC

Nein, aber ich habe

if (!strchr(buf,'\n'))

übersehen :)

Danke übrigens

1
RIDDICC  03.02.2020, 22:44
@codinginc
  1. kicher - ich mach gern „Einzeiler“... sowwy...
  2. np :)
1

Ist ja eine interessante Diskussion.

Was ich nicht verstehe, wer soll denn bei einem Server Eingaben von STDIN veranlassen?

Woher ich das weiß:Berufserfahrung – openSuSE seit 1995

Isendrak  24.05.2020, 10:50

Da gäbe es so einiges. Im einfachsten Fall ein Webserver über CGI.

0
codinginc 
Beitragsersteller
 04.02.2020, 22:17

Sorry, es muss sich auf dem Server kompilieren und ausführen lassen :)

0

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.


codinginc 
Beitragsersteller
 03.02.2020, 21:43

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...

0
KarlRanseierIII  03.02.2020, 21:49
@codinginc

Ä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).

1
codinginc 
Beitragsersteller
 03.02.2020, 21:56
@KarlRanseierIII

Geht leider nicht :) Eingabelänge darf nicht beschränkt werden ...

Ich könnte aber mit getchar und realloc alles einlesen, oder?

0
KarlRanseierIII  03.02.2020, 22:03
@codinginc

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.

0
codinginc 
Beitragsersteller
 03.02.2020, 22:04
@KarlRanseierIII

Ja, eine 2 stellige Zahl sogar nur :D

Ich verstehe aber nicht, warum es mit nur bei 1 Stelligen Eingaben so ein Scheiß macht...

0
KarlRanseierIII  03.02.2020, 22:24
@codinginc
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.

0
codinginc 
Beitragsersteller
 03.02.2020, 22:29
@KarlRanseierIII

Achso... es wurde konsumiert und deswegen hat getchar() auf eine Eingabe gewartet... macht Sinn :D

0
KarlRanseierIII  03.02.2020, 22:31
@KarlRanseierIII

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.ä. .

1
codinginc 
Beitragsersteller
 03.02.2020, 22:39
@KarlRanseierIII

Guter Gedanke, aber unser Prof sieht das nicht so :D

Wer weiß, vielleicht gibt ja mal jemand genau ein Zeichen zu viel ein...

0
KarlRanseierIII  03.02.2020, 22:48
@codinginc

Schon klar, wenn aber so penibel, dann verarbeite bitte auch alle Rückgabewerte entsprechend.

Wenn schon, denn schon.

1
KarlRanseierIII  03.02.2020, 23:17
@codinginc
 if ( fgets(input, 3, stdin) == NULL ){/*Fehlerbehandlung */}

fgets hat einen Rückgabewert, der betrachtet werden muß. getchar ebenso etc. pp. .

1

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.

Woher ich das weiß:Berufserfahrung