[Projektgestaltung] .ini Parser
-
c-freak schrieb:
CStoll schrieb:
In C++ hätte ich die gesamte INI-Datei in eine "map<string,map<string,string> >" eingelesen und mir dort die richtigen Werte herausgepickt. In C mußt du dir entsprechende Suchstrutkuren wohl selber basteln.
völlig falsch! in C nimmt man für gewöhnlich eine vorhandene library, wie z.b. http://ndevilla.free.fr/iniparser/
C hat solche Sachen allerdings nicht an Bord, also muß man entweder auf externe Quellen ausweichen oder sich selber etwas schreiben. (wobei ich vermutlich auch die WinAPI-Funktionen GetPrivateProfile*() vorgeschlagen hätte - wenn die Frage in einem anderen Board gekommen wäre.
@Pyro: Für den Anfang solltest du dir eine Datenstruktur ausdenken (oder übernehmen, nicht war vista?), mit der du den Inhalt der .INI im Programm verwalten kannst. Dann baust du dir die nötigen Funktionen, um diese Datenstruktur lesen, durchackern (auf der Suche nach bestimmten Einträgen) und schreiben zu können.
-
Also ich möchte nen Parser basteln, der vom Inhalt/Gestaltung der ini Datei unabhängig Parameter und Werte raussucht / zuordnet. Den ich also immer und überall
und nicht nur für bestimmte Datenstrukturen verwenden kann.Ich hab nur keine Ahnung, wie ich das bewerkstelligen soll.
-
Moment mal, zurück auf Anfang: Eine INI-Datei hat eine feste Struktur (einzelne Sektionen, darin jeweils die Werte als "Name=Wert" aufeglistet. Und für die interne Verarbeitung solltest du diese Aufteilung als Grundlage verwenden, um möglichst flexibel auf die Daten zugreifen zu können.
Nach außen (also an die Anwendung, die einen INI-Parser nutzen will) stellst du dann Funktionen zur Verfügung, um mit dem Sektions- und Variablennamen einen Wert auszulesen bzw. einzutragen. Was für Werte da letztendlich gebraucht werden, geht den Parser nichts mehr an (solange die Anwendung die Namen kennt).
-
Ja soweit passt das auch mit dem, was ich mir vorgestellt hatte.
Aber eine 'feste Struktur' ?du meinst sowas wie:
[Sektion 1] Wert1 = 1 Wert2 = 4 Wert3 = "Hallo" [Sektion 2] ...
-
Ja, genau das meinte ich - oder kennst du noch andere Formate für INI-Dateien? (und damit meine ich jetzt nicht XML und Konsorten)
-
Naja es gibt auch ini Dateien von diversen Spielen, die nicht so ein Muster vorweisen.
Und die möchte ich ggf. auch mit meinem Parser bearbeiten können. ( Ist aber eher ein optionaler zusatz. erstmal das grundlegende machen )
-
Pyro Phoenix schrieb:
Naja es gibt auch ini Dateien von diversen Spielen, die nicht so ein Muster vorweisen.
Und die möchte ich ggf. auch mit meinem Parser bearbeiten können. ( Ist aber eher ein optionaler zusatz. erstmal das grundlegende machen )Es gibt aber ein Standard für INI Files: http://en.wikipedia.org/wiki/INI_file
Wenn eine Datei diesem Muster nicht entspricht, dann ist es keine INI Datei (egal welche Endung die Datei hat).
-
Pyro Phoenix schrieb:
Naja es gibt auch ini Dateien von diversen Spielen, die nicht so ein Muster vorweisen.
Und die möchte ich ggf. auch mit meinem Parser bearbeiten können.möchtest du einen parser für standard-ini-dateien oder möchtest du einen pseudo-intelligenten parser schreiben, der verschiedene dateiformate automagisch unterstützt?
mein rat: versuch dich erst mal an standard-init-dateien, bevor du dir größere ziele steckst.
@net: dein dumpfes c++-gebashe wird langweilig, denk dir mal was neues aus.
-
du musst dir halt mal n paar ini files ansehen, oder wikipedia evtl.
dann wirst du schon sehen, was bei allen ini files gleich ist.
und das sind dann deine keywords für den parser.
das sage ich aber, während ich selber keine ahnung hab wie ini files aussehen, bzw. ob sie überhaupt einigermassen einheitlich sind.
aber genau diese einheitlichen begriffe, die immer wieder auftauchen, musst du vom parser scannen lassen.
je nach dem, was du da lesen/schreiben willst, baust du dir ne struktur in deinem programm, die alle attribute hat, die du in einer ini-datei für dich sinnvoll hälst.
-
ininini schrieb:
möchtest du einen parser für standard-ini-dateien oder möchtest du einen pseudo-intelligenten parser schreiben, der verschiedene dateiformate automagisch unterstützt?
mein rat: versuch dich erst mal an standard-init-dateien, bevor du dir größere ziele steckst.
Erstmal klein anfangen .. so hatte ich das geplant
hdi-loggedout schrieb:
je nach dem, was du da lesen/schreiben willst, baust du dir ne struktur in deinem programm, die alle attribute hat, die du in einer ini-datei für dich sinnvoll hälst.
Struktur? Bitte mal genauer erläutern.
Also es gibt die
;Kommentar [Sektion] ;Kommentar Schlüssel=Wert
Struktur.
Also ich dachte mir, das man per Funktion ( sektion, schlüssel ) den
entsprechenden Wert herausfinden kann.€dit:
Laut Wikipedia:
Bei dem Erstellen einer INI-Datei sind folgende Regeln zu beachten:
- Jede Sektion darf nur einmal vorkommen.
- Jeder Schlüssel darf nur einmal je Sektion vorkommen.
- Kommentare werden mit einem ";" eingeleitet.
- Auf Werte wird mittels Sektion und Schlüssel zugegriffen.
- Kommentare dürfen nicht direkt hinter einem Schlüssel stehen.
- Leerzeichen und Anführungszeichen werden von verschiedenen Programmen teilweise unterschiedlich behandelt.
-
Pyro Phoenix schrieb:
Struktur? Bitte mal genauer erläutern.
Also es gibt die
;Kommentar [Sektion] ;Kommentar Schlüssel=Wert
Struktur.
Also ich dachte mir, das man per Funktion ( sektion, schlüssel ) den
entsprechenden Wert herausfinden kann.Ja, davon rede ich die ganze Zeit. Diesen Aufbau mußt du auf sinnvolle Art in den RAM übertragen (den gesamten Dateiinhalt binär in den Speicher zu schreiben, ist i.a. nicht sinnvoll).
Eine Möglichkeit wäre es, Schlüssel-Einträge als Paar von Strings, Sektionen als Liste/Array/whatever von Schlüsseleinträgen (und evt. Kommentaren) und das gesamte INI-File als eine Liste/Array/whatever von Sektionen darzustellen.
-
Ich hab da ein kleines Problem:
error C2440: '=' : 'struct CIniParser::section *' kann nicht in 'struct section *' konvertiert werden
class CIniParser { private: typedef struct section * s_node; typedef struct key_value * kv_node; typedef struct section { char *sectionname; s_node next; s_node prev; kv_node first; kv_node last; }; typedef struct kev_value { char *key; char *value; kv_node next; kv_node prev; s_node member; }; int p_buffer; struct section *root; struct section *actv; struct section *prev; int getSection ( char *name ); int getTopic ( char *key, char *value ); public: CIniParser ( char *c_file ); ~CIniParser (); }; #endif
Bei:
prev->next = actv;
Ich bin grad zu verpeilt um selber rauszufinden worans liegt ...
-
"class", "private"? Bist du sicher, daß das immer noch C ist?
Ansonsten: Was soll ein typedef bringen, wenn du dem Typ dabei keinen Namen gibst?
-
Ich habs in ne class gepackt. Alles in einer Datei war mir zu unübersichtlich.
Naja hab das Problem jetz gelöst, indem ich die structs ausserhalb der Klasse
definiere.
-
Pyro Phoenix schrieb:
Ich habs in ne class gepackt. Alles in einer Datei war mir zu unübersichtlich.
Darauf wollte ich gar nicht hinaus - ich wollte dich nur darauf hinweisen, daß "class" in C nicht existiert. Und wenn du sowieso schon C++ verwendest, dann gleich richtig
-
Nächtes mal vielleicht ^^
Wie gesagt, man soll mit den grundlagen anfangen.Hab jetz aber ein anderes Problem, dessen Lösung mir nicht bekannt ist.
typedef struct key_value * kv_node; typedef struct section * s_node; struct section { char *sectionname; s_node next; s_node prev; kv_node first; kv_node last; }; struct kev_value { char *key; char *value; kv_node next; kv_node prev; s_node member; }; class CIniParser { private: struct section *root; struct section *actvs; struct section *prevs; struct key_value *actvkv; struct key_value *prevkv;
actvkv = new key_value;
ergibt:
error C2512: 'key_value' : Kein geeigneter Standardkonstruktor verfuegbar
wobei jedoch:
actvs = new section;
keine probleme verursacht.
-
Pyro Phoenix schrieb:
actvkv = new key_value;
ergibt:
error C2512: 'key_value' : Kein geeigneter Standardkonstruktor verfuegbar
nimm 'malloc' für structs.
-
Womit wir bei einer bunten Mischung aus C- und C++ Code wären - sowas ist weder besonders gut wartbar noch wirklich praktikabel. Entweder du nutzt reinen C++ Code oder reines C, aber bitte entscheide dich.
-
actvkv = (key_value *)malloc ( sizeof( key_value ) );
ergibt:
error C2027: Verwendung des undefinierten Typs "key_value" Siehe Deklaration von 'key_value'
-
Du musst halt auch lesen, was CStoll zu deinen typedefs sagt. Probiers mit:
actvkv = (struct key_value *)malloc ( sizeof( struct key_value ) );
Allerdings ist die malloc-Vergipsung schon wieder so eine Hybridformulierung. Das einzige, was dafür spricht, ist daß es in C und C++ so läuft. In C99 sollte man das ohne Cast machen, in C++ mit static Casts. Kann dir egal sein, aber ich weise darauf hin.