Was tun mit Fehlern in den FAQ?



  • ZB hier:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-111042.html

    SideWinder schrieb:

    Wer auf Punkt 2 verzichten kann (das Programm wartet dann auf das nächste "Enter") ist mit folgender standard-kompatibler Funktion gut bedient:

    // C-Version
    #include <stdio.h>
    
    void wait ()
    {
        setvbuf(stdin,NULL,_IONBF,0);
        setvbuf(stdin,NULL,_IOFBF,BUFSIZ);
        getchar();
    }
    

    ...
    PS: Wenn ihr Fehler findet, meldet euch bitte umgehend.

    So weit so gut, nur wie meldet man sich eigentlich? Ein Email-Weg war auf die Schnelle nicht zu finden.

    Ich hab oft und gerne auf den FAQ-Eintrag verwiesen, und bin heute darauf hingewiesen worden, dass er falsch sein könnte. Hab dann nachgelesen, und bin jetzt ziemlich sicher dass er falsch ist. Begründung hier:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-263244-and-start-is-10.html
    🙂



  • Was tun mit Fehlern in den FAQ?

    Am einfachsten wäre es, wir benennen die FAQ um in FFM ( Frequently Made Mistakes ).

    Gruß,
    B.B.



  • Oder hier:

    SideWinder schrieb:

    #include <iostream>
    
    void wait ()
    {
        std::cin.clear();
        std::cin.ignore(std::cin.rdbuf()->in_avail());
        std::cin.get();
    }
    

    Die C++-Version löscht zuerst alle Fehlbits die eine Eingabe verhindern könnten und ignoriert dann soviele Zeichen wie im Puffer vorhanden sind.

    Problem hier ist, dass der Puffer u.U. noch nicht in der Standardbibliothek "angekommen" ist, sprich die Zeichen noch im Puffer des Bestriebssystems liegen. Besser ist folgende Variante:

    #include <iostream>
    #include <limits>
    
    void wait ()
    {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cin.get();
    }
    

    Sie löscht zuerst alle Fehlbits die eine Eingabe verhindern könnten und ignoriert dann soviele Zeichen (auch jene, die noch nicht im Puffer sind) bis ein Zeilenende (Return) gelesen wurde.



  • LordJaxom schrieb:

    Sie löscht zuerst alle Fehlbits die eine Eingabe verhindern könnten und ignoriert dann soviele Zeichen (auch jene, die noch nicht im Puffer sind) bis ein Zeilenende (Return) gelesen wurde.

    Also ist es in C++ gar nicht möglich, einfach alle Zeichen, die gerade im Puffer liegen, zu verwerfen? Es sieht aus, als müsste man bis auf ein bestimmtes Zeichen warten.

    Ich glaube, dass es auch in C keine Möglichkeit gibt, alle Zeichen zu verwerfen, d.h. man muss auch dort bis zum nächsten Return warten, zB so:

    int c;
    while ((c = getchar()) != EOF && c != '\n')
        ;
    

    Stimmt doch, oder?
    🙂

    Edit: Grammatik



  • Noch was: die FILE-Zeiger von C und die iostreams von C++ verwenden in jedem Fall verschiedene Puffer, oder?
    🙂



  • Tatsächlich? Oha, das wurde damals sehr sehr lange diskutiert um zu diesem Ergebnis zu kommen.

    Also du kannst dich auf jeden Fall immer via E-Mail beim Autor des Eintrages melden 🙂

    Also die C++-Variante kann ich ja auf die Version von LordJaxom umändern. Wobei ich mir *SEHR* sicher bin, dass mir damals HumeSikkins gesagt hat, dass dieser Weg auch nicht immer geht und eben deswegen der andere zu empfehlen sei...

    Wie funktioniert dann aber nun die korrekte C-Version? Bisher konnte man mit diesem Konstrukt immer helfen.

    @mngbd: Ja, die Puffern beide intern. Aber es gibt irgendeine Möglichkeit afaik diese beiden Puffer zu synchronisieren (von C++-Seite her). Das bringt uns aber wenig, wenn wir keine C-Variante haben 🙂

    Also gibt es eine verbesserte C-Variante? Eine die in häufigeren Fällen funktioniert?

    MfG SideWinder



  • Habt ihr das auch probiert?

    Also die C++-Variante funktioniert bei mir im VC 2008 (die bisher in der FAQ steht).

    Es haben nur beide den Bug, dass falls noch gar keine Eingabe erfolgt ist ein doppeltes Bestätigen mit Enter nötig ist (das hat aber auch die hier neu angebotene Variante inkludiert...).

    MfG SideWinder



  • SideWinder schrieb:

    Also du kannst dich auf jeden Fall immer via E-Mail beim Autor des Eintrages melden 🙂

    Tut mir leid, wenn ich dich da übergangen habe. Aber in deinem Profil konnte ich keinen Email-Kontakt finden (vielleicht hab ich was übersehen), und in #c++ auf EuIRC hab ich dich auch nicht getroffen (dort trifft man manche von den Wiederholungstätern).

    SideWinder schrieb:

    Wie funktioniert dann aber nun die korrekte C-Version? Bisher konnte man mit diesem Konstrukt immer helfen.

    Ich weiss nichts besseres, als mit getchar() bis zum nächsten Return zu lesen. Das Problem an setvbuf() ist, dass C99 sagt, dass man das nur machen darf, solange man noch nicht von dem stream gelesen hat, sonst ist es undefiniertes Verhalten (TC2 7.19.5.6). Man könnte zwar die Pufferung von Anfang an zeichenweise machen, aber das ist offenbar auch keine Lösung.

    SideWinder schrieb:

    Habt ihr das auch probiert?

    Also die C++-Variante funktioniert bei mir im VC 2008 (die bisher in der FAQ steht).

    Bei mir funktionieren sie auch beide (auf einen GNU-System mit dem gcc). Aber zumindest die C-Variante ist leider nicht standardkonform, wenn ich das richtig verstanden habe (wobei ich mir ziemlich sicher bin). Mit C++ kenn ich mich nicht gut genug aus, um dazu was zu sagen.
    🙂



  • SideWinder schrieb:

    Also die C++-Variante funktioniert bei mir im VC 2008 (die bisher in der FAQ steht).

    Nach meiner Erfahrung funktioniert die C++-Variante bisher immer zuverlässig. Die Variante mit in_avail funktioniert dagegen nicht bei jedem Compiler zuverlässig.

    Es haben nur beide den Bug, dass falls noch gar keine Eingabe erfolgt ist ein doppeltes Bestätigen mit Enter nötig ist (das hat aber auch die hier neu angebotene Variante inkludiert...).

    Genauergesagt reicht in Fällen, wo die vorherige Eingabe bereits das Whitespace '\n' abgeräumt und keine Fehlerbits gesetzt hat, ein einfaches cin.get(). Das führt natürlich trotzdem dazu, dass die Variante nicht 100% zuverlässig ist.



  • Bei welchen Compilern funktioniert es nicht?

    Welche Verbesserungsvorschläge gibt es? Warum ist in_avail() nun schlechter als max()? Was genau passiert bei zweiterem unter der Haube anders?

    Welche anderen Vorschläge gibt es für C?

    Solange es nichts besseres gibt weiß ich nicht wirklich was ich sonst in die FAQ stellen soll 😞 Einfach den Thread ganz herausnehmen obwohl bei den meisten Anwendern alles läuft will ich nun auch nicht.

    MfG SideWinder



  • SideWinder schrieb:

    Welche anderen Vorschläge gibt es für C?

    Ich fürchte: gar keine. Jedenfalls finde ich nichts dergleichen.

    Aber was C angeht: die getchar()-Variante hält ohnehin, was der FAQ-Text verspricht, nämlich alles bis zum nächsten '\n' loszuwerden. Mein Vorschlag: einfach die setvbuf()-Variante rausnehmen und die getchar()-Variante hineingeben.

    Bleibt noch das C++-Problem...
    🙂



  • Wegen C++: im Notfall könnte man's eigentlich genauso wie in C machen: solange zeichenweise lesen, bis das Zeichen ein '\n' ist. Für die system-abhängigen Lösungen kommt unten ohnehin noch ein eigener Abschnitt.
    🙂



  • Habe mir notiert den Text über die Feiertage zu überarbeiten, die zweite C++-Version als Alternative einzufügen sowie der C-Version ein Rufzeichen voran zustellen.

    MfG SideWinder



  • Es wäre vielleicht auch eine gute Idee, einen Link hierhin zu setzen, als Alternativ-Vorschlag:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-39349-and-start-is-1.html

    Ich würde zumindest ein Rufzeichen vor den C-Code setzen, weil ja der Standard ganz deutlich sagt, dass er zu undefiniertem Verhalten führt. Dass der Code funktioniert ist einfach eine Folge der üblichen Implementationen, etwa so, wie dass man mit longjmp() in manchen Fällen nach innen springen kann. Standardkonform ist das aber in beiden Fällen nicht.
    🙂



  • Ich habe den FAQ-Artikel nun überarbeitet:
    http://www.c-plusplus.net/forum/viewtopic-var-p-is-797103.html

    Allerdings:
    @mngbd: Diese Version liest nur eine Zeile aus dem Puffer, außerdem könnte der Puffer auch leer sein.

    @LordJaxom: Deine Variante habe ich nur als Alternative angegeben, da bei mir beide Versionen funktionieren und die rdbuf()-Variante nicht das Problem hat, dass zwei Enter notwendig sind wenn noch gar nie eingelesen wurde.

    Bitte seht euch den Artikel an und gebt weitere Vorschläge/Feedback ab 🙂

    Vielen Dank nochmal für eure Hinweise.

    MfG SideWinder



  • SideWinder schrieb:

    @mngbd: Diese Version liest nur eine Zeile aus dem Puffer, außerdem könnte der Puffer auch leer sein.

    Das stimmt, hmm... ich denke nochmal in Ruhe darüber nach.

    Ob man da vielleicht was mit getc()/ungetc() tricksen könnte? Ich weiss es nicht.

    Langsam glaub ich, dass die C-Pufferung einfach broken design ist. Ein kleines Standard-Makro, das nachsieht, ob etwas im Puffer ist, wäre schon sehr hilfreich.

    SideWinder schrieb:

    Bitte seht euch den Artikel an und gebt weitere Vorschläge/Feedback ab 🙂

    Du hast sogar zwei Rufzeichen vor dem undefinierten Verhalten. 🙂

    Sonst fällt mir nichts auf.
    🙂


Anmelden zum Antworten