Probleme bei file einlesen



  • samo schrieb:

    hmm, ich kann aber nicht

    szBuffer >> x
    

    machen, da dann kommt

    error C2678: binary '>>' : no operator found which takes a left-hand operand of type 'std::string' (or there is no acceptable conversion).

    Aber mit szBuffer.substr() kann ich auch nicht arbeiten, da ja die float-Zahlen immer wieder unterschiedliche Laenge haben

    Den Index, an welchem der Float-Wert beginnt, bekommst du ja durch deine Suche nach dem 'X,Y oder Z' geliefert. Von dort aus musst du das nächste Leerzeichen suchen, dann hast du deinen ganzen Wert.
    Alternativ kannst du auch festlegen das jeder Fließkommawert mit einer festen Präzision (z.B. 😎 gespeichert wird.

    grüße



  • Wie suche ich nach dem naechsten Leerzeichen? mit find('\')?



  • find(" ")
    


  • std::string::size_type pos = str.find( " ", lastindex );
    
    if ( pos == std::string::npos )
      // nich gefunden
    

    grüße



  • o.k., er findet jetzt meine Leerzeichen und auch meine X, Y, und Z, aber er liest immer nur das X und auch das zum Teil nicht richtig ein. Die Y und Z bleiben immer auf 0 und ich weiss nicht warum. Kann mir jemand weiterhelfen?

    Das ist mein jetziger Code:

    string szBuffer;
    		string szValue;
    
    		string::size_type pos1 = 0;
    		string::size_type pos2 = 0;
    		string::size_type pos3 = 0;
    
    		float x = 0.;
    		float y = 0.;
    		float z = 0.;
    
    		while (!file.eof())
    		{
    			getline(file, szBuffer);
    			pos2 = szBuffer.size();
    			if (szBuffer.find("X",0) != string::npos)
    			{
    				pos3 = szBuffer.find("X",0);
    				pos1 = szBuffer.find(" ", pos3); 
    				x = atof((szBuffer.substr(pos1-pos3,pos1)).c_str());
    
    				//if (szBuffer.find("Y",0) != string::npos)
    				//{
    					pos3 = szBuffer.find("Y",0);
    					pos1 = szBuffer.find(" ", pos3); 
    					y = atof((szBuffer.substr(pos1-pos3,pos1)).c_str());
    
    					//if (szBuffer.find("Z",0) != string::npos)
    					//{
    						pos3 = szBuffer.find("Z",0); 
    						x = atof((szBuffer.substr(pos2-pos3,pos2)).c_str());
    					//}
    				//}
    				m_RobotPath->InsertNextPoint(x,y,z);
    			}
    		}
    	}
    

    und das die einzulesende Datei

    N10G94
    N11T01 M6
    N12G50 X0.00 Y0.00 Z0.00
    N13S2000 M3
    N14S1200M3
    N15G00X0.000 Y0.000 Z5.000
    N16G01X0.000 Y0.000 Z0.000 F100.0
    N17G01X54.300 Y0.000 Z0.000
    N18G01X54.300 Y0.056 Z0.000
    N19G01X38.944 Y0.056 Z0.000
    N20G01X38.833 Y0.056 Z-0.013
    N21G01X9.389 Y0.056 Z-0.013
    .........

    P.S.: Die einzulesende Datei kann ich nicht aendern, die bekomme ich so von einem anderen Programm das ich nicht beinflussen kann



  • samo schrieb:

    Hallo zusammen

    ich habe ein file das so aussieht:

    N10G94
    N11T01 M6
    N12G50 X0.00 Y0.00 Z0.00
    N13S2000 M3
    N14S1200M3
    N15G00X-3.667Y-3.667Z5.000
    N16G01X-3.667Y-3.667Z0.000F100.0
    N17G01X43.000Y-3.667Z0.000
    N18G01X43.000Y-3.000Z0.000
    N19G01X-3.667Y-3.000Z0.000
    N20G01X-3.667Y-2.333Z0.000
    .........

    Was ich jetzt moechte sind nur die x, y, und z Werte auslesen.

    Du kannst Dir eine Menge Arbeit sparen, wenn Du einfach das ausliest, was Dich interessiert - in diesem Fall die X-, Y- und Z-Werte.
    Grundregel Nr.1 dabei ist: baue Dir eine Struktur, die dem entspricht, was Du viele Male aus der Datei auslesen willst. Also hier ganz einfach

    struct XYZ
    {
        double m_x, m_y, m_z;
    };
    

    Regel Nr. 2 füge eine Lesefunktion hinzu

    #include <iostream>
    struct XYZ
    {
        friend std::istream& operator>>( std::istream& in, XYZ& xy );
        double m_x, m_y, m_z;
    };
    

    Vorher solltest Du natürlich genau wissen, wie Deine Datei aufgebaut ist. Also auch die Teile, die nicht eingelesen werden sollen, müssen definiert sein. Ich unterstelle mal, dass die Zeichen 'X', 'Y' und 'Z' exklusiv sind und in keinem anderen Zusammenhang in der Datei auftauchen. Dann kann die Einlesefunktion etwa so aussehen

    std::istream& operator>>( std::istream& in, XYZ& xy )
    {
        typedef std::istream::traits_type traits_type;
        if( in.ignore( 9999, traits_type::to_int_type( 'X' ) ) )
        {
            XYZ tmp;
            char cy, cz;
            if( (in >> tmp.m_x >> cy >> tmp.m_y >> cz >> tmp.m_z).ignore( 9999, traits_type::to_int_type( '\n' ) ) )
            {
                if( cy == 'Y' && cz == 'Z' )
                {
                    // alles korrekt gelesen
                    xy = tmp; // Input übernehmen
                }
                else
                    in.setstate( std::ios_base::failbit ); // Fehler es folgt kein 'Y' oder 'Z'
            }
        }
        return in;
    }
    

    Und der Rest geht jetzt so, wie das Einlesen einzelner Integerwerte

    #include <fstream>
    #include <vector>
    #include <iterator>
    int main()
    {
        using namespace std;
        ifstream file("input.txt");
        std::vector< XYZ > xyz( (istream_iterator< XYZ >( file )), istream_iterator< XYZ >() );
        // 'xyz' ist mit den Werten aus der Datei gefüllt
        return 0;
    }
    

    Oder auch - wenn Du das istream_iterator etwas kryptisch findest

    #include <fstream>
    int main()
    {
        using namespace std;
        ifstream file("input.txt");
        for( XYZ xyz; file >> xyz; )
        {
            // hier das xyz-Objekt weiterverarbeiten
        }
        return 0;
    }
    

    Gruß
    Werner



  • Wenn die Datei nur aus der Struktur besteht, kannst du die Datein aber auch als Binärdateien speichern. Allerdings kannst du sie dann nur noch mit einem Hexeditor bearbeiten (die gespeicherte Datei)

    struct asd
    {
        int x;
        int y;
        int z;
    };
    
    asd testwerte[100];
        for(int i=0; i<=100;++i)        //Struktur mit Werten füllen
        {
            testwerte[i].x = 1;
            testwerte[i].y = 1;
            testwerte[i].z = 1;
        }
    
        fstream datei;
        //Struktur Array auf die Festplatte schreiben
        datei.open("test.dat", ios::binary | ios::out);
        datei.write(reinterpret_cast<char*>(testwerte),sizeof(asd)*100);
        datei.close();
    
        memset(testwerte,0,sizeof(asd)*100);    //Nur zur Demonstration erforderlich
        //Strukturarray wiedereinlesen
        datei.open("test.dat",ios::binary | ios::in);
        datei.read(reinterpret_cast<char*>(testwerte),sizeof(asd)*100);
    
        for(int i=0; i<=100;++i)
        {
            //Daten verarbeiten
            cout << testwerte[i].x << endl;
            cout << testwerte[i].y << endl;
            cout << testwerte[i].z << endl;
        }
    

    Es fällt im Code oben natürlich noch die Fehlerbehandlung und man kann damit nur
    Arrays einlesen, wenn man deren Länge kennt. Doch natürlich kann man dieses Problem umgehen, wenn man am Anfang der Datei die Länge des Array speichert.



  • Werner Salomon schrieb:

    ...

    struct XYZ
    {
        friend std::istream& operator>>( std::istream& in, XYZ& xy );
        double m_x, m_y, m_z;
    };
    
    ...
    std::istream& operator>>( std::istream& in, XYZ& xy )
    {
        typedef std::istream::traits_type traits_type;
    ...
       
    std::vector< XYZ > xyz( (istream_iterator< XYZ >( file )), istream_iterator< XYZ >() );
    

    ...
    Gruß
    Werner

    Aaaah ! 👍
    Sehr elegant ! Das gefällt mir.

    Danke,

    Simon2.

    flammenvogel schrieb:

    Wenn die Datei nur aus der Struktur besteht, kannst du die Datein aber auch als Binärdateien speichern. ...

    Der Vorschlag wird ihm wohl nicht viel helfen:

    samo schrieb:

    ...
    P.S.: Die einzulesende Datei kann ich nicht aendern, die bekomme ich so von einem anderen Programm das ich nicht beinflussen kann

    Gruß,

    Simon2.



  • @Simon2: Ups, das hab ich wohl überlesen. Vielleicht sollte ich das nächste mal etwas genauer hinschauen. 😉



  • flammenvogel schrieb:

    @Simon2: Ups, das hab ich wohl überlesen. Vielleicht sollte ich das nächste mal etwas genauer hinschauen. 😉

    Macht ja nix ... passiert mir auch öfter. 😉

    Gruß,

    Simon2.


Anmelden zum Antworten