Stringstream und dynamisches Array



  • Keydo schrieb:

    Kann ich mir im Überwachungsfenster den Inhalt des "isZahl"-Streams anzeigen lassen ?

    Das sollte eigentlich gehen, schau bei dessen Membern. Ansonsten machst du eben eine Ausgabe:

    std::cout << isZahl.str() << std::endl;
    

    Es ist relativ wahrscheinlich, dass der Stream fehlerhaft ist, wenn das Array nicht berührt wird durch den operator >> .



  • Also die Ausgabe läuft wie erwartet, und der Inhalt vom Stream ist auch richtig,
    Ich hab mit stream.fail() geprüft und mit dem Debugger die zeilenweise Ausgabe vom stream auf der Console.

    hmm komisch, sicherlich ist es nur etwas triviales -.-



  • Das ist echt merkwürdig... Versuch mal, mit dem Stream und op>> in eine andere, gerade zuvor deklarierte Variable zu schreiben und überprüf diese. Falls die Variable immer noch nicht den richtigen Wert hat, liegt es definitiv am Stream.

    Wilde Zeiger und sonstige undefinierte Dinge hast du nirgends?



  • int iTest = 0;
    isZahl >> iTest;
    cout << iTest << isZahl.str();
    

    also iTest bleibt 0 *komisch*, aber isZahl.str() gibt mir den Wert des Buffers aus (also den Zeileninhalt).

    Das macht mir n bissel angst :>



  • Hm... vermutlich ist stream-intern etwas kaputt. Was passiert, wenn du dem Stream per str() einen neuen String zuweist und dasselbe nochmals versuchst?

    Ich geh dann mal ins Bett, gute Nacht 😉



  • N8i Nexus,

    selbst n neudefinierten string hat er nicht genommen -.-

    UPDATE: oh ich glaube ich habs, krass -.- wenn ich den Stream vor jedem getline. mit Clear() lösche scheint es zu funktionieren.



  • Hast du tatsächlich bis spät in die Nacht an dem rumprobiert? 😃

    Mit stringstream::clear() setzt du nur die Fehlerflags zurück, was heisst, dass irgendwo etwas schiefgelaufen ist. Du solltest dich vielleicht schon darum kümmern, denn Ignorieren von Fehlern ist nicht immer das Wahre...



  • Hallo, ich wollte ungern deswegen einen neuen Thread aufmachen und versuch es hier als Anhang.

    Ich hab nun nach der While-Schleife veruscht den Speicher des Arrays wieder freizugeben. Dies klappt bis zu einem bestimmten Punkt dann erfolgt eine Fehlermeldung, das der Heap kaputt sei.

    // Speicherplatz wieder freigeben
    	// in umgekehrter Reihenfolge
    
    	// Spalten der I-ten Zeile
    	for(int i = 0; i < iZeilen; i++)
    	{
    		delete dynarray[i];
    	}
    	delete [] dynarray;   // <-- nach dieser Anweisung sagt er mir "HEAP Corrupton ERROR"
    

    Wordurch wird das verursacht? Wie kann ich das vermeiden oder umgehen? Habe ich etwas übersehen?



  • Du hast ja ein zweidimensionales Array, behandelst es aber bei der Freigabe wie ein eindimensionales.

    Richtig wäre:

    for(int i = 0; i < iZeilen; ++i)
    {
        for (int j = 0; j < iSpalten; ++j)
        {
            delete dynarray[i][j];  // 2. Dimension löschen
        }
        delete[] dynarray[i];       // 1. Dimension löschen
    }
    delete[] dynarray;              // 0. Dimension löschen
    


  • jo, ich hab die n8 dran gehockt und gelesen und gelesen ^^

    ich hab mal den Code etwas gekürtzt um die Fehlerstellen besser zu finden.

    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <string>
    using namespace std;
    
    int main(int argc, char** argv)
    {
    
    	// Datei zum Lesen öffnen
    	ifstream stream("eingabe.txt");
    	if( stream.is_open() != true )
    	{
    	cout << "Fehler beim Datei nicht öffnen!\n" << endl;
    	};
    
    	string sBuffer;
    	istringstream isZahl;
    
    	int iSpalten = 0;		// Anzahl der Spalten
    	int iZeilen = 0;		// Anzahl der Zeilen
    
    	bool isMatrixRead = false;
    	int** dynarray = NULL;
    
    	int icnt = 1;
    
     	while(getline(stream, sBuffer))
    	{
    		isZahl.str(sBuffer);
    
    		if(icnt == 1)
    		{
    
    			isZahl >> iZeilen;
    			isZahl >> iSpalten;
    
    			dynarray = new int* [iSpalten];	// Platz für Zeilen reservieren
    
    			// int** -> dyanarray[0]
    			//			dyanarray[1]
    
    			// Nun Speicher fuer die Spalte reservieren
    			for(int i = 0; i < iZeilen; i++)
    					dynarray[i] = new int [iSpalten];			// Speicherplatz für die Spalten reservieren
    
    			// int** -> dyanarray[0] --> dyanarray[0][0] dyanarray[0][1]
    			//			dyanarray[1] --> dyanarray[1][0] dyanarray[1][1]
    
    		}else if (!isMatrixRead)
    		{
    			for(int i = icnt-2; (i < icnt-1 && i < iZeilen);i++ )
    			{
    				for(int k = 0; k < iSpalten; k++)
    				{
    					isZahl >> dynarray[i][k];
    				}
    			}
    			if(icnt-2 == iZeilen)
    				isMatrixRead = true;
    
    		}
    		//isZahl.clear();
    		icnt++;
    	}
    	// Speicherplatz wieder freigeben
    	// in umgekerhter Reihenfolge
    
    /*	
    	for(int i = 0; i < iZeilen; i++)
    	{
    		for(int j = 0; j < iSpalten; j++)
    		{
    			delete dynarray[i][j];
    		}
    		delete[] dynarray[i];
    	}
    	delete [] dynarray;
    */
    return 0;
    }
    

    Die Anweisung "delete dynarray[i][j]" mag er nicht da Objekte die keine Zeiger sind nicht gelöscht werden können.



  • Sorry, ich hatte deine Speicheranforderung falsch im Kopf.

    Schau mal im Code:

    dynarray = new int* [iSpalten]; // Dimension iSpalten
    // ...
    for(int i = 0; i < iZeilen; i++) 
        dynarray[i] = new int [iSpalten]; // auch Dimension iSpalten
    

    Ich weiss nicht, wie du das 2D-Array organisierst, aber eine der beiden Dimensionen muss die Zeilen- und die andere die Spaltenanzahl sein.

    Was den Stream betrifft, seh ich gerade nichts. Geh mit einem Debugger schrittweise durch und überprüf die Fehlerflags, dann siehst du auch, wo der Fehler auftritt.

    Beim FileStream könntest du auch if(!stream) schreiben.


  • Administrator

    Der Fehler mit dem Stream ist wohl sehr trivial.
    Teste mal ob eof() true zurück gibt. Ich bin mir ziemlich sicher, dass er das tut. Du liest Werte aus und der Stream kommt ans Ende und setzt dann das Flag EOF, was ein Fehler ist und man kann aus dem Stream nichts weiteres mehr auslesen.
    Falls wirklich das EOF Flag gesetzt ist, dann ist der Aufruf von clear() gar nicht so verkehrt 😉

    Grüssli



  • Also wie das 2D-Array aufgebaut werden sollte, hab ich mir folgendes szenario angeschaut:

    Bild:
    http://www.hs-augsburg.de/~sandman/c_von_a_bis_z/bilder/16_10.gif

    Bezüglich des EOF.Flags werd ich gleich nochmal guggn.



  • Das EOF-Flag szenario:

    Nachdem er die ersten beide Werte aus dem Stream in die Variablen kopiert hat, setzt er das EOF-Flag. Das EOF-Flag bleibt gesetzt bis eine Clear-Anweisung kommt.

    Das hat aber auch nur Auswirkung beim Auslesen des Streams -.- der Inhalt des Streams wird angepasst.

    Nun bleibt nur noch die spannende Frage wieso nun mein kleines Array rum zickt.

    wird vlt. wieder eine lange N8 ^^


  • Administrator

    Noch kurz Zeit gehabt, dein zweites Problem anzuschauen:

    int main()
    {
        // Beispiel-Erstellung:
        int** pArray = new int*[5];
    
        for(int i = 0; i < 5; ++i)
        { pArray[i] = new int[10]; }
    
        // Beispiel-Zerstörung:
        for(int i = 0; i < 5; ++i)
        { delete[] pArray[i]; } // Hier war glaub ich der Fehler. Ein delete[] wird benötigt und nicht ein simples delete.
    
        delete[] pArray;
    }
    

    Ich glaube damit sollten alle Probleme behoben sein, oder?
    Anstatt C-Arrays könntest du auch std::vector nehmen, dann würden solche delete Probleme erst gar nicht auftauchen :p

    Grüssli


Anmelden zum Antworten