Tipps/Ratschläge zur Isolierung eines Codes aus einer Textdatei
-
hi, ich ersuche Hilfe bzw Tipps um folgendes zu realisieren:
Ich habe einen "Code" in einer Textdatei und möchte diesen Code dann in meinem Programm abschnittweise in einer Variable bzw einem Container speichern (Hier bereits das erste Problem: Welcher Container? std::vector? std::map?).
Ich möchte/muss es abschnittweise speichern, da der Code folgendermaßen aussieht://Code-Anfang [BEZEICHNUNG] Key1 = Wert1 OptionalerKey1 = OptionalerWert1 Key2 = Wert2 Key3 = Wert3 OptionalerKey2 = OptionalerWert2 Key4 = Wert4 Key5 = Wert5 //Code-Ende //Code-Anfang [NEUE_BEZEICHNUNG] //usw.
Die Kommentarzeilen, dass ein neuer Code beginnt bzw. endet gibt es im Original natürlich nicht...
Da ich leider bereits beim Aussuchen des Containers Probleme hatte/habe, konnte ich mir bezüglich der Isolierung des Codes noch keine wirklichen Gedanken machen, weshalb ich hier auf einige Tipps/Ratschläge hoffe
Mfg Stephen
-
pro Abschnitt eine std::map<string,string>
-
Ich würde eine mehrdimensionale Struktur dafür verwenden map<string,map<string,string>> (der Schlüssel der äußeren Ebene ist die Bezeichnung, auf der inneren Ebene stehen Schlüssel/Wert-Paare).
PS: Wenn du unter Windows unterwegs bist - ist eventuell GetPrivateProfileString und Kollegen etwas für dich?
-
Hm, da wurde ich wohl nicht ganz verstanden... hab mich zu unklar ausgedrückt.
Mir geht es nicht darum, die einzelnen Key-Wert-Paare zu speichern, das ist egal, es geht einzig allein um die Zeilen.
Vllt etwas klarer ausgedrückt://Code-Anfang [BEZEICHNUNG] Zeile1 OptZeile1 Zeile2 Zeile3 OptZeile2 Zeile4 Zeile5 //Code-Ende //Code-Anfang [NEUE_BEZEICHNUNG] //usw.
Sinn dahinter ist folgender: Der Benutzer soll später mittels bestimmter Funktionen in den gespeicherten Daten bestimmte Bezeichner finden können und diese dann ersetzen.
Hier mal mein Idee (aus dem Kopf getippt, deshalb evt. Fehler entschuldigen)
vector<map<int, string>> storage; //Großer Container ifstream streamIn("testfile.txt"); //Testdatei map<int, string> data; //Mein Container int lineCount; //Int zum Ermitteln der Anzahl der Zeilen bool blockInUse = false; //Bool; überprüft, ob ein Codeblock "bearbeitet" wird while(!streamIn.eof()) { string line; //Zeile getline(streamIn, line); //Datei wird zeilenweise eingelesen if(line.empty()) //Leere Zeile übersprungen continue; if(line[0] == '[' && blockInUse == false) //Falls die Zeile mit '[' beginnt (-> "[BEZEICHNER]" und kein Codeblock bearbeitet wird ... { blockInUse = true; //... wird ein Block "bearbeitet" lineCount = 0; //Zeilen auf 0 } if(line[0] == '[' && blockInUse == true) //Falls die Zeile mit '[' beginnt (-> s.o.) und ein Block bearbeitet wird ... { storage.push_back(data); //Wird die map dem großen Container hinzugefügt. PROBLEM: Falls nicht wieder alle Werte belegt sind (OptWerte), werden diese trotzdem dem großen Container hinzugefügt -> Problem! blockInUse == false; //Block wird nicht mehr bearbeitet continue; //Schleife von vorn... } data[lineCount] = line; //Falls -^ nicht eintritt, wird die Zeile "lineCount" mit dem Wert "line" der map hinzugefügt ++lineCount; //Wir springen in die nächste Zeile->lineCount wird inkrementiert }
Wie man im Code erkennen kann, ist das nicht sonderlich ausgereift...
Das Problem ist immer noch, welcher Container bietet sich an? (Man muss auch bedenken, dass der Nutzer später darauf zugreifen soll (Spricht für map, da man hier leicht mit map.find() arbeiten kann). Allerdings wie kann ich die einzelnen Codeblöcke überhaupt richtig isolieren... die oben gezeigte Pseudomethode finde ich persönlich nicht wirklich schön und sicher ist es wohl auch nicht...
Mfg Stephen
-
Wie gesagt, mit einer map<> kannst du die Zuordnung der Sektionsbezeichner zu den Sektionen (Sub-Maps) herstellen. Das Parsen der Datei mußt du dann natürlich selber erledigen (btw, so wie dein Beispielcode aussieht, packst du die leeren Blöcke sofort in deinen vector<>):
map<string, blockinhalt> daten; while(getline(datei, zeile)) { if(zeile[0]=='[') // Anfang neuer Block { daten[aktblock] = block; aktblock = zeile; block.clear() } else // Datenzeilen block.push_back(zeile); }
PS: Was du mit optionalen oder notwendigen Zeilen je Sektor machst, mußt du selber wissen.
-
Also ich stehe glaube ich total auf dem Schlauch...
Du schlägst vor, dass ich eine map<string, vector<string>> erstelle, die den Codeblock so speichert: (Bsp)
test_map["Funktion_1"] = Vector_Mit_Den_Zeilen_des_CodeBlocks;
Hab ich das soweit verstanden?
-
MasterStephen schrieb:
Sinn dahinter ist folgender: Der Benutzer soll später mittels bestimmter Funktionen in den gespeicherten Daten bestimmte Bezeichner finden können und diese dann ersetzen.
Auch dann wäre es doch klasse, wenn er die Key-Value paare vorliegen hat, oder? Boost.Program_Options nimmt da einen guten Batzen Arbeit ab
-
MasterStephen schrieb:
Also ich stehe glaube ich total auf dem Schlauch...
Du schlägst vor, dass ich eine map<string, vector<string>> erstelle, die den Codeblock so speichert: (Bsp)
test_map["Funktion_1"] = Vector_Mit_Den_Zeilen_des_CodeBlocks;
Hab ich das soweit verstanden?
So ähnlich, ich glaub er wollte aber Maps von diesem Typ noch in eine andere Map stecken, die die Gruppen enthält.