fstream getline - Nächste Zeile?



  • Hallo!

    Ich habe probiert, den Lesezeiger um 1 zu erhöhen und dann neu zu setzen, damit in die nächste Zeile gesprungen wird.
    Funktioniert aber nicht.

    class Field
    {
    	char maps[50][15][78];
    public:
    	Field();
    	~Field();
    
    	void drawMap();
    };
    
    Field::Field() 
    { 
        // Load maps
    	// For each map
        for(short i = 0; i < 2; i++) 
        { 
    		stringstream curMap;
    		curMap << "map";
    		curMap.width(2); 
            curMap.fill('0');
    		curMap << i + 1 << ".txt";
    
    		fstream mapFile(curMap.str().c_str(), ios::in | ios:: out | ios::binary);
    
    		if(mapFile.fail())
                cout << curMap.str() << " nicht geladen!" << endl; 
            else 
    		{
                cout << curMap.str() << " geladen!" << endl; 
    
    			// For each row 
    			for(short r = 0; r < 15; r++) 
    			{
    				// For each element 
    				for(short e = 0; e < 78; e++) 
    					mapFile.getline(maps[i][r], 78);
    				long rpos = mapFile.tellg();
    				rpos++;
    				mapFile.seekp(rpos, ios::cur);
    			} 
    		}
        } 
    } 
    
    Field::~Field()
    {
    	;
    }
    
    void Field::drawMap()
    {
    	for(short r = 0; r < 15; r++)
    	{
    		for(short e = 0; e < 78; e++)
    		{
    			cout << maps[0][r][e];
    		}
    		cout << endl;
    	}
    }
    

    Die map01.txt sieht so aus:

    GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGSSSSSSSSSSSSSSSSSS
    GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGSSSSSSSSSSSSSSSSSSSSSSSS
    GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGSSSSSSSSSSSSSSSSSSSSSSSS
    GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGSSSSSSSSSSSSSSSSSSSSSSSS
    GGGGGGGGGGGGGGGGGGGGGGGGSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
    GGGGGGGGGGGGGGGGGGGGGGGGSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
    WWWWWWWWWWWWWWWWWWGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGSSSSSSSSSSSSSSSSSSSSSSSSSSS
    WWWWWWWWWWWWWWWWWWGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGSSSSSSSSSSSSSSSSSSSSSSSSSSS
    WWWWWWWWWWWWWWWWWWGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
    GGGWWWGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
    GGGWWWGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
    GGGWWWWWWGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
    GGGWWWWWWWWWWWWWWWWWWWWWGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
    GGGWWWWWWWWWWWWWWWWWWWWWGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
    GGGWWWWWWWWWWWWWWWWWWWWWGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
    

    Ausgegeben wird jedoch nur die 1. Zeile, der Rest sind irgendwelche Zeichen.



  • der lesezeiger zeigt auf das aktuelle ZEICHEN nicht auf die ZEILE.
    das heist dü müsstest entweder alles zeichenweise einlesen oder den zeiger immer um sizeof(zeile) erhöhen

    Mfg Shade37337



  • Aber der Zeiger zeigt nach getline doch auf das letzte Element, und mit rpos++ dann auf das erste der nächsten Zeile??

    Und warum funktioniert

    // For each element 
    				for(short e = 0; e < 78; e++) 
    					mapFile.getline(maps[i][r], 78);
    				long rpos = mapFile.tellg();
    				rpos += 79;
    				mapFile.seekp(rpos, ios::cur);
    

    nicht? Es wird immer nur die 1. Zeile angezeigt.

    😕



  • Meierei schrieb:

    Und warum funktioniert [...] nicht? Es wird immer nur die 1. Zeile angezeigt.

    Weil du immer in dieselbe Stelle deines Arrays einliest. In dieser Schleife ändern sich weder i noch r. Vermutlich soll da statt i e stehen. Dann läuft die Schleife aber zu weit, e darf höchstens 49 werden.



  • Meierei schrieb:

    Aber der Zeiger zeigt nach getline doch auf das letzte Element, und mit rpos++ dann auf das erste der nächsten Zeile??

    Nein, der zeigt nach jedem getline auf den Anfang der Folgezeile.

    @shade:
    Sei mir nicht böse aber halte dich doch ein bisschen mit Deinem Halbwissen zurück. sizeof(zeile) bringt je nach Typ von zeile (String oder Char-Array) wenig bis garnichts, weil es entweder die Länge des gesamten Fassungsvermögens des char-Arrays oder die Größe der Verwaltungsdaten der string-Klasse zurückgibt.



  • sizeof(zeile)
    wa rals pseudocode gemeint den er was ersetzten muss

    MfgShade37337



  • Meierei schrieb:

    Aber der Zeiger zeigt nach getline doch auf das letzte Element, und mit rpos++ dann auf das erste der nächsten Zeile??

    Und warum funktioniert

    // For each element 
    				for(short e = 0; e < 78; e++) 
    					mapFile.getline(maps[i][r], 78);
    				long rpos = mapFile.tellg();
    				rpos += 79;
    				mapFile.seekp(rpos, ios::cur);
    

    nicht? Es wird immer nur die 1. Zeile angezeigt.

    😕

    Überlege dochmal was du da machst! map[i][r] ist ein array aus 78 elementen. Und was macht die getline-Funktion? Schau es dir genau an: http://cppreference.com/cppio/getline.html
    Sie liest mehrere Zeichen! Also brauchst du sie nicht 78 mal aufzurufen. Einmal reicht. Außerdem musst du bedenken, dass sie bis num - 1 einliest, also musst du 79 als dritten Parameter benutzen.

    Nun musst du noch etwas wissen: Wenn die maximale Anzahl, also 78, erreicht wurde, bevor ein Zeilenumbruch erreicht wurde, wir der Status des Stream auf einen Fehlschlag gesetzt. Dies musst du abfangen und verarbeiten. Außerdem musst du den Zeilenumbruch, so wie du dir es auch gedacht hast, überspringen, nur: Manchmal ist der Zeilenumbruch 2 Zeihen lang! Dann besteht er aus \r\n. Deswegen solltest du ihn lieber so überspringen:

    mapFile.ignore(2, '\n');
    

    Noch ein paar Sachen: Neben fail() musst du auch noch auf eof() prüfen, da dies auch einen fail() auslösen kann. Ganz sicher bin ich mir da nicht...
    Außerdem würde ich kein ios::binary benutzen bei einer Textdatei. Dort hat getline Nebenwirkungen die ich noch nicht verstanden habe, also einfach weglassen.

    Ich hoffe mal ich hab nichts falsches erzählt, aber so könnte es dann aussehen:

    #include <iostream>
    #include <sstream>
    #include <fstream>
    using namespace std;
    
    class Field {
        public:
            Field();
            void drawMap();
        private:
            char maps[50][15][78];
    };
    
    Field::Field() {
        // Load maps
        // For each map
        for(int i = 0; i < 2; ++i) {
            stringstream curMap;
            curMap << "map";
            curMap.width(2);
            curMap.fill('0');
            curMap << i + 1 << ".txt";
    
            ifstream mapFile(curMap.str().c_str());
    
            if(mapFile.fail()) {
                cout << curMap.str() << " nicht geladen!" << endl;
            } else {
                cout << curMap.str() << " geladen!" << endl;
    
                for(int r = 0; r < 15; ++r) {
                    mapFile.getline(maps[i][r], 79);
                    if(mapFile.fail() && !mapFile.eof()) {
                        mapFile.clear();
                        mapFile.ignore(2, '\n');
                    }
                }
            }
        }
    }
    
    void Field::drawMap() {
        for(int r = 0; r < 15; r++) {
            for(int e = 0; e < 78; e++) {
                cout << maps[0][r][e];
            }
            cout << endl;
        }
    }
    
    int main() {
        Field m;
        m.drawMap();
    }
    


  • Ohh vielen Dank es funktioniert. Gerade fand ich in meinem Buch das Kapitel "Mehr über Dateien". Vielleicht hätte ich es mir zuerst ansehen sollen.

    Jedoch gibt es immer ein paar Dinge, die man wissen sollte.



  • Mir ist gerade aufgefallen, dass ich doch etwas Scheiße gelabert habe. Also: Wenn du 79 angibst, und die Zeile 78 Zeichen hat, dann setzt er das fail-bit nicht, sondern nimmt das '\n' auch aus dem Stream. Ist ja auch klar, es hat ja alles geklappt. Also brauchst du das mit dem fail gar nicht:

    for(int r = 0; r < 15; ++r) {
                    mapFile.getline(maps[i][r], 79);
                }
    

    Falls du aber noch bedenken willst, dass eine Zeile mal länger als 79 Zeichen ist, kannst du das einbauen:

    for(int r = 0; r < 15; ++r) {
                    mapFile.getline(maps[i][r], 79);
                    if(mapFile.fail() && !mapFile.eof()) {
                        mapFile.clear();
                        mapFile.ignore(numeric_limits<streamsize>::max(), '\n');
                    }
                }
    

    mfg.



  • Jo, habs jetzt so gemacht:

    Field::Field() 
    {
    	cout << "Spielfeld laden . . ." << endl;
    
    	// Load maps - For each map
        for(int i = 0; i < 5; ++i) 
    	{ 
    		stringstream curMap; 
            curMap << "map"; 
            curMap.width(2); 
            curMap.fill('0'); 
            curMap << i + 1 << ".txt"; 
    
            ifstream mapFile(curMap.str().c_str()); 
    
            if(mapFile.fail()) 
                cout << curMap.str() << " nicht geladen!" << endl;
    		else
    		{
                cout << curMap.str() << " geladen!" << endl;
    			// For each row
    			for(int r = 0; r < 15; ++r)
    				mapFile.getline(maps[i][r], 79);
    		}
        }
    }
    

    Passt jetzt, danke!


Anmelden zum Antworten