CSV auslesen und in einem 2D Array speichern



  • Hallo,

    ich habe folgendes Problem, ich muss für das Spiel Schiffe versenken eine externe Datei einlesen lassen und die Positonen der Schiffe in ein Array abspeichern. Das Problem besteht darin das bei einer CSV Datei die Spalten durch ein Semikolon getrennt werden, das soll allerdings nicht in das Array.

    void Field::scanData()
    {
    	const int zeile = 12;
    	const int spalte = 12;
    	char s;
    	char meinfeld[zeile][spalte];
    
    	////Name der Datei angeben, die eingelesen werden soll
    	//cout << "Dateiname eingeben: ";
    	//cin >> Datei;
    	//system("cls");
    
    	// ifstream zum einlesen der Binär Datei
    	ifstream Daten;
    	//Einlesen der zuvor eingegebenen Datei
    	Daten.open("Testat1.csv", ios::in);
    
    
    	if (!Daten)
    	{
    		cout << "Datei konnte nicht geoeffnet werden!" << endl;
    		system("PAUSE");
    	}
    	else
    	{
    		for (int y = 0; y < zeile; y++)
    		{
    			for (int x = 0; x < spalte; x++)
    			{
    				while (Daten.peek() == ';')
    				Daten.get(s);
    				meinfeld[y][x] = s;
    			}
    		}
    
    		system("PAUSE");
    
    		Daten.close();
    		system("cls");
    		cout << "Datei erfolgreich eingelesen!" << endl << endl;
    		system("PAUSE");
    		system("cls");
    
    		cout << setw(3) << "    A" << setw(3) << "B" << setw(3) << "C" << setw(3) << "D" << setw(3) << "E" << setw(3) << "F" << setw(3) << "G" << setw(3) << "H" << setw(3) << "I" << setw(3) << "J" << setw(3) << "K" << setw(3) << "L" << setw(3) << endl << endl;
    		for (int y = 0; y < zeile; y++)
    		{
    			cout << setw(4) << left << y + 1;
    			for (int x = 0; x < spalte; x++)
    			{
    				cout << setw(3) << left << meinfeld[y][x];
    			}
    			cout << endl;
    		}
    
    	}
    }
    
    Vielen Dank schonmal
    


  • Den Semikolon kannst du einfach mittels Daten >> char_variable überlesen.
    Wie sieht deine csv genau aus?



  • o o o o o o o o o o o o
    o o o o o o o o o o o o
    o o o o o o o o o o o o
    o o s s s o o o o o o o
    o o o o o o o o o o o o
    o o o o o o o s o o o o
    o o o o o o o s o o o o
    o o o o o o o s o o o o
    o o o o o o o s o o o o
    o o o o o o o s o o o o
    o o o o o o o s o o o o
    o o o o o o o o o o o o

    nur als Beispiel, es muss halt für mich später sichtbar sein wo ein Schiff platziert wurde und wo nicht.



  • Könnte auch mit std::getline gehen.

    ifstream Daten;
    std::string buffer;
    while (std::getline(Daten, buffer))
    {
        std::stringstream streamline(buffer);
        while (std::getline(streamline, buffer, ';'))
        {
            std::stringstream cell(buffer);
        {
    }
    

    Also ich habe es nicht ausprobiert und für das Array müsste noch zwei Variablen in den Schlaufen mitzählen. Glaube aber es hat so mehr overhead.



  • Ich würde es irgendwie in der Form machen:

    #include <fstream>
    #include <iostream>
    #include <vector>
    using namespace std;
    
    int main()
    {
        vector<vector<char>> raster;
        for( ifstream file( "test.txt" );file;)
        {
            vector<char> row;
            for( char c, skip;; )
            {
                file >> std::noskipws >> c >> skip;
                if( !file || skip=='\n' )
                    break;
                row.emplace_back( c );
            }
            raster.emplace_back(row);
        }
        
        for( const auto& row : raster )
        {
            for( auto c : row )
                cout << c << ';';
            cout << endl;
        }
        cout << "Treffer bei 1|2: " << std::boolalpha << (raster[1][2]=='s') << endl;
        cout << "Treffer bei 3|2: " << std::boolalpha << (raster[3][2]=='s');
    }
    


  • Ist es auch für einen Anfänger möglich euren Lösungsansatz in ein Array abzuspeichern?



  • Was gefällt Dir an vector<vector<char>> raster; aus @out's Vorschlag nicht?



  • Funktionieren tut es ja aber ich kann das leider nicht nachvollziehen und weiss nicht wie ich es in der richtigen reihenfolge ins 2d array übertrage :smiling_face_with_open_mouth_cold_sweat:



  • Dieser Beitrag wurde gelöscht!


  • @out sagte in CSV auslesen und in einem 2D Array speichern:

    for( const auto& row : raster )
    {
        for( auto c : row )
            cout << c << ';';
        cout << endl;
    }
    

    wie kann ich den die größe ändern die abgescannt wird? in meiner Datei ist das Feld nähmlich 12x12 groß aber ausgegeben wird nur 11x12. Es wird die erste Spalte übersprungen...



  • @phatneezy sagte in CSV auslesen und in einem 2D Array speichern:

    wie kann ich den die größe ändern die abgescannt wird? in meiner Datei ist das Feld nähmlich 12x12 groß aber ausgegeben wird nur 11x12. Es wird die erste Spalte übersprungen...

    Eine Größenangabe ist unnötig, da das Array dynamisch ist und automatisch die richtige Größe hat, nämlich die Arraygröße.
    Spalte 12 fehlt, weil ein Logikfehler drin war. Ich habs für dich mal kommentiert:

    #include <fstream>
    #include <iostream>
    #include <vector>
    using namespace std;
    
    int main()
    {
        /*
         vector ist das dynamisches Array in C++. D.h. die Größe von dem Array wird zur
         Laufzeit beliebig bestimmt. Eine Angabe für Spalten und Zeilen sind nun also nicht notwendig.
         */
        vector<vector<char>> raster;
        
        /*
         Den Aufbau einer for-Schleife kennst du?
         for( Definition von Variablen; Abbruchbedingung; Irgendwas das nach jedem Schleifendurchgang passiert)
         Hier ist die Abbruchbedingung file. Einfach nur file ist praktisch das gleiche wie !file.fail()
         Es wird abgebrochen, wenn über das Ende der Datei hinausgelesen wird.
         */
        for( ifstream file( "test.txt" );file; )
        {
            vector<char> row;
            for( char c, skip;; )
            {
                /*
                 Da wir keine Zeilengröße wissen, müssen wir auf Zeilenumbruch testen.
                 Standardmäßig überließt aber der operator>> Whitespaces (Leerzeichen, Zeilenumbrüche, Tabs...).
                 noskipws sagt, er soll keine Whitespaces überlesen, damit wir auf Zeilenumbruch testen können.
                 Nun wird also zuerst ein Zeichen gelesen (o oder s) und dann das nachfolgende Zeichen (; oder \n).
                 Die Schleife soll abbrechen, wenn beim Einlesen ein Fehler auftrat oder wenn das Zeilenende erreicht ist.
                 Ist das nicht der Fall, wird das eingelesene Zeichen im Array abgespeichert (emplace_back).
                 */
                if( file >> c )
                    row.emplace_back( c );
                
                file >> std::noskipws >> skip;
                if( !file || skip=='\n' )
                    break;
            }
            // Nun wurde eine Zeile gelesen und diese wird nun auch abgespeichert.
            raster.emplace_back(row);
        }
        int x=1;
        // Einfach nur die Ausgabe des Rasters.
        for( const auto& row : raster ) // const auto&, weil eine Kopie teuer wäre.
        {
            cout << x++ << " ";
            for( auto c : row ) // Hier mach ich kein const auto&, weil es sich nur um ein char (1 Byte) handelt.
                cout << c << ';';
            cout << endl;
        }
        
        // Der Zugriff auf ein vorhandenes Element ist genauso, wie bei C-Arrays mittels [].
        // boolalpha sagt nur, dass er true und false, anstatt 1 und 0 ausgeben soll.
        cout << "Treffer bei 1|2: " << std::boolalpha << (raster[1][2]=='s') << endl;
        cout << "Treffer bei 3|2: " << std::boolalpha << (raster[3][2]=='s');
    }
    
    


  • @out Vielen, Vielen Dank dir. Funktioniert perfekt.


Anmelden zum Antworten