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 GGGWWWWWWWWWWWWWWWWWWWWWGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGAusgegeben 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öhenMfg 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 mussMfgShade37337
-
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!