Zeile feststellen



  • Hi Leute.

    Mich zerhauts heute wieder an den einfachen Dingen :D.
    Ich lese eine Datei mit Text mittels ifstream(file, std::ios::binary) in einen std::string. Jetzt möchte ich einige Zeichen darin ersetzen. Das ist jetzt nicht das große Problem.
    Nur wie stelle ich fest, in welcher Zeile ich bin?
    Zeile definiere ich den String ab anfang bis zum cr ( oder crlf je nach system ).
    Habs mit nem stringstream und std::getline versucht das zeilenweise zu ersetzen um so die zeilennummern zu zählen, aber irgendwie hat das nicht hingehauen.

    Hat jemand nen Lösungsansatz bitte? 🙂
    rya.



  • mh also ich würde für das was du vorhast echt alles mit allen sonderzeichen in EINEN string lesen, oder zeilenweise in einen vector<string>

    #include <fstream>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        fstream f;
        f.open("datei.txt", ios::in);
    
        if ( !f )
           return 1;
    
        string EinString;
        vector<string> v;
        string tmp;
        while ( !f.eof() )
        {
            getline(f, tmp);
            v.push_back(tmp);
            EinString += tmp;
            EinString += '\n';
        }
    
        return 0;
    }
    

    vector::size() ist die anzahl der zeilen in der datei
    und wenn du in dem einen String die chars durchgehst kannst du die '\n' s zählen und erhälst somit die anzahl der zeilen

    ich bevorzuge die vector methode i den meisten fällen, kommt aber immer drauf an



  • Du kannst natürlich über die Whitespaces gehen, aber ich würde das eher so machen, dass ich alle Zeilen von Anfang an getrennt einlesen.. Dann ist die Navigation auch einfacher.. Und auch das zurückschreiben..



  • Den Ansatz über Vector hab ich nicht bedacht, danke für den Hinweis.
    Ich probier das mal aus.
    Ich brauche es dann in einem string, weil angelscript den code den ich hier lade, als char-pointer haben will.
    Ich arbeite derzeit an einer art generischem Compiler für angelscript und möchte hier in meinen Makefiles ein wenig preprocessing anbieten und so Dinge wie _LINE_, _FILE_ etc ermöglichen :). Wobei _FILE_ nicht das Problem ist hihi^^. 🙂
    Danke derweil.
    rya.



  • Scorcher24 schrieb:

    Ich lese eine Datei mit Text mittels ifstream(file, std::ios::binary) in einen std::string. Jetzt möchte ich einige Zeichen darin ersetzen. Das ist jetzt nicht das große Problem.
    Nur wie stelle ich fest, in welcher Zeile ich bin?

    Eine elegante Möglichkeit besteht darin, einen Filter zwischen Stream und Streambuf einzuziehen, der die Zeilen mitzählt. Z.B. so:

    #include <iostream>
    #include <fstream>
    #include <streambuf>
    #include <string>
    #include <boost/io/ios_state.hpp>
    
    class LineCounter : public std::streambuf
    {
    public:
        explicit LineCounter( std::streambuf* sb, char nl = '\n' )
            : m_target( *sb )
            , m_new_line_char( nl )
            , m_lineNo( 1 )
            , m_lf_detected( false )
        {}
        int LineNo() const { return m_lineNo; }
    
    protected:
        virtual int_type underflow()
        {
            return m_target.sgetc();
        }
        virtual int_type uflow()
        {
            if( m_lf_detected )
            {
                ++m_lineNo;
                m_lf_detected = false;
            }
            const int_type m = m_target.sbumpc();
            if( !traits_type::eq_int_type( m, traits_type::eof() ) && traits_type::to_char_type( m ) == m_new_line_char )
                m_lf_detected = true;
            return m;
        }
    private:
        std::streambuf& m_target;
        char m_new_line_char;
        int m_lineNo;
        bool m_lf_detected;
    };
    int line_of( std::basic_ios< char >& io )
    {
        return dynamic_cast< const LineCounter& >( *io.rdbuf() ).LineNo();
    }
    
    int main()
    {
        using namespace std;
        ifstream file( "input.txt" );
        if( file.is_open() )
        {
            LineCounter lncnt( file.rdbuf() );
            boost::io::ios_rdbuf_saver rbsvr( file, &lncnt ); // oder ggf.: static_cast< istream& >( file ).rdbuf( &lncnt );
            for( string word; file >> word; )
            {
                cout << "Zeile " << line_of( file ) << ": " << word << endl;
            }
        }
        return 0;
    }
    

    Vorteil: völlige Unabhängigkeit von der Art und Weise, wie oder was man aus dem istream heraus liest.

    Gruß
    Werner



  • Wow, danke Dir. Hab das Problem zwar am Samstag bereits über den Vector gelöst, aber das ist auch nicht schlecht :).
    rya.


Anmelden zum Antworten