Vektor mit daten aus Txt zeilenweise beschreiben (was anderes als push_back)



  • SeppJ schrieb:

    Um dir mal zu sagen, worauf ich hinaus wollte:

    1. ` eva <<"Satzart=CMPK01|ADRESSART=KUNDE|ERP_KEY="<<w[1]<<"|NAME1="<<w[5]<<"|NAME2="<<w[7]<<"|STRASSE="<<w[17]<<"|PLz="<<w[11]<<"|ORT="<<w[9]<<"|LAND="<<w[3]<< '\n';

    `
    Existiert überhaupt ein Element 17, also hat deine Datei 18 Zeilen oder mehr? Ist dir überhaupt klar, dass ein vector bei 0 anfängt?

    Es existieren sogar viel mehr Elemente die habe ich aber schon ruasgefillter (ein Datensatz enthält mit allen Leerstellen (die manchmal aber nicht leer sind) über 100 Elemente. ISt also gelöst!

    1. w.erase (w.begin(),w.end());
      Du löscht also den gesamten vector und danach geht es zurück zu Schritt 1 wo munter auf den vector zugegriffen wird. BLÄMM! 😋

    Sorry da stehe ich jetzt auf dem Schlauch. Also wenn ich im debug mir das anschaue komme ich noch nicht mal auf diesen Punkt er springt immer nur zwischen zeile 17 und 18 hin und her ohne nach unten zu gehen (obwohl ich über all berakpoints eingesetzt habe (vielleicht liegt auch da mein Fehler)



  • Matthesjimte schrieb:

    Also wenn ich im debug mir das anschaue komme ich noch nicht mal auf diesen Punkt er springt immer nur zwischen zeile 17 und 18 hin und her ohne nach unten zu gehen (obwohl ich über all berakpoints eingesetzt habe (vielleicht liegt auch da mein Fehler)

    Setzte den ersten Breakpoint auf Zeile 19, lasse ihn bis dahin laufen (Run) und schau Dir dann im Debugger an, wie groß Dein vector ist (wieveiel Elemente). Setzte den nächsten Breakpoint in Zeile 21 und Du wirst sehen, dass beim zweiten mal in Zeile 21 der vector leer ist. Anschließend gibt's den 'subscript out of range'.



  • @werner erstmal vielen dank für den Schnelle Codeblock

    Ich habe den in Visual C++ 2008 Express importiert und mit Vektor angeschaut, das sieht genauso aus wie bei mir 😞
    hier das ergebnis mittendrin
    [9](" ","10000"," ","DE"," ","Institut Für Fußbodentechnik"," ","Norbert Strehle"," ")

    vielleicht bin ich auch zu blöd ich dachte das die Daten aber so intern weg sepichert werden.
    [0](" ")
    [1]("10000"
    [2](" ")
    [3]("DE")

    ich wollte erst alle Daten der Datei einlesen und dann über eine Schleife die DAten dann in der Ausgabe selektieren ist vielleicht umständlich aber ich wollte den Code noch für andere Dateien benutzen



  • Werner_logoff schrieb:

    Matthesjimte schrieb:

    Wenn ich im Debug Modus anschaue steht da w[0]" " im w[1]" ","Name" im w[2]]" ","Name"," " usw. irgendwann kommt dei Fehlermeldung vector subscript out of range (überlaufen)

    letzteres liegt daran, dass Du den vector sofort in der Schleife wieder löschst. Jeder weitere Zugriff ist ein 'subscript out of range'.

    Willst Du sowas:

    #include <string>
    #include <fstream>
    #include <vector>
    
    int ausgabe()
    {
        using namespace std;
        const int ZEILEN_PRO_DATENSATZ = 17;
        fstream eva("c:\\temp\\eva.txt");
        ifstream in("c:\\temp\\daten.txt");
        while (in)
        {
            // --   genau einen Datensatz verarbeiten
            vector<string> w; // Einen Vektor für die Werte EINES Datensatzes
            for (string line5; w.size() < ZEILEN_PRO_DATENSATZ && getline(in,line5);)
                w.push_back (line5);      //Zeile in den Vektor übergeben
            if (in)
                eva <<"Satzart=CMPK01|ADRESSART=KUNDE|ERP_KEY="<<w[1]<<"|NAME1="<<w[5]<<"|NAME2="<<w[7]<<"|STRASSE="<<w[17]<<"|PLz="<<w[11]<<"|ORT="<<w[9]<<"|LAND="<<w[3]<< '\n';
        }
        return 0;
    }
    

    Matthes schrieb:

    Die Quelldatei ist ungefähr so aufgebaut (mit leerzeilen)

    leer
    Name
    leer
    leer
    Strasse
    Ort
    leer

    stimmt nicht überein mit "... ERP_KEY="<<w[1]<<"|NAME1="<<w[5]<<"|NAME2="<<w[7]<<"|STRASSE="<<w[17] ..." ??

    Du hast recht ich dachte aber das es nicht so wichtig und der Fehler nur beim push_back lag (eigentlich hatte ich gehofft das der Satz kommt dann nehm doch einfach das oder das). ISt wohl doch ein bißchen schwerer zu lösen.



  • Matthesjimte schrieb:

    Ich habe den in Visual C++ 2008 Express importiert und mit Vektor angeschaut, das sieht genauso aus wie bei mir 😞

    ja im Prinzip sollte der genauso aussehen. der Unterschied ist nur, dass bei Dir ALLE Zeilen des Dokuments im vector sind und bei meinem Code nur jeweils die 17 (eines Datenblocks)

    Matthesjimte schrieb:

    hier das ergebnis mittendrin
    [9](" ","10000"," ","DE"," ","Institut Für Fußbodentechnik"," ","Norbert Strehle"," ")

    Die [9] bedeutet, dass der vector 9 Elemente enthält. Wen Du auf das [+] vor dem vector im Debug-Fenster klickst, so siehst Du sie einzeln.

    Matthesjimte schrieb:

    vielleicht bin ich auch zu blöd ich dachte das die Daten aber so intern weg sepichert werden.
    [0](" ")
    [1]("10000"
    [2](" ")
    [3]("DE")

    ja genauso werden sie gespeichert, in diesem Fall sind die [#] die Indizes ...

    Matthesjimte schrieb:

    ich wollte erst alle Daten der Datei einlesen und dann über eine Schleife die DAten dann in der Ausgabe selektieren ist vielleicht umständlich aber ich wollte den Code noch für andere Dateien benutzen

    kannst Du auch machen, brauchst Du aber nicht, braucht mehr Speicher und ist evt. etwas schwieriger zu Programmieren.



  • @werner Danke erstmal werde do heute abend noch mal reinschauen



  • @werner Dank dir bin ich jetzt schlauer. das mit dem Plus war ein guter Tipp

    Mein Programm steigt aus weil nicht mehr wie 1800 Vectoren eingelesen werden und dann meine Ausgabe auf einen Vektor zugreift der nicht existiert.

    Gibt es da eine Grenze? kann man die umgehen

    auch wenn nicht schön aussieht hier mein code

    int ausgabe()
    {
    # include <cstdlib>
    # include <string>
    # include <fstream>
    
    unsigned int k;	
    int z;
    int v1=1;
    int v2=5;
    int v3=7;
    int v4=17;
    int v5=11;
    int v6=9;
    int v7=3;
    char test;
    fstream eva;
    eva.open("c:\\temp\\eva.txt");
    ifstream in("c:\\temp\\daten.txt");
    string line5; // variable für zeileneinlesen
    vector<string> w; // Einen Vektor für die Werte deklarieren
    
    while ( std::getline(in, line5,'\n')) 
    {
    	w.push_back (line5);      //Zeile in den Vektor übergeben
    }
    for (k=0 ; k<=1000 ; k++)  //Vektor hochzählen
    {
    	z=k*18;
    	v1=z+1;
    	v2=z+5;
    	v3=z+7;
    	v4=z+17;
    	v5=z+11;
    	v6=z+9;
    	v7=z+3;
    
    	eva <<"Satzart=CMPK01|ADRESSART=KUNDE|ERP_KEY="<<w[v1]<<"|NAME1="<<w[v2]<<"|NAME2="<<w[v3]<<"|STRASSE="<<w[v4]<<"|PLz="<<w[v5]<<"|ORT="<<w[v6]<<"|LAND="<<w[v7]<< '\n';
    
    }
    
    return 0;
    }
    

    Die Datei die ich einlesen muss hat 400 zeilen und 17 elemente macht 6800 Daten.
    Muss ich mich da am besten von Vektoren verabschieden? oder soll ich die Datei einlesen, erste zeile löschen und wieder schließen. dann wieder aufmachen, löschen usw.? ist aber nicht die feine Art.

    Fragen über Fragen! und nochmals vielen Dank 👍 für die schnelle Hilfe, hätte schon vor Tagen in Forum schreiben sollen



  • Vektoren haben keine Größenbegrenzung. Deine for-schleife ist komplett falsch. Du führst mysteriöse Rechnungen aus, die letztlich in einer Zugriffsverletzung enden müssen!!!

    Mal tachelles, wie sehen nun die Daten wirklich aus? NICHT nur ungefähr. Gib ein komplettes Beispiel, aus mindestens 3 Datensätzen. Dann erst kann dir richtig geholfen werden.



  • Bei der for-Schleife ist der höchste berechnete Index 18017 (v4). Das ist weit mehr als 6800. Das muss ja daneben gehen.



  • #include <string> 
    #include <fstream> 
    #include <vector> 
    
    int ausgabe() 
    { 
        using namespace std; 
        const int ZEILEN_PRO_DATENSATZ = 17; 
        fstream eva("c:\\temp\\eva.txt"); 
        ifstream in("c:\\temp\\daten.txt"); 
        while (in) 
        { 
            // --   genau einen Datensatz verarbeiten 
            vector<string> w; // Einen Vektor für die Werte EINES Datensatzes 
            for (string line5; w.size() < ZEILEN_PRO_DATENSATZ && getline(in,line5);) 
                w.push_back (line5);      //Zeile in den Vektor übergeben 
            if (in) 
                eva <<"Satzart=CMPK01|ADRESSART=KUNDE|ERP_KEY="<<w[1]<<"|NAME1="<<w[5]<<"|NAME2="<<w[7]<<"|STRASSE="<<w[17]<<"|PLz="<<w[11]<<"|ORT="<<w[9]<<"|LAND="<<w[3]<< '\n'; 
        } 
        return 0; 
    }
    

    Die Abfrage if(in) sieht für mich komisch aus. Müsste man nicht viel eher überprüfen, ob der Vektor v auch 18 Elemente hat, also der Datensatz komplett ist, dann die Ausgabe nach eva schreiben und abschließend den Vektor v leeren?
    Und in einem else-Zweig eine Fehlerbehandlung durchführen?



  • bmario schrieb:

    #include <string> 
    #include <fstream> 
    #include <vector> 
    
    int ausgabe() 
    { 
        using namespace std; 
        const int ZEILEN_PRO_DATENSATZ = 17; 
        fstream eva("c:\\temp\\eva.txt"); 
        ifstream in("c:\\temp\\daten.txt"); 
        while (in) 
        { 
            // --   genau einen Datensatz verarbeiten 
            vector<string> w; // Einen Vektor für die Werte EINES Datensatzes 
            for (string line5; w.size() < ZEILEN_PRO_DATENSATZ && getline(in,line5);) 
                w.push_back (line5);      //Zeile in den Vektor übergeben 
            if (in) 
                eva <<"Satzart=CMPK01|ADRESSART=KUNDE|ERP_KEY="<<w[1]<<"|NAME1="<<w[5]<<"|NAME2="<<w[7]<<"|STRASSE="<<w[17]<<"|PLz="<<w[11]<<"|ORT="<<w[9]<<"|LAND="<<w[3]<< '\n'; 
        } 
        return 0; 
    }
    

    Die Abfrage if(in) sieht für mich komisch aus. Müsste man nicht viel eher überprüfen, ob der Vektor v auch 18 Elemente hat, also der Datensatz komplett ist, dann die Ausgabe nach eva schreiben und abschließend den Vektor v leeren?
    Und in einem else-Zweig eine Fehlerbehandlung durchführen?

    wenn bool(in)==true ist, so muss der vector ZEILEN_PRO_DATENSATZ Elemente enthalten (17 oder 18 - Matthes ist sich da selber nicht einig). Ansonsten wäre die darüber liegende for-Schleife gar nicht verlassen worden.
    Das Leeren des vectors ist unnötig, da der vector lokal exisitiert und mit jedem Schleifendurchlauf der while-Schleife neu angelegt wird. (Nein, das muss nicht zwingend unperfomant sein)

    Die Abfrage if(w.size()==ZEILEN_PRO_DATENSATZ) .. wäre in diesem Fall gleichbedeutend, enthielte aber eine implizite Redundanz gegenüber den Zeilen darüber. Es wäre ja z.B.: denkbar, dass man in den Code-Zeilen 14-16 nur die Zeilen aus der Datei liest, die man auch wirklich braucht, dann müsste diese Abfrage wieder angepasst werden - ein einfaches if(in) dagegen nicht. Aber ich glaube Matthes kämpft noch mit profaneren Problemen.



  • Werner_logoff schrieb:

    wenn bool(in)==true ist, so muss der vector ZEILEN_PRO_DATENSATZ Elemente enthalten (17 oder 18 - Matthes ist sich da selber nicht einig). Ansonsten wäre die darüber liegende for-Schleife gar nicht verlassen worden.

    Das klingt logisch, danke.

    Werner_logoff schrieb:

    Das Leeren des vectors ist unnötig, da der vector lokal exisitiert und mit jedem Schleifendurchlauf der while-Schleife neu angelegt wird. (Nein, das muss nicht zwingend unperfomant sein)

    Oha, da hatte ich doch glatt übersehen, dass w lokal ist, in Matthes Version war es das noch nicht 🙂
    Und du wirst lachen, aber ich hab mich mittlerweile auch gefragt, ob es sinnvoll wäre w nicht lokal zu machen. Was ist denn effizienter, den Vektor komplett zu zerstören, also Konstruktor und Destruktor für jeden Durchlauf in Kauf nehmen, oder die Elemente jeweils zu löschen?

    Aber ein was fällt mir noch ein:

    vector<string> w(ZEILEN_PRO_DATENSATZ+1);
    

    mario



  • bmario schrieb:

    Aber ein was fällt mir noch ein:

    vector<string> w(ZEILEN_PRO_DATENSATZ+1);
    

    Das wäre auch eine Möglichkeit, die gleich zeigt, dass die Abfrage if(in) der Abfrage if(w.size()==ZEILEN_PRO_DATENSATZ) überlegen ist. Vergisst man nämlich im letzteren Fall die Abfrage zu ändern, so schießt man sich in's Knie und merkt es vielleicht gar nicht.

    Das '+1' ist unnötig.

    bmario schrieb:

    Was ist denn effizienter, den Vektor komplett zu zerstören, also Konstruktor und Destruktor für jeden Durchlauf in Kauf nehmen, oder die Elemente jeweils zu löschen?

    Solche Fragen würde ich bei dem Level, bei dem wir hier gerade diskutieren, ganz ganz weit hinten ansiedeln. (s. Donald Knuth "premature optimization is the root of all evil").
    Denk' lieber darüber nach, wie man den Code übersichtlich, einfach und vor allem funktionsfähig gestaltet.


Anmelden zum Antworten