Du bist nicht angemeldet.

Werbeanzeige

1

02.06.2015, 22:29

C++ | String durchsuchen

Abend,

ich würde gerne eine Tilemap die in Form einer Textdatei vorliegt öffnen. Leider habe ich gerade null Ahnung wie ich bestimmte Sachen in dem String suchen kann. Hier ist mal eine Beispiel Datei:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[Map] 
Mapname: Custom_Map
Mapwidth: 10
Mapheight: 10
Tilewidth: 10
Tileheight: 10
Layers: 2

[Tilesets] 

[Layers] 
Layer 
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,

Layer 
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,

(Für sowas wäre eine Art "Spoiler" Funktion ganz gut :D)

Wie kann ich jetzt die Ids aus den Layern rausfiltern? Mit der find Funktion hab ich schon etwas rumprobiert aber irgendwie klappt das nicht so recht, wenn ich zB. nach "[Layer]" suche, sucht er anscheinend nur das "[".

2

02.06.2015, 23:00

Quellcode

1
ids= filestream.mid(filestream.toStdString().find("[Layer]"), 20);


Und ich sehe gerade wo der Fehler ist, da muss natürlich [Layers] stehen :dash:
Gut jetzt ist aber noch die Frage wie er dann die Ids rausfiltern kann. Es sollte auch gehen wenn die Layer andere Namen haben, aber dann weiß ich halt nicht wie ich an die richtige Stelle springen soll.

Hello_Kitty!

unregistriert

3

03.06.2015, 00:07

Die nächste Zeile nach "[Layers]" enthält den ersten Namen und allen weiteren gehen dem Beispiel nach zwei Leerzeilen ("\n\n") voraus. Eine andere Möglichkeit wäre die nächste nicht leere Zeile zu finden, die nicht mit einer Zahl beginnt. Das wäre wahrscheinlich etwas robuster, wenn du sicher weißt, dass Layernamen nie mit einer Zahl beginnen und die Tile-IDs (?) immer numerisch sind.

Wahrscheinlich wirst du aber zunächst das Ende der Layers-Sektion finden wollen.

4

08.06.2015, 16:05

Hallo,

auch auf die Gefahr hin, gelüncht zu werden... ;)

Warum erstellst du deine Datei nicht in XML und benutzt z.B. TinyXML zum parsen. So kannst du sie leicht unterteilen und die Teile auch leicht einlesen. Damit sparst du dir einen Haufen Arbeit/Ärger und kannst dich um wichtigere Dinge kümmern.


Grüße,

5

08.06.2015, 17:53

Zitat

Hallo,

auch auf die Gefahr hin, gelüncht zu werden... ;)

Warum erstellst du deine Datei nicht in XML und benutzt z.B. TinyXML zum parsen. So kannst du sie leicht unterteilen und die Teile auch leicht einlesen. Damit sparst du dir einen Haufen Arbeit/Ärger und kannst dich um wichtigere Dinge kümmern.


Grüße,


Hab mich noch nie mit XML befasst, aber wenn es so leicht seien soll werde ich es mir mal anschauen. Gibt es irgendwelche Nachteile was die Perfomance angeht?

CeDoMain

Alter Hase

Beiträge: 592

Wohnort: Schwäbisch Gmünd

Beruf: Entwickler für Gebäudeautomation und Industrieroboter

  • Private Nachricht senden

6

08.06.2015, 17:56

Warum erstellst du deine Datei nicht in XML und benutzt z.B. TinyXML zum parsen. So kannst du sie leicht unterteilen und die Teile auch leicht einlesen. Damit sparst du dir einen Haufen Arbeit/Ärger und kannst dich um wichtigere Dinge kümmern.
Hab ich auch schon überlegt. Aber ich dachte mir, ist vielleicht interessanter das auch mal selber zu machen. Ist ja schließlich nicht so schwer.

Mein Vorschlag, wie du vorgehen könntest: Versuch dein Dateiformat so zu ändern, dass du klar einen Variablennamen vom Inhalt trennen kannst. Das kannst du ganz einfach durch Zeichen erreichen, die in den jeweiligen Texten verboten sind. Außerdem würde ich Whitespace (Leerzeichen bzw. Umbrüche) nicht als Trenner akzeptieren, dann kannst du das beliebig formatieren, alles in eine Zeile schreiben und auch Bezeichner mit Leerzeichen verwenden. Bespiel:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[Map] 
#Mapname: "Custom Map"
#Mapwidth: "10"
#Mapheight: "10"
[Layers]
#Layer: 
"
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0
"

Das Einlesen würde ich dann mithilfe einer String-Cursor-Kombination implementieren. Du schreibst dir einfach mehrere Methoden, die alle eine Referenz oder einen Zeiger auf einen String und einen int übergeben bekommen. Die Methoden können dann zum Beispiel Whitespace überspringen oder den Text zwischen dem nächsten '#' und ':' extrahieren. Das könnte dann so aussehen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// Überspringt Leerzeichen
void SkipSpace(std::string& s, int& c)
{
    for (; c < s.size(); c++)
    {
        if (!isspace(s[c])) break;
    }
}

// Extrahiert so Worte wie [Map] oder [Layers]
std::string GetToken(std::string& s, int& c)
{
    for (; c < s.size(); c++)
    {
        if (s[c] == '[') break;
    }
    std::string Name = "";
    for (; c < s.size(); c++)
    {
        if (s[c] == ']') break;
        Name += s[c];
    }
    c++;
    return Name;
}

// Extrahiert so Worte wie #Mapname: oder #Layer:
std::string GetVariable(std::string& s, int& c)
{
    for (; c < s.size(); c++)
    {
        if (s[c] == '#') break;
    }
    std::string Name = "";
    for (; c < s.size(); c++)
    {
        if (s[c] == ':') break;
        Name += s[c];
    }
    c++;
    return Name;
}
Eine letztendliche Parsermethode ruft dann immer abwechselnd die einzelnen Methoden auf und speichert/verarbeitet deren Ergebisse.

Falls du das Dateiformat vorgegeben hast, dann musst du die Trenner halt auf Whitespace und Zeilenumbruch anpassen.
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

CeDoMain

Alter Hase

Beiträge: 592

Wohnort: Schwäbisch Gmünd

Beruf: Entwickler für Gebäudeautomation und Industrieroboter

  • Private Nachricht senden

7

08.06.2015, 18:00

Gibt es irgendwelche Nachteile was die Perfomance angeht?
Nein, so direkt nicht! Du musst dir nur überlegen, wie oft du die Datei speichern willst und ob der XML-Overhead (Das Drumherum, was kein Inhalt ist, sondern bsp. Steueranweisungen wie <...> oder </...>) in einem Verhältnis zu deinen Daten steht. Wenn dein Beispiel das komplexeste ist, was du in eine Datei schreibst, dann empfehle ich dir das selber zu machen - das ist mit meinem Vorschlag ziemlich einfach zu machen. Wenn du zu meinem Code noch mehr Fragen hast, dann kannst du mich auch gerne nochmal fragen.
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

8

08.06.2015, 18:04

Zitat

Nein, so direkt nicht! Du musst dir nur überlegen, wie oft du die Datei speichern willst und ob der XML-Overhead (Das Drumherum, was kein Inhalt ist, sondern bsp. Steueranweisungen wie <...> oder </...>) in einem Verhältnis zu deinen Daten steht. Wenn dein Beispiel das komplexeste ist, was du in eine Datei schreibst, dann empfehle ich dir das selber zu machen - das ist mit meinem Vorschlag ziemlich einfach zu machen. Wenn du zu meinem Code noch mehr Fragen hast, dann kannst du mich auch gerne nochmal fragen.


Alles klar, dein Beispiel sieht aufjedenfall interessant aus, ich schau mal was sich damit machen lässt.

Beiträge: 1 239

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

9

08.06.2015, 18:12

Wenn es schnell gehen soll, nimm PugiXML.
Das habe ich meistens verwendet. Das soll auch viel schneller sein und die Einrichtung(Man schiebt die drei Dateien einfach in das Projekt) bzw. das Interface fand ich eigentlich auch sehr überzeugend.

Bei der größe an Daten die du hier präsentierst wird das selbstverständlich nicht überwiegen.

Der größte Vorteil von XML ist, dass man jeder Zeit an jeder Stelle weitere Daten einfügen kann. Das macht es wirklich optimal über die Zeit zu erweitern.

Werbeanzeige