Datei einlesen mit trennzeichen?
-
Hallo
also ich möchte gern eine Datei einlesen, die in etwa so aussehen soll:1; passwort; 16; 8; ================ ==_#_____~~===== =_#___+______=== =____________=== =__-------___=== =____________=== ================;die ";" sollen abei das Trennzeichen darstellen.
Zur erklärung: Ich habe mir ein kleines spiel geschrieben ^^
*1 -> ist das Level dieses Spielfeldes
*passwort stellt das passwort des lvls da
*16 -> ist die Breite des Spielfeldes
*8 -> ist die Höhe des Spielfeldes + 1
* Der rest ist das Spielfeld selbst.Ich habe mir auch ein paar andere Theman angesehen zu diesem Thema, aber die meisten habe es zeilenweise eingelesen. Bei mir ist es aber so, dass das Spielfeld in EIN string vector reinkommen soll -> das heist jede zeile ein "push_back"^^.
In dieser Datei sollen auch Mehrer solcher Level stehen. Und ich möchte auch etwas schreiben der nur ein Bestimmtes Level ausliest.
MFg
-
Eine einzelne Zeile kannst du mit getline() auslesen und dann interpretieren (zur Not kannst du auch einen zusätzlichen Parameter angeben, dann liest er nicht bis zum NewLine, sondern bis zum übergebenen Zeichen). Ich würde die ersten vier Zeilen gesondert einlesen und interpretieren - und anschließend die Spielfeld-Daten in einer Schleife.
PS: Um gezielt auf einen bestimmten Level zugreifen zu können, mußt du den Offset vom Dateianfang kennen - und da die einzelnen Level unterschiedlich viel Platz benötigen können, bedeutet das höchstwahrscheinlich durchzählen. Oder du liest alle Levels ein und speicherst sie während der gesamten Laufzeit in einem vector<>.
-
Ich habe mir auch schon gedacht, das ich die gesammten level einlese -> aber ich will nicht so viel speicher verbraten (auch wenn es vlt jetzt wenig ist) Ich habe mir gedacht das man vlt ein Trennzeichen definieren könnte, welches ein LVL beinhalten also zumbeispiel "A" -> anfang der leveldefinition und "E" für ende der lvldefinition.
Oder wenn es wirklich nicht anders geht, dann muss ich eben jede Leveldefinition in EINE zeile schreiben. Und diese dann einlesen -> dazu müsste ich danach aber den String bearbeiten ^^ -> weis ich nicht wie ich das anstellen sollte.
-
Klar kannst du ein Trennzeichen definieren, aber das hilft dir nicht bei deinem ursprünglichen Problem - in der Datei zum n'ten Vorkommen eines Zeichens zu springen ist nicht gerade trivial.
Wenn es dir zu viel Platz ist, alle Levels im RAM zu halten, gäbe es noch eine Alternative - du merkst dir nur den Offset jedes Levels im RAM und kannst dann bei Bedarf über seekg() dorthin springen. (funktioniert allerdings nur bei lesendem Zugriff - beim Schreiben (Level-Editor o.ä.) kommt noch dazu, daß du alle nachfolgenden Level umkopieren müsstest, um Lücken zu füllen bzw. zu schaffen)
PS: Haben deine Level eigentlich eine definierte Maximalgröße? Oder ist die Höhe und Breite nach oben unbeschränkt?
-
Wenn es dir zu viel Platz ist, alle Levels im RAM zu halten, gäbe es noch eine Alternative - du merkst dir nur den Offset jedes Levels im RAM und kannst dann bei Bedarf über seekg() dorthin springen. (funktioniert allerdings nur bei lesendem Zugriff - beim Schreiben (Level-Editor o.ä.) kommt noch dazu, daß du alle nachfolgenden Level umkopieren müsstest, um Lücken zu füllen bzw. zu schaffen)
das klinkt wunderbar -> wie geht das ^^
Einen Level editor ist sinlos, da man es mit einen einfachen Editormachen kann^^ -> also brauche ich kein extra tool dafür zu schreiben.
Maximalgrößen haben sie -> 256*256 -> da ja der char die kleinste einheit war (nach bool ^^) und es viel zu viel zeit benötigte die karte neu zu zeichenen -> ich mach nach jeder bewegegung "CLS" und schreibe die karte neu -> bei 265*265 ist das schon zeitaufwendig ^^
-
Rainu schrieb:
Wenn es dir zu viel Platz ist, alle Levels im RAM zu halten, gäbe es noch eine Alternative - du merkst dir nur den Offset jedes Levels im RAM und kannst dann bei Bedarf über seekg() dorthin springen. (funktioniert allerdings nur bei lesendem Zugriff - beim Schreiben (Level-Editor o.ä.) kommt noch dazu, daß du alle nachfolgenden Level umkopieren müsstest, um Lücken zu füllen bzw. zu schaffen)
das klinkt wunderbar -> wie geht das ^^
Im Prinzip ungefähr so:
vector<istream::pos_type> Level_offsets; do { Level_offsets.push_back(infile.tellg()); Read_Level(infile); //Daten eines Levels einlesen - die Ergebnisse kannst du wegwerfen //wichtig ist hier nur, daß der Lesezeiger der Datei hinterher auf dem Anfang des nächsten Levels steht } while(infile); //so, jetzt weißt du für jeden Level, wo in der Datei seine Daten anfangen. int Level_num = 13; infile.seekg(Level_offsets[Level_num]; Level aktuell = Read_Level(infile);(PS: Und tu dir selbst einen Gefallen und halt wenigstens den gerade aktuellen Level im RAM - die Daten bei jeder Bewegung neu einlesen zu wollen ist einfach nur unnötig)
Maximalgrößen haben sie -> 256*256 -> da ja der char die kleinste einheit war (nach bool ^^) und es viel zu viel zeit benötigte die karte neu zu zeichenen -> ich mach nach jeder bewegegung "CLS" und schreibe die karte neu -> bei 265*265 ist das schon zeitaufwendig ^^
Nicht gerade die eleganteste Lösung - ich würde wohl nur die Abschnitte neu schreiben, in denen sich etwas geändert hat (Stichwort: gotoxy()).
-
so ich habs gleich mal ausprobiert ^^
using namespace std; int main(int argc, char *argv[]) { ifstream leseDatei("karte.txt"); vector<istream::pos_type> lvl_offsets; string tmp; do { lvl_offsets.push_back(leseDatei.tellg()); getline(leseDatei,tmp,';'); getline(leseDatei,tmp,';'); getline(leseDatei,tmp,';'); getline(leseDatei,tmp,';'); getline(leseDatei,tmp,';'); //Daten eines Levels einlesen - die Ergebnisse kannst du wegwerfen //wichtig ist hier nur, daß der Lesezeiger der Datei hinterher auf dem Anfang des nächsten Levels steht }while(leseDatei); cout << lvl_offsets.size(); leseDatei.seekg(lvl_offsets[1]); getline(leseDatei,tmp,';'); cout << "\n" << tmp; system("PAUSE"); return EXIT_SUCCESS; }inhalt der zu lesenden datei:
1;def;16;8;
==#~~=====
=+_===
=-------===
=#_===
=#______===
================;
2;def;16;8;==#~~=====
=+___===
=-------___===
=____________===
=____________===
================;
3;def;16;8;==#~~=====
=+_===
=-------===
=#______===
=____________===
================;Ausgabe:
3
Druecken Sie.....Das heist -> er hat zwar alle Lvl wie gewünscht erfasst, aber wenn ich versuche dahin zu springen und daten zu lesen will er es nicht machen ^^
(PS: Und tu dir selbst einen Gefallen und halt wenigstens den gerade aktuellen Level im RAM - die Daten bei jeder Bewegung neu einlesen zu wollen ist einfach nur unnötig)
Das habe ich schon ^^ -> ich habe zuerst die Map im Code erstellt -> dann habe ich sie per eingabe einlesen lassen -> und nun mache ichi es über datei ^^
Nicht gerade die eleganteste Lösung - ich würde wohl nur die Abschnitte neu schreiben, in denen sich etwas geändert hat (Stichwort: gotoxy()).
Das wäre meine nächste Frage gewesen

-
Sorry, mein Fehler - nach der Schleife ist ja noch das eofbit und failbit des Streams gesetzt, die mußt du erst mit clear() aufräumen.
-
ok habe ich gemacht -> zeigt jetzt aber das falsche an
================
==#~~=====
=+___===
=-------___===
=____________===
=____________===
================;ich war der meinung, dass der Zeiger auf das lvl zeigt also:
-> 2;def;16;8; ================ ==_#_____~~===== =_____+______=== =__-------___=== =____________=== =____________=== ================;aber er zeigt auf das hier:
2;def;16;8;
-> ================
==#~~=====
=+___===
=-------___===
=____________===
=____________===
================;hab ich irgendwo einen Denkfehler ^^
-
Gib mal nur zu Testzwecken die Daten aus, die während der Schleife eingelesen wurden.
-
Eins is schon mal klar -> er macht nicht das was er soll ^^
Code:
..... do { lvl_offsets.push_back(leseDatei.tellg()); getline(leseDatei,tmp,';'); cout << tmp << "\n"; getline(leseDatei,tmp,';'); cout << tmp << "\n"; getline(leseDatei,tmp,';'); cout << tmp << "\n"; getline(leseDatei,tmp,';'); cout << tmp << "\n"; getline(leseDatei,tmp,';'); cout << tmp << "\n---------------------------------------\n"; //Daten eines Levels einlesen - die Ergebnisse kannst du wegwerfen //wichtig ist hier nur, daß der Lesezeiger der Datei hinterher auf dem Anfang des nächsten Levels steht }while(leseDatei); ....Ausgabe:
1
def
16
8================
== # ~~=====
= + ===
= ------- ===
= # ===
= # ===---------------------------------------
== # ~~=====
= + ===
= ------- ===
= ===
= ===3
def
16
8
---------------------------------------== # ~~=====
= + ===
= ------- ===
= # ===
= ===---------------------------------------
3== # ~~=====
= + ===
= ------- ===
= ===
= ===
-
Für alle die es wissen wollen:
es musste noch das Binary-Flag gesetzt werden ^^
ifstream leseDatei("karte.txt",ios::binary);Jetzt geht es einwandfrei ^^