eingabepuffer in c löschen



  • hallo forum.

    in c++ löscht man den eingabepuffer ja so:

    std::cin.clear();
    std::cin.ignore(std::cin.rdbuf()->in_avail());
    std::cin.get();
    

    nun frage ich mich obs ne möglichkeit gibt, das auch in c zu machen. rein
    theorethisch kann man ja mit

    fflush ( stdin );
    

    den puffer löschen,
    was aber nicht zulässig ist (wegen undefined behavior).

    man könnte aber auch mit

    stdin->_cnt = 0;
    

    den counter der zeichen im
    eingabestream auf null setzen, sprich den eingabepuffer löschen. nun wollte ich
    fragen, ob die letzte möglichkeit "sauberer" code ist (kein undefined behavior
    oder so)

    mfg Gaste



  • ist bestimmt undefined, weil 'stdin' theoretisch überall anders aussehen könnte.
    🙂



  • Davon abgesehen dass der C++-Code den gleichen Fehler hat wie fflush(stdin) - nämlich nicht auf allen Plattformen funktionieren - kann man den korrekten C++-Code eigentlich in C nachbilden (ignore muss man emulieren)...

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cin.get();
    
    int c;
    clearerr(stdin); // braucht man imho nichtmal
    while ((c = fgetc(stdin)) != '\n') && c != EOF)
        ;
    fgetc(stdin);
    


  • is wohl so schrieb:

    ist bestimmt undefined, weil 'stdin' theoretisch überall anders aussehen könnte.
    🙂

    meines wissens nach ist stdio ein

    typedef &(_iobuf[0])
    

    , die bei jedem
    programm automatisch angelegt wird (wenn sie überall anders aussehen würde,
    würde printf ja auch nicht funktionieren und somit wäre c dann ja
    plattformahängig, was es nicht ist).

    und _iobuf wird ja so definiert:

    struct _iobuf 
    {
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
    };
    

    also kann stdin nicht immer anders sein, sonst würden ja die ganzen streams
    nicht funktionieren.

    LordJaxom schrieb:

    Davon abgesehen dass der C++-Code den gleichen Fehler hat wie fflush(stdin) - nämlich nicht auf allen Plattformen funktionieren - kann man den korrekten C++-Code eigentlich in C nachbilden (ignore muss man emulieren)...

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cin.get();
    
    int c;
    clearerr(stdin); // braucht man imho nichtmal
    while ((c = fgetc(stdin)) != '\n') && c != EOF)
        ;
    fgetc(stdin);
    

    ich weis schon, dass das so funtkioniert, wollt nur wissen ob meine überlegung
    "sauberer" code ist.



  • Gaste schrieb:

    also kann stdin nicht immer anders sein, sonst würden ja die ganzen streams
    nicht funktionieren.

    wieso nicht? diese 'streams' und die dazugehörigen strukturen gehören nun mal zusammen. das verhalten kann aber auf unterschiedliche weise gecodet worden sein. bei dir ist 'stdin' eine struct, wo anders könnte es einfach eine 'nummer' sein.
    🙂



  • Streams of Blood schrieb:

    Gaste schrieb:

    also kann stdin nicht immer anders sein, sonst würden ja die ganzen streams
    nicht funktionieren.

    wieso nicht? diese 'streams' und die dazugehörigen strukturen gehören nun mal zusammen. das verhalten kann aber auf unterschiedliche weise gecodet worden sein. bei dir ist 'stdin' eine struct, wo anders könnte es einfach eine 'nummer' sein.
    🙂

    wieso sollte nur gerade bei mir stdin das element mit dem index null vom _iobuf
    sein, und woanders eine nummer, das ergiebt überhaupt keinen sinn!! wenn nur bei
    mir stdin das 1. element vom _iobuf ist, warum funktionieren dann die standard-c
    ein und ausgabefunktionen, auf anderen platformen, wo stdin eine nummer ist??
    angenommen stdin ist eine nummer und nicht das typedef (das übrigens so in stdio.h
    steht). woher kommen dann die ganzen daten, zb. die größe des puffers, den
    aktuellen lesezeiger, die anzahl der zeichn im eingabepuffer usw???



  • Gaste schrieb:

    warum funktionieren dann die standard-c ein und ausgabefunktionen, auf anderen platformen, wo stdin eine nummer ist??

    weil jede library-implementierung weiss, was ihre eigenen versionen von stdin, stdout, usw. zu bedeuten haben. der c-code ist nur dann austauschbar, wenn man die standard-funktionen so benutzt, wie's im iso-spec vorgeschrieben ist. sobald man in die eingeweide schaut und dieses wissen nutzt, ist der code bereits nicht mehr portabel (kann natürlich manchmal beabsichtigt sein).
    🙂



  • Was sich hinter einem FILE* verbirgt, ist jedem System selber überlassen - theoretisch könnte da auch ein UNIX File-Deskriptor nach void* gecastet und dir übergeben werden. Wichtig ist nur, daß DEINE File-Funktionen mit DEINEN FILE* zurechtkommen.

    Aber das ist gar nicht das Problem bei fflush(stdin) - der Standard sagt zu fflush(), daß es den Ausgabepuffer eines übergebenen FILE* leeren soll. Was bei reinen Eingabe-Strömen passiert, ist undefined. (und das "bekannte" Verhalten von fflush(stdin); ist eine Erweiterung, die MS definiert hat)



  • CStoll schrieb:

    Was sich hinter einem FILE* verbirgt, ist jedem System selber überlassen - theoretisch könnte da auch ein UNIX File-Deskriptor nach void* gecastet und dir übergeben werden. Wichtig ist nur, daß DEINE File-Funktionen mit DEINEN FILE* zurechtkommen.

    Aber das ist gar nicht das Problem bei fflush(stdin) - der Standard sagt zu fflush(), daß es den Ausgabepuffer eines übergebenen FILE* leeren soll. Was bei reinen Eingabe-Strömen passiert, ist undefined. (und das "bekannte" Verhalten von fflush(stdin); ist eine Erweiterung, die MS definiert hat)

    das mit dem fflush ist mir schon klar, aber ich habe überlegt wenn man mit

    stdin->_cnt = 0;
    

    die anzahl der noch zu lesenden zeichen auf null setzt, dann löscht das sozusagen den puffer. ich wollt jetzt fragen, ob das auch undefined ist.

    mfg Gaste



  • Ja, ist es - schließlich gehört der Inhalt und Aufbau eines FILE zu den Implementierungsdetails des konkreten Compilers (wie gesagt, ein FILE* muß nichtmal ein "echter" Zeiger sein). Portabler geht es sicher mit setvbuf() (siehe die C-Version von "Automatisches Schließen verhindern" in der Konsolen-FAQ).



  • CStoll schrieb:

    (und das "bekannte" Verhalten von fflush(stdin); ist eine Erweiterung, die MS definiert hat)

    wohl eher ein ungewollter nebeneffekt.
    🙂


Anmelden zum Antworten