char* zeile aufteilen



  • Baileysss schrieb:

    Gibt es auch eine Möglichkeit, meinen String der jetzt in char *myline irgendwie "umzuspeichern" in char myline[]?? Ich habe nämlich egal was ich versuche immer Konvertierungsfehler! 😞

    Wozu? Ich dachte, Du wolltest vergleichen.

    Vorname Name;6;7;4;10;5;9;8;3;6;7;4;10;5;9;8;6;7;4;10;5;9;6;7;4;10;5;9;

    Schließt die Zeile echt mit einem ; am Ende ab? Sind es immer 27 Zahlen?



  • Die Zeile schließt immer mit einem ; ab, aber manchmal sind es weniger Zahlen.



  • Ich denke an sowas ähnliches:

    int main(){
        ifstrweam in("datei.csv");
        ofstream out("datei2.csv");//fürs Beispiel unten
        string zeile;
        while(getline(datei,zeile)){
            stringstream z(zeile.c_str());
            string name;
            getline(z,name,';');
            vector zahlen;
            int zahl;
            while(getline(z,zahl,';')){
                zahlen.push_nack(zahl);
            }
            //ab hier kannste mit den zahln machen, was Du magst. 
            //Beispiel: Duplikate rauswerfen
            zahlen.erase(unique(zahlen.begin(),zahlen.end()),zahlen.end());
            out<<name<<';';
            for(bector<int>::iterator i=v.begin();i!=v.end();++i)
                out<<*i<<';';
            out<<'\n';
        }
    }
    


  • Werner Salomon würde dich dafür lynchen, dass du beim Datei Lesen std::getline() einsetzt und den Umweg über std::stringstream gehst 😉



  • Vielen Dank Volkard! Ich probiere es sofort mal aus.
    Alternativ habe ich mir jetzt "meine Zeile" als Integer gespeichert und in kleinere Blöcke aufgeteilt (vorher in der Datei), nur das ist auch keine Lösung, da ja die "Integerwerte" viel zu groß sind, und es einfach keinen Sinn macht, in der Datei soviel "vorarbeit" zu leisten.

    @Nexus:
    Wie würdest du es den machen?



  • Nexus schrieb:

    Werner Salomon würde dich dafür lynchen, dass du beim Datei Lesen std::getline() einsetzt und den Umweg über std::stringstream gehst 😉

    Vor zwei Stunden noch hat Baileysss klassisches C geschrieben, und ich könnte wetten, daß LAENGE sogar ein Makro ist. Ich fürchte, er muß selbst für meine Lösung eine ganze Menge nachschlagen. Eine solomonische Lösung würde ihn unter Umständen töten.
    Andererseits, jetzt, wo er danach gefragt hat...
    Nee, das zwingende Semikolon am Ende kann man vielleicht benutzen. Schleife und Abbruchbedingungen haben ich mal großzügig weggelassen.

    ifstrweam in("datei.csv");
        ofstream out("datei2.csv");//fürs Beispiel unten
        {
            sring name;
            getline(in,name,';');
            //oder in.ignore(alles,';');//name incl ; weglesen, falls nicht gebraucht
            vector zahlen;
            int zahl;
            while(in>>zahl && in.peek()==';'){
                zahlen.push_nack(zahl);
            }
            //Verarbeitung wie gehabt
        }
    


  • Hi Folks,

    😃 vorab möchte ich klar stellen, dass ich niemanden lynche und es auch nicht meine Absicht ist, mit meinen Lösungsvorschläge Anfänger zu töten!

    Baileysss schrieb:

    @Nexus:
    Wie würdest du es den machen?

    Nexus meint vermutlich dass, was Volkard die salomonische Lösung nennt - also was in der Art:

    #include <fstream>
    #include <iostream>
    #include <string>
    #include "is_endl.h" // (s. http://www.c-plusplus.net/forum/p1940874#1940874)
    
    // -- liest genau ein ';' - ansonsten setzt es den istream auf fail
    std::istream& semikolon( std::istream& in )
    {
        char c;
        if( in >> c && c != ';' )
            in.setstate( std::ios_base::failbit );
        return in;
    }
    
    int main()
    {
        using namespace std;
        ifstream in("datei.csv");
        string name;
        getline(in,name,';');
    
        bool first = true;
        int vorgaenger;
        for(int zahl; !is_endl( in ) && in >> zahl; in >> semikolon, vorgaenger = zahl, first = false )
        {
            if( first )
                continue;
            // --   hier kann jetzt die aktuelle 'zahl' mit dem 'vorgaenger' verglichen werden
            if( zahl > vorgaenger ) // nur ein Beispiel
                cout << zahl << " > " << vorgaenger << endl;
        }
    }
    

    Ich würde es eher als den C++-Weg bezeichnen. Zumindest hat da noch niemand so wirklich widersprochen.

    Ist ja wieder 'ne altbekannte Situation. Ein Anfänger fragt was mit Einlesen aus einer CSV-Datei - was vermeintlich einfach ist, es aber nicht ist. Unter anderen auch weil ..

    Baileysss schrieb:

    Die Zeile schließt immer mit einem ; ab, aber manchmal sind es weniger Zahlen.

    .. hier das Zeilenende als formatierendes Element eingesetzt wird, was der istream aus dem C++-Standard so ohne weiteres nicht kann - bzw. nur über den getline-Hack.

    Dann antwortet jemand unter Rücksichtnahme darauf, dass ein Anfänger nicht gleich eine volle Breitseite C++ vor dem Latz geschossen bekommt. Anschließend kommt dann ein irgendwie gearteter Kommentar, dass man das doch anders macht (letzteres hätte auch von mir sein können 😉 ).

    Was ist denn da die 'echte' salomonische Lösung? Ist das Einlesen von CSV- und anderen Dateien in C++ zu schwierig, als dass man es Anfängern zumuten soll, es zu verstehen? Oder sollte man die vorhandenen C++-Mittel einsetzen und versuchen es ihm/ihr anschließend zu erklären? Womöglich mit der Gefahr der Abschreckung?

    Ich würde mir dazu mehr Feedback von den Anfängern wünschen. Umso mehr wir wissen, wie schwierig oder einfach die Antworten bei Euch ankommen, umso besser können Euch die erfahrenen Leute hier helfen.

    Gruß
    Werner



  • Huhu Werner,

    ich habe eine kurze Frage bzgl. deines Codes.

    #include <fstream>
    #include <iostream>
    
    std::istream& semikolon( std::istream& in )
    {
        char c;
        if( in >> c && c != ';' )
            in.setstate( std::ios_base::failbit );
        return in;
    }
    
    int main()
    {
        using namespace std;
        ifstream in("datei.csv");
    
        in >> semikolon; // Was genau passiert hier? Es verwirrt mich gerade irgendwie, dass rechts vom Eingabeoperator eine Funktion steht.
    }
    

    lg



  • Es gibt ein paar Überladungen für den Eingabe-Operator. Neben den üblichen Datentypen kannst du dort auch Funktionen übergeben, die einen Stream entgegennehmen - mit dem Effekt, daß diese Funktion auf den betroffenen Stream angewendet werden.
    (auf diese Weise werden auch Stream-Manipulatoren wie std::endl oder std::skipws realisiert)



  • Hallo, Werner Salomon!

    Also

    for(int zahl; !is_endl( in ) && in >> zahl; in >> semikolon, vorgaenger = zahl, first = false )
    

    macht mich ein wenig traurig.

    Mein Ansatz ist darüberhinaus technisch scheiße, weil er deutlich lahm ist. C++ soll nicht lahm sein.

    Vorhin kam mir eine merkwürdige Idee, wie man vielleicht beide Ansätze vermengern könnte.

    int main(){
        ifstrweam in("datei.csv");
        for(foreign_non_empty_line_reader flr(in);!flr.eof();flr.jump_to_next_non_empty_line()){
            string name;
            getline(flr,name,';');
            vector zahlen;
            int zahl;
            while(flr>>zahl>>semikolon)){
                zahlen.push_back(zahl);
            }
            if(!flr)
                continue oder break oder throw?
            //ab hier kannste mit den zahln machen, was Du magst.
            ...
        }
    }
    

    Klingt das gut? Wäre es möglich, auf einen Stream zweilenweise einen anderen Stream anzusetzen, wobei der neue Stream so trivial ist, daß es nicht viel kostet?



  • Kann mir jemand bitte die komplette Lösung zeigen... ich raffs nicht 😞


Anmelden zum Antworten