[Projektgestaltung] .ini Parser
-
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.
-
Ergibt selbes Problem.
error C2027: Verwendung des undefinierten Typs "key_value" Siehe Deklaration von 'key_value'
-
Auch auf die Gefahr hin, mich zu wiederholen: bitte verwende keinen Sprachen-Mischmasch.
(ansonsten solltest du mal etwas zusammenhängenderen Code vorführen, um das Problem zu erläutern - solche Probleme wie "Verwendung des undefinierten Typs ..." entstehen meist, weil nur eine Forward Deklaration dort steht, wo der Compiler eine vollständige Definition benötigt.
-
Sry. Ich dachte, das sei eher unproblematisch C und C++ zu vermischen.
parser.h
#ifndef INIPARSER_H #define INIPARSER_H 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; int getSection ( char *name ); int getTopic ( char *key, char *value ); public: CIniParser ( char *c_file ); ~CIniParser (); }; #endif
parser.cpp
#include <stdio.h> #include <malloc.h> #include "../tools/tools.h" // für sizeOfFile (); #include "parser.h" CIniParser::CIniParser ( char *c_file ) { root = NULL; actvs = NULL; actvkv = NULL; FILE *p_iniFile = NULL; // actvkv = new key_value; if ( ( p_iniFile = fopen ( c_file, "r" ) ) == NULL ) { this.~CIniParser (); } /* actvs = root; do { printf ( "%s\n", actvs->sectionname ); actvs = actvs->next; } while ( actvs != NULL ); getchar();*/ }; CIniParser::~CIniParser () { }; CIniParser::getSection ( char *name ) { if ( root == NULL ) { root = (section *)malloc ( sizeof( section ) ); actvs = root; root->first = NULL; root->last = NULL; root->next = NULL; root->prev = NULL; root->sectionname = name; return 0; } else { prevs = actvs; actvs = (section *)malloc ( sizeof( section ) ); prevs->next = actvs; actvs->first = NULL; actvs->last = NULL; actvs->next = NULL; actvs->prev = prevs; actvs->sectionname = name; return 0; } return 1; }; CIniParser::getTopic ( char *key, char *value ) { if ( root->first == NULL ) { actvkv = (key_value *)malloc ( sizeof( struct key_value ) ); return 0; } else { return 0; } return 1; };