[c++] Wie einen 'Ini-Ausleser' Programmieren

Sircoly

Mitglied
Halli Hallo,

ich möchte so einer Art '.ini-Dateien ausleser' machen.
Ein Beispiel:
(Init.ini)
Code:
// Dies ist ein Kommentar
$a = "Dies ist eine Variable"

Und mein Code soll dann alle Zeilen, bei denen AM ANFANG ein '//' steht, nichts tuen.
Halt als Kommentar abstempeln.
Wenn AM ANFANG der Zeile ein '$' steht, soll der Inhalt der Variable ausgelesen werden.
sowas wie:
char array[100] = $a

Habt ihr eine Idee, wie ich das realisieren kann?
Vielleicht jede Zeile in einen Array einlesen lassen und dann das 1. Zeichen(kein Blank oder TAB) kontrollieren lassen?
Aber wie erkenne ich dann bei "meinen" Variablen(also die mit dem $), welche Variable es ist? - Weil ich z.B. $pfad1 und $pfad2 auswählen soll.
 
Kommt ganz darauf an, mit welchem Framework du arbeitest. Die VCL kennt die TIniFile-Klasse, die MFC müsste etwas vergleichbares haben, da du allerdings direkt im C/C++-Forum postest, wird es wohl etwas kniffliger.

Die grundlegende Vorgehensweise:
- Ini-Datei zum Lesen öffnen (Filehandle etc.)
- Inizeile in char[] einlesen
- Inizeile trimmen.
- if(zeile[0] == '$') {
- Zeile beim '=' splitten, grob gesagt:
Key = substr(zeile, 0, PositionDes'=' - 1);
Value = substr(zeile, PositionDes '=' + 1, length(zeile) - PositionDes'=' - 1);
- Key und Value irgendwohin packen, wo du sie haben willst
- }
- fertig.
 
Halli Hallo,

also muss ich jede Zeile erstmal einlesen und in einem Array speichern.
Dann die Zeilen einzeln nach dem '$'-Operator durchsuchen und dann die Zeile speichern.
Dann die Zeile bei dem '='-Operator trennen und den Wert, der Danach kommt in einer Variable speichern.

Kannst du mir GENAU diesen schritt nochmal verdeutlichen?
Also das, was nach dem = kommt, wie ich das speichern kann.
 
Autsch. Erwischt. Da wären wir schon wieder beim Thema "dynamische Arrays" in Standard C++.

Also ich ganz persönlich würde es noch ein bißchen anders angehen. Ich würde mir eine Funktion basteln, die ich mit entsprechenden Ini-Sektionen aufrufen kann, und die mir dann den passenden Wert zurückliefert.

Etwas in der Art:

void read_ini_value(char* Filename, char* Key, char* Value) {
- Ini-Datei zum Lesen öffnen (Filehandle etc.)
- Inizeile in char[] einlesen
- Inizeile trimmen.
- if(zeile[0] == '$') {
- Zeile beim '=' splitten, grob gesagt:
tempKey = substr(zeile, 0, PositionDes'=' - 1);
if(strcmp(tempKey, Key) == 0) Value = substr(zeile, PositionDes '=' + 1, length(zeile) - PositionDes'=' - 1);
- Datei schließen und freigeben
}

Dann könntest du die Werte gemütlich auslesen:

char* Value;
char* Filename = "wasweissich.ini";
char* Key = "test";

read_ini_file(Filename, Key, Value);

Mal so in die Tüte gesprochen. :)
 
Halli Hallo,

vielen dank! - Du hast mir echt weitergeholfen.
Ja, ich wollte mir auch eine Funktion schreiben, bei der ich einfach den Namen der Variable eingebe,
und er mir dann den Wert zurückgibt.

Hier mal mein Anfang:
C++:
bool __cParse::ReadVar(char * ext_cTarget, char * ext_cVarName, char * &ext_cVarContent)
{
     /***** Deklaration *****/
	bool sm_bNoError;														    // Variablendeklaration für Befehl

	/***** Definition *****/
	sm_bNoError = false;

	/***** Aktion *****/
    ifstream sm_fFileOpen( ext_cTarget );                                       // Offnen der Datei

    if(sm_fFileOpen.is_open())                                                  // Wenn die Datei erfolgreich geöffnet werden konnte
    {
        DEBUG_OUTPUT("Datei erfolgreich geoeffnet");                                // DEBUG: Ausgaben
        sm_bNoError = true;                                                         // Fehler melden
    }
    else                                                                        // Ansonsten
    {
        DEBUG_OUTPUT("Fehler beim oeffnen der Datei");                              // DEBUG: Ausgabe
        sm_bNoError = false;                                                        // keinen Fehler melden
    }


    /***** Termination *****/
	return sm_bNoError;														    // Funktion Terminieren
}

Nur weiter weiß ich momentan nicht.
Mir fällt grade nicht der Befehl dazu ein, wie ich die Datei einlesen kann.
Oder wie hast du das gemeint? - Kannst du mir vielleicht ein "MINI-Beispiel" zeigen?

oder hat sonst jemand eine Idee, wie ich das Bewerkstelligen kann?
 
Zuletzt bearbeitet von einem Moderator:
Vieleicht hilft dir die Klasse im Anhang weiter. Dies iIst eine kleine Klasse um
configurations Dateien zu lesen. Ob du dir Code kopierst oder nicht ist deine Sache.
Aber du wählst hoffentlich die sinnvollere Variante ;)

Folgendes tut die Klasse:
1. Beim laden einer datei werden alle Zeilen die nicht mit "#" anfangen an einen
Vector angehängt. config::load(std::string filename)

2. Mit config::getValue(std::string data) bekommst du einen Wert nach dem "="
Zeichen zurück:
Nehmen wir an du hast die Zeilen
Code:
config1=1
config2=1
und rufst getValue("config1");, bekommst du den Wert von "config1" nach dem "="
Zeichen. (getValue liefert immer std::string zurück)

Wenn du einen Wrapper für die config Klasse schreiben würdest könntest du im
Wrapper member deklarieren und diese im Konstruktor des Wrapper direkt mit den
Konfigurationswerten füllen.
 

Anhänge

Halli Hallo,

danke für die Klasse(n). Haben mir sehr geholfen!

Wenns erlaub ist, werde ich die erstmal benutzen.
Versuche aber dann später meine eigene Klasse zu schreiben. Kannst du mir ein wenig
darüber erzählen, wie du das hinbekommen hast? - Stichwörter oder so?
Oder vielleicht eine Beschreibung? - Würde mich mal interessieren.
 
Gemacht habe ich es folgendermaßen:
1. Member std::vector<std::string> deklariert.


2. Methode bool load(std::string fileName):
Öffnet angegebene Datei zum lesen und liefert false zurück falls dies fehlschlägt:
C++:
configStream.open(fileName.c_str());
 
if (!configStream.is_open())
    return false;

Nun Zeile für Zeile einlesen und falls die aktuelle Zeile nicht mit "#" anfäng an den
vector anhängen:
C++:
while (getline(configStream, configRow))
{
    if (!extraType.strStartsWith(configRow, "#"))
        configRows.push_back(configRow);
}


3. Methode std::string getType(std:string configRow) (eigentlich unnütz da ich in
getValue diese einfch mit extraType.strStartsWith(configRow, data) ersetzen könnte, dann
wüsste ich ja schon ob die gerade durchgegangene zeile der config zeile entspricht
die ich haben will). Hatte ich wohl implementiert bevor ich mir die Klasse extraTypes geschrieben hatte.


4. Methode std::string getValue(std::string data)
Hm... Startet eine Zählschleife, die Anzahl der Durchläufe entspricht der Anzahl der
Konfigurations Zeilen, wenn nicht vorher der Wert data dem Rückgabewert von
getType(configRow) entspricht.
Wie gesagt ersetze mal
C++:
if (getType(configRow) == data))
mit
C++:
if (extraType.strStartsWith(configRow, data))
Wenn extraType.strStartsWith(configRow, data) in keinem fall wahr ist wird einfach
ein lehrer string zurück gegeben.


5. Methode std::vector<std::string> getVCR()
Gibt dir den Vektor mit den beinhalteten Kongigurationszeilen zurück.


6. Methode void clear()
Genauso bullshit wie getType() auch wenn ich nur wüste was ich da machen wollte :D



Du solltest dir außerdem alle Methoden der Klasse extraTypes angucken die in
den Implementirerungen der classe config aufgerufen werden(extraType.xxx())


Mit freundlichen grüßen,
FBIagent
 
Zurück