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.


Log in to reply