2D-Array in TXT schreiben



  • Hallo Leute,

    ich lerne gerade C++ und stehe nun vor einem Problem, dass ich irgendwie nicht gelöst bekomme. Leider habe ich auch nicht wirklich das passende über Google oder hier im Forum gefunden...

    Also, es geht um folgendes: Ich habe ein 2-dimensionales Array, dass ich jetzt in eine Txt-Datei ausgeben möchte. Das Trennzeichen ist eine Raute "#".

    Mein Code sieht bisher so aus:

    // Schreibt Array wieder in TXT:
    void array_to_csv(vector<vector<double> > array){
    
    	long zeilen, spalten;
    
    	FILE *file;
    
    	// Länge Zeilen
    	zeilen = array.size();
    	// Länge Spalten
    	spalten = array[0].size();
    
    	file = fopen("test.txt", "w");
    
    	for(int i = 0; i < zeilen; i++){
    		for(int h = 0; h < spalten; h++){
    			printf( "%g#", array[i][h] );
    			fprintf( file, "%g#", array[i][h] );
    		}
    		printf( "\n" );
    		fprintf( file, "\n" );
    	}
        fclose(file);
    }
    

    Dies funktioniert bisher aus sehr gut. Das Problem ist nur, dass das Array mitunter ziemlich groß sein kann > 10.000 x 10.000. Da er die Wert aber zur Zeit auch mit in die Konsole schreibt, dauert das ganze dann sehr lange. Kann ich mir das nicht irgendwie sparen? Ich meine, die Ausgabe in die Konsole, die dabei vermutlich etwas länger dauert, muss ja nicht sein. Es soll ja nur in der Txt-Datei gespeichert werden.

    Ich habe auch etwas von dem Befehl fputs gelesen. Dieser soll schneller sein, als der printf. Allerdings glaube ich, dass dieser nur für strings bzw. chars ist. Kann mir da jemand weiter helfen?

    Vielen Dank schonmal!
    Gruß
    Tobi



  • Lass printf() doch einfach weg, wenn du die Konsolenausgabe nicht willst ... mehr tut die Funktion nämlich nicht.

    EDIT:
    Ganz nebenbei: Da wir hier im C++ Forum sind, darf ich erwähnen, dass es da auch noch die fstream Klassen gibt.



  • mh, das war ja einfach

    dann mal vielen Dank!!!



  • Du könntest den Schleifenkörper auch folgendermassen umbauen, um alle möglichen Arrayformen abzudecken:

    // Iterator über alle inneren Vektoren (Zeilen)
    for( vector<vector<double> >::const_iterator outer = array.begin(); outer != array.end(); ++outer )
    {
       // Iterator über alle Elemente eines inneren Vektors (Spalten)
       for( vector<double>::const_iterator inner = outer->begin(); it != outer->end(); ++inner )
       {
          if( inner != outer->begin() )
          {
             // ab 2. Element Trennzeichen ausgeben
             cout << ";";
          }
          // Element ausgeben
          cout << *inner;
       }
       // neue Zeile
       cout << endl;
    }
    

    Wenn dein Array 10Kx10K Elemente haben kann solltest du es per const Referenz übergeben. Als Referenz, um unnötiges Kopieren zu vermeiden und const, da du während der Ausgabe nur lesend darauf zugreifst.



  • Ich habe ihn so verstanden, dass sein einziges Problem ist, dass er keine Konsolenausgabe will ... dann sollte man sie einfach weglassen.



  • FrEEzE2046 schrieb:

    Ich habe ihn so verstanden, dass sein einziges Problem ist, dass er keine Konsolenausgabe will ... dann sollte man sie einfach weglassen.

    Ja ich weiss, war zu faul fstream statt cout zu benutzen, waren mir dann doch zwei Zeilen Code zu viel.



  • ok, also mein code funktioniert nun auch wunderbar.

    hat der code von DocShoe irgendwelche vorteile?

    habe noch nicht für 10000 elemente getestet, aber hätte der evt. gewindigkeitsvorteile?


  • Mod

    ootobbyoo schrieb:

    ok, also mein code funktioniert nun auch wunderbar.

    hat der code von DocShoe irgendwelche vorteile?

    habe noch nicht für 10000 elemente getestet, aber hätte der evt. gewindigkeitsvorteile?

    Der Code von DocShoe ist viel allgemeiner, ohne wesentliche Nachteile durch die Abstraktion zu haben. Er ermöglicht es nämlich auch "nicht-rechteckige" Arrays auszugeben, was ein durchaus nicht ungewöhnlicher Anwendungsfall ist. Noch allgemeiner wäre es natürlich ein Template anstatt einer spezialisierten Funktion für vector<double> zu nehmen, aber wir wollen mal nicht gleich übertreiben.



  • also, mein code sieht nun folgendermaßen aus:

    // Schreibt M_2 in TXT:
    void M_2_to_csv(vector<vector<vector<double> > > array){
    
    	long zeilen, spalten;
    
    	FILE *file;
    
    	zeilen = array.size(); // Länge Zeilen
    	spalten = array[0].size(); // Länge Spalten
    
    	file = fopen("M_2.txt", "w");
    
    	for(int i = 0; i < zeilen -1 ; i++){  // "-1", da letzte Zeile abgespalten wird
    		for(int h = 0; h < spalten; h++){
    			if(h < spalten - 1){fprintf( file, "%g#", array[i][h][1] );}
    		}
    		fprintf( file, "\n" );
    	}
        fclose(file);
    }
    

    das funktioniert auch wunderbar...

    allerdings möchte ich nun, dass hinter den letzten wert in der zeile keine raute mehr geschrieben wird. wie ist das möglich?



  • Die letzte Ausgabe einfach außerhalb der Schleife machen.



  • das hatte ich auch schon versucht, aber dann schreibt er den letzten wert immer an die zweite stelle und allen anderen werte sind wieder weg...



  • ootobbyoo schrieb:

    das hatte ich auch schon versucht, aber dann schreibt er den letzten wert immer an die zweite stelle und allen anderen werte sind wieder weg...

    Was macht er?



  • also eigentlich sollte es in der txt z.B. so aussehen:

    2#3#4#13#0#0#0

    es sieht dann aber so aus:

    2#0



  • hat niemand eine idee?

    hier nochmal der ursprüngliche code:

    // Schreibt M_2 in TXT:
    void M_2_to_csv(vector<vector<vector<double> > > array){
    
    	long zeilen, spalten;
    
    	FILE *file;
    
    	zeilen = array.size(); // Länge Zeilen
    	spalten = array[0].size(); // Länge Spalten
    
    	file = fopen("M_2.txt", "w");
    
    	for(int i = 0; i < zeilen -1 ; i++){  // "-1", da letzte Zeile abgespalten wird
    		for(int h = 0; h < spalten; h++){
    			fprintf( file, "%g#", array[i][h][1] );
    		}
    		fprintf( file, "\n" );
    	}
        fclose(file);
    }
    

    ich möchte nur, dass am eine der zeile keine raute steht. das kann eigentlich nicht so schwer sein...



  • Hallo,

    for(int i = 0; i < zeilen -1 ; i++){  // "-1", da letzte Zeile abgespalten wird
            for(int h = 0; h < spalten - 1; h++){
                fprintf( file, "%g#", array[i][h][1] );
            }
            fprintf( file, "%g\n", array[zeilen - 2][spalten - 1][1] );
        }
    

    Wie wärs damit?



  • Braunstein schrieb:

    Hallo,

    for(int i = 0; i < zeilen -1 ; i++){  // "-1", da letzte Zeile abgespalten wird
            for(int h = 0; h < spalten - 1; h++){
                fprintf( file, "%g#", array[i][h][1] );
            }
            fprintf( file, "%g\n", array[zeilen - 2][spalten - 1][1] );
        }
    

    Wie wärs damit?

    Wie wärs mit C++?



  • Warum sagst du mir das?
    Der OP wollte printf und FILE verwenden, wer bin ich denn ihn daran zu hindern? 😉



  • Du, bist, BRAUNSTEIN! Aber leider nicht Sparta, sonst hättest du ihn davon überzeugt, dass fprintf und FILE der absolut falsche Ansatz in C++ sind.



  • ok, danke erstmal.

    wieso der falsche ansatz? wie mache ich es denn besser?

    so, wie ich es geschrieben habe, läuft es sehr gut und auch schnell...



  • Richtig wäre es die Streams zu benutzen. Sonst kannst du gleich C schreiben.


Log in to reply