Datei zeichenweise auslesen - newline Problem.



  • Gugelmoser schrieb:

    Ich hoffe, meine Erklärung hat dir geholfen.

    Ja, hat sie, herzlichen Dank:-)
    Die fehlerhafte Ausgabe ist jetzt nachvollziehbar.

    Schritt 3:
    			Das erste Zeichen der Sequence ist ein +. Alles OK, eine Zahl darf ein Vorzeichen haben.
    
    		Schritt 4:
    			Das zweite Zeichen der Sequence ist ein -. What? Eine Zahl kann immer nur 1 Vorzeichen haben. D.h. das - ist
    			ein nicht-numerisches Zeichen. Nun wird der Einlesevorgang abgebrochen, cin geht in einen Fehlerzustand über,
    			und die restlichen Zeichen (-798) bleiben im Puffer stecken. Es wurde also nur das + gelesen, und einfach nur + wird als +0 gehandhabt.
    

    Mit der Programmabfolge ist imho klar, daß die benutzten Standardfunktionen nicht wirklich dafür geeignet sind, Zahlen aus einem Stream zu filtern, denn wer kann denn schon garantieren, daß in einer Datei vor einer negativen Zahl nicht zufällig ein "+" steht. Und das natürlich nur, sofern negative Zahlen überhaupt vorkommen dürfen.


  • Mod

    redrew99 schrieb:

    Mit der Programmabfolge ist imho klar, daß die benutzten Standardfunktionen nicht wirklich dafür geeignet sind, Zahlen aus einem Stream zu filtern, denn wer kann denn schon garantieren, daß in einer Datei vor einer negativen Zahl nicht zufällig ein "+" steht. Und das natürlich nur, sofern negative Zahlen überhaupt vorkommen dürfen.

    Wobei dich nichts daran hindert, dein eigenes num_get-facet zu schreiben und zu verwenden.



  • Man könnte neg. Zahlen auch einfach mit -1 multiplizieren. Allerdings finde ich auch, wenn z.B. in einer Datei "Geburtsjahre" neg. Zahlen vorkommen, dann sollte man eher an der Datei ansetzen, anstatt am Programm.



  • Werner Salomon schrieb:

    Hier mal ein Manipulator, der direkt an der streambuf-Schnittstelle die Zeichen abgreift. In Summe ist das natürlich mehr Code, aber in der Anwendung wird's dann wieder schnuckelig einfach.Werner

    Wenn ich das richtig sehe, müßte in Zeile 8 und 15 noch ein "typename" gesetzt werden, sonst kompiliert der Code nicht.

    typename std::basic_istream< E, Traits >::sentry ok( in);
    ...
    for( typename Traits::int_type m = in.rdbuf()->sgetc(); ; m = in.rdbuf()->snextc() )
    ...
    


  • Und da soll mir noch ein einziges mal jemand widersprechen, MSVC wäre so korrekt mit Templates. -.-



  • Werner Salomon schrieb:

    Unter der Voraussetzung, dass keine isolierten '-' (und '+'?) Zeichen in der Datei stehen, Gruß Werner

    Sry, aber das ist nicht optimal, denn ein "§$!56 zp-,7789" sollte korrekt ausgelesen werden können. Aktuelle Ausgabe wäre "56".
    Das Problem kann man aber relativ einfach lösen, indem man das Zeichen nach einem "+/-" abfragt und je nachdem, ob Zahl oder nicht,dann halt weiterverfährt.



  • redrew99 schrieb:

    Wenn ich das richtig sehe, müßte in Zeile 8 und 15 noch ein "typename" gesetzt werden, sonst kompiliert der Code nicht.

    typename std::basic_istream< E, Traits >::sentry ok( in);
    ...
    for( typename Traits::int_type m = in.rdbuf()->sgetc(); ; m = in.rdbuf()->snextc() )
    ...
    

    Hallo redrew99,

    Natürlich habe ich den Code vorher mal durch den Compiler geschickt, aber Du hast Recht, das Visual Studio, welches ich verwende, ist da recht großzügig.

    Gruß
    Werner



  • Möchte ich nochmal festhalten: MSVC ist, was Templates angeht kaputt. Werner gibt mir Recht.

    ICH HABE RECHT!



  • 314159265358979 schrieb:

    Möchte ich nochmal festhalten: MSVC ist, was Templates angeht kaputt.

    Ja, Visual C++ hat einige Bugs im Bereich Templates. "Ist kaputt" ist aber vielleicht etwas übertrieben, obwohl das natürlich Ansichtssache ist.

    Werner gibt mir Recht.

    ICH HABE RECHT!

    Ganz ruhig, Mami kommt gleich.



  • Mami ist tot. <.<


  • Mod

    Hier mal ein Entwurf mit einem eigenen num_get-facet:

    #include <iostream>
    #include <locale>
    
    class my_num_get : public std::num_get<char>
    {
    private:
        template <typename T>
        iter_type do_do_get(iter_type in, iter_type end, std::ios_base& str, std::ios_base::iostate& err, T& v) const
        {
            bool negative = false;
            for ( ; in != end; ++in )
            {
                auto c = *in;
                if ( c == '+' )
                    negative = false;
                else if ( c == '-' )
                    negative = true;
                else
                    break;
            }
            auto res = std::num_get<char>::do_get( in, end, str, err, v );
            if ( negative )
                v = -v;
            return res;
        }
    
        virtual iter_type do_get(iter_type in, iter_type end, std::ios_base& str, std::ios_base::iostate& err, long& v) const override { return do_do_get( in, end, str, err, v ); }
        virtual iter_type do_get(iter_type in, iter_type end, std::ios_base& str, std::ios_base::iostate& err, long long& v) const override { return do_do_get( in, end, str, err, v ); }
        virtual iter_type do_get(iter_type in, iter_type end, std::ios_base& str, std::ios_base::iostate& err, unsigned short& v) const override { return do_do_get( in, end, str, err, v ); }
        virtual iter_type do_get(iter_type in, iter_type end, std::ios_base& str, std::ios_base::iostate& err, unsigned& v) const override { return do_do_get( in, end, str, err, v ); }
        virtual iter_type do_get(iter_type in, iter_type end, std::ios_base& str, std::ios_base::iostate& err, unsigned long& v) const override { return do_do_get( in, end, str, err, v ); }
        virtual iter_type do_get(iter_type in, iter_type end, std::ios_base& str, std::ios_base::iostate& err, unsigned long long& v) const override { return do_do_get( in, end, str, err, v ); }
    };
    
    int main()
    {
        using namespace std;
        cin.imbue(locale(locale(""), new my_num_get()));;
        long long wert;
        for (;;)
        {
            cin >> wert;
            if (cin.eof())
                break;
            if (cin)
                cout << wert << '\n';
            else
                {
                    cin.clear();
                    cin.ignore(1);
                }
        }
    }
    


  • Mit Makros wärs besser.


  • Mod

    314159265358979 schrieb:

    Mit Makros wärs besser.

    Das ist eine sehr subjektive Wahrheit. Dein Fetisch wird nämlich nicht allgemein geteilt.



  • Es wird:
    - Besser lesbar
    - Besser wartbar
    - Die Fehlerwahrscheinlichkeit reduziert

    Also ja, mit Makros ist es besser.



  • 314159265358979 schrieb:

    Es wird:
    - Besser lesbar
    - Besser wartbar
    - Die Fehlerwahrscheinlichkeit reduziert

    Also ja, mit Makros ist es besser.

    Nein.
    Nein.
    Nein.
    Nein.



  • Troll or just stupid?


Anmelden zum Antworten