3-dimensionale map
-
Hallo,
ich habe in einer Klasse eine Konfiguration als map<string,string> realisiert.
nun versuche ich eine dritte dimension hinzuzufügen (section einer Ini-Datei als int [index in einer 2. map<int,string>])map selbst versteht scheinbar nur 2 Elemente, wie könnte ich das anders realisieren?
Gruß Frank
-
Ich verstehe nicht, was du bzgl map<string,string> mit "eine dritte dimension hinzufügen" meinst.
Ich rate einfach mal:
- map< string, pair<int,string> >
- map< pair<string,int>, string >
- map< string, map<int, string> >
- ...
-
Die straightforward Lösung wäre wohl eine
map<string, map<string, string>>.
Ansonsten würde ich mir überlegen, ob du den Sectionname nicht einfach vorne an den Key dranhängen kannst. Außerdem würd ich mir überlegen, ob ich nicht eher eine unordered_map will.
-
danke für die schnellen Antworten
ich wusste gar nicht, dass sowas geht...
in meinem Fall wäre das dann ja
map< int, map<string, string> >
wobei int der index (bzw. iterator) des sectionnamens in einer 2. map (zuweisung zu einem Sectionnamen)
könnte zwar auch einen vector nehmen, aber dann habe ich probleme mit dem index, wenn ich da werte lösche..ich brauche einen unveränderlichen index.
wenn ich den Sectionnamen bei jedem Item hinterlege (map< string, map<string, string> > ) habe ich einen massiven speicherverbrauch (auch wenn das bei aktuellen Speichergrößen kaum ins Gewicht fallen würde)
was wäre die unordered map?
wie gesagt, ich will in die Struktur eine Ini-datei laden/rekonstruierenGruß Frank
-
frank schrieb:
wenn ich den Sectionnamen bei jedem Item hinterlege (map< string, map<string, string> > ) habe ich einen massiven speicherverbrauch (auch wenn das bei aktuellen Speichergrößen kaum ins Gewicht fallen würde)
Da vertust Du Dich massiv bzgl "massiven Speicherverbrauch". Der Sectionsname würde in der Datenstruktur nur 1mal pro Sektion gespeichert.
Vor einem Jahr habe ich das auch mal per map<string,map<string,string> > gemacht. Im Nachhinein stellte ich aber fest, dass "Ini" zu wenig hierarchisch ist und ich tiefere Ebenen "frickeln" musste. Hätte ich mal lieber XML verwenden sollen...
-
typedef std::string Key; typedef std::string Value; typedef std::string SectionKey; typedef std::map<Key, Value> Section; typedef std::map<SectionKey, Section> IniFile;Ich würde aber überlegen das in einer Klasse zu kapseln, um die Zugriffe etwas lesbarer zu machen.
-
ah, jetzt seh ichs auch, dass der sectionname nur einmal gespeichert wird

ich baue dass schon in eine Klasse, alleine schon wegen der parsing-routinen
auf den ersten Blick macht das construct map<string,map<string,string>> das ganze einfacher, besonders, weil ich mir die zuordnung der section zu einer index-variable spare
nur wie muss der äußere interator aussehen?
der innere bleibt ja bei "std::map<std::string, std::string>::iterator value_iter;"...nur der äußere müsste als 2.Element eine map beinhalten.//edit:
folgendes compiliert ohne Fehler...ist es auch richtig?
//g++ -Wall inifile.cpp -o inifile # include <string> //cpp-string #include <map> //for config using namespace std; typedef std::string IniKey; typedef std::string IniValue; typedef std::string IniSectionKey; typedef std::map<IniKey, IniValue> IniSection; typedef std::map<IniSectionKey, IniSection> IniFile; int main(int argc, char *argv[]) { IniFile ini; //std::map<std::string,std::string> std::map<std::string, IniSection>::iterator section_iter; std::map<std::string, std::string>::iterator value_iter; for (section_iter = ini.begin(); section_iter != ini.end(); section_iter++) { std::string section_name=section_iter->first; IniSection section=section_iter->second; for (value_iter = section.begin(); value_iter != section.end(); value_iter++) { std::string value_name=value_iter->first; std::string value_value=value_iter->second; } } }
-
Hallo,
ich habe es mittlerweile soweit, dass das parsing der Datei funktioniert, aber etweder wird nichts hinzugefügt, oder das auslesen ist falsch...
hier mal mein Code:
typedef std::string tIniKey; typedef std::string tIniValue; typedef std::string tIniSectionKey; typedef std::map<tIniKey, tIniValue> tIniSection; typedef std::map<tIniSectionKey, tIniSection> tIniFile; std::map<std::string, tIniSection>::iterator section_iter; std::map<std::string, std::string>::iterator value_iter; //private der klasse: tIniSection fSection; //zuweisung in methode fSection=fIniFile[section]; fSection[key]=value; //auslesen in anderer methode for (section_iter = fIniFile.begin(); section_iter != fIniFile.end(); section_iter++) { fSection=section_iter->second; for (value_iter = fSection.begin(); value_iter != fSection.end(); value_iter++) { cout << "[Section]:" << section_iter->first << "Key:" << value_iter->first.c_str() << ",Value:" << value_iter->second.c_str() << endl; } }sieht jemand den Fehler? für mich scheint alles zu passen
so wie es aussieht, wird die Section erstellt, aber die untermap nicht (oder sie wird irgendwo wieder freigegeben)
ich habe den kompletten code mal hier hochgeladen: http://nopaste.info/6e393da13f.html
Gruß Frank
-
Wir wärs mit boost::multi_index ?
-
möchte ungern fremde libs verwenden, wenn die funktionalität durch die STL verfügbar ist.
wenn ich ein neues Item so anlege, funktioniert es:
fIniFile[section][key]=value;in hinblick auf case-insensitive Zugriffe und Vermeidung von doppelten Sections/Keys, möchte ich aber nach der section suchen, ggf. erstellen und falls sie existiert hat, den key suchen.
das geht als Einzeiler nach der Schreibweise oben nicht.
-
Hallo,
ich habe es hinbekommen...ich suche nach der Section/dem Key case-insensitive und nutze den vorhandenen Namen (wenn existiert, sonst den parameter) um den Wert zu setzen.
void SetValue(string section,string key,string value) { section=trim(section); key=trim(key); value=trim(value); string existing_section=section_find(section); if (existing_section=="") { //section does not exist fIniFile[section][key]=value; } else { string existing_key=key_find(section,key); if (existing_key == "") { //key does not exist in existing section fIniFile[existing_section][key]=value; } else fIniFile[existing_section][existing_key]=value; } }somit ist meine INI-Klasse soweit komplett. Sie ist mit ca. 300 Zeilen recht klein und funktioniert unter linux und windows...man muss nur die entsprechende fileexists-Funktion aktivieren.
Wer interesse hat...ich habe sie unter http://www.fw-web.de/download.php?file=cpp/inifile.cpp hochgeladen
Gruß Frank