String bis Zeilenende per Stream einlesen



  • Hoi,

    ich habe ein Format der Art

    <Zahl> <Zahl> <Zahl> [Optionaler String] *Zeilenende*

    Zwischen der letzten Zahl und dem String sind beliebig viele Leerzeichen/Tabulatoren.
    Meine Lösung ist getline() und den String trimmen.

    Geht das eleganter, also ohne das trimmen?

    Danke und Grüße,
    Ethon

    Edit: Ich weiß, ich könnte mit einer manuellen Schleifen Spacces überspringen und dann getline aufrufen. Da es hierbei aber um das Raushängen des C++-Penis geht suche ich die eleganteste Streamlösung. 😉



  • Einfach int lesen, int lesen, int lesen,
    Whitespace skippen (Manipulator std::ws),
    prüfen ob das nächste Zeichen '\n' ist, wenn ja fertig, wenn nein string lesen.



  • Nur dass '\n' als Whitespace gilt und auch gefiltert wird.
    Dh. ich muss die locale ändern.



  • Edit³: Ok, habs. Das ist das Problem... 💡 s



  • C++ und Penis in einem Satz! Der Erfinden von C++ würde sich im Grab umdrehen, wenn er sowas lesen würde.



  • Ethon schrieb:

    Nur dass '\n' als Whitespace gilt und auch gefiltert wird.
    Dh. ich muss die locale ändern.

    Oh, stimmt ja.
    Mein Fheler.



  • clang schrieb:

    C++ und Penis in einem Satz! Der Erfinden von C++ würde sich im Grab umdrehen, wenn er sowas lesen würde.

    Zum Glück lebt er noch ...



  • Hi Ethon,

    wenn es hier um 'ne C++-raushängende Lösung geht, wie wäre es dann mit einer gettrimmedline-Funktion - als Pendant zu std::getline:

    #include <iostream>
    #include <string>
    #include <locale> // std::ctype
    
    #include <sstream> // std::istringstream (s.main)
    
    template< typename E, typename Traits >
    std::basic_istream< E, Traits >& gettrimmedline( std::basic_istream< E, Traits >& in, std::basic_string< E, Traits >& str )
    {
        std::basic_istream< E, Traits >::sentry ok( in, true ); // true := noskipws
        if( ok )
        {
            std::ios_base::iostate state = std::ios_base::goodbit;
            try
            {
                bool readsome = false;
                std::basic_string< E, Traits >::size_type len = 0;
                str.clear();
                const std::ctype< E >& ctype_ = std::use_facet< std::ctype< E > >( in.getloc() );
                const E delim = ctype_.widen('\n');
                for(;;)
                {
                    const Traits::int_type m = in.rdbuf()->sbumpc();
                    if( Traits::eq_int_type( m, Traits::eof() ) )
                    {
                        state |= std::ios_base::eofbit;
                        break;
                    }
                    const E c = Traits::to_char_type( m );
                    readsome = true;
                    if( Traits::eq( c, delim ) ) // Zeilenende
                        break;
                    if( ctype_.is( std::ctype_base::space, c ) )
                    {
                        if( str.empty() )
                            continue; // überliest führende white character
                    }
                    else
                        len = str.length()+1; // Länge merken mit dem letzten 'not white character'
                    str.append( 1, c );
                }
                if( readsome )
                    str.resize( len ); // ggf. white character am Ende entfernen
                else
                    state |= std::ios_base::failbit;
            }
            catch( ... )
            {
                state |= std::ios_base::badbit;
                if( in.exceptions() & std::ios_base::badbit )
                    throw;
            }
            in.setstate( state );
        }
        return in;
    }
    
    int main()
    {
        using namespace std;
        istringstream in(
            "1 23 45 das ist ein Text        \n"
            "1 67 89\n"
            "1 -9 23     \n"
            "1 17 89"  // Bem.: 'Leerer' Inhalt führt zu Fehler
            );
        int a, b, c;
        for( string s; gettrimmedline( in >> a >> b >> c, s ); )
            cout << "Optionaler Text: [" << s << "]" << endl;
        return 0;
    }
    

    Gruß
    Werner


Anmelden zum Antworten