Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Fawkes

Frischling

  • »Fawkes« ist der Autor dieses Themas

Beiträge: 58

Beruf: Realschüler :)

  • Private Nachricht senden

1

16.06.2013, 13:06

Inireader

Hallo, ich erstelle diesen Thread nur, da ich denke das einige Anfänger ( so wie ich ) bestimmt mal das Problem hatten einen Inireader zu schreiben. Ich habe lange dannach im Internet gesucht aber nichts Plattformunabhängiges gefunden. Deshalb habe ich mir selber eine Klasse dafür geschrieben, leider ist die Form der Ini etwas anders als man es gewohnt ist. Bei meinem Inireader muss man einen Tag und einen Closing Tag angeben:

[code]

[Schurke] <- Tag
Str=12
Dex=17
Int=4
[/Schurke] <- closing Tag

[Krieger]
Str=18
Dex=10
Int=2
[/Krieger]

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <string>
#include <iostream>
#include <fstream>
#include <iterator>


class IniReader{

public:

    static int getIntager( std::string path, std::string Category, std::string keyword, int defvalue){

    std::fstream stream(path, std::ios_base::in); // File öffnen
    stream << std::noskipws; // Keine Enter überspringen
 
    if(stream.bad())
        throw std::runtime_error("Error when opening file: " + path + "."); // Wenn die Datei nicht vorhanden oder beschädigt ist: error

    std::istream_iterator<char> begin(stream), end_of_file; //
                                                            //  Datei Inhalt in einen String packen
    std::string buffer(begin, end_of_file);                 //
    stream.close();

    size_t categoryPos1 = buffer.find( "[" + Category + "]" );  // Position vom Tag rausfinden
    size_t categoryPos2 = buffer.find( "[/" + Category + "]" ); // Position vom Closing Tag rausfinden

    size_t len = categoryPos2 - categoryPos1;                   // Länge zwischen Tag und Closing Tag rausfinden

    std::string subCategory = buffer.substr( categoryPos1, len );   // Einen Substring anlegen  da kommt alles rein was zwischen dem Tag und dem Closing Tag steht!

    size_t keywordPos = 0;  // Die position des keywords

    if( ( keywordPos = subCategory.find( keyword ) ) != std::string::npos ){ // keyword finden

            std::string value = subCategory.substr( keywordPos - 1 ); // davon einen neuen string erstellen ( Nur die Zeile in der das keyword drin steht ist jetzt in value vorhanden )

            size_t valuepos = value.find( "=" ); // Nur den Wert hinter dem '=' rausfinden

            std::string THEVALUE = value.substr( valuepos + 1); // Den wert in THEVALUE schreiben

            int toInt = atoi( THEVALUE.c_str() ); // umwandeln

            return toInt; // zurückgeben
        }

    return defvalue; // Wenn das obere nicht funktioniert hat wird ein defaultwert zurück gegeben welchen man selber aussuchen darf
}

    static std::string getString( std::string path, std::string Category, std::string keyword, std::string defvalue){

    std::fstream stream(path, std::ios_base::in);
    stream << std::noskipws;
 
    if(stream.bad())
        throw std::runtime_error("Error when opening file: " + path + ".");

    std::istream_iterator<char> begin(stream), end_of_file;
    std::string buffer(begin, end_of_file);
    stream.close();

    size_t categoryPos1 = buffer.find( "[" + Category + "]" );
    size_t categoryPos2 = buffer.find( "[/" + Category + "]" );

    size_t len = categoryPos2 - categoryPos1;

    std::string subCategory = buffer.substr( categoryPos1, len );

    size_t keywordPos = 0;

    if( ( keywordPos = subCategory.find( keyword ) ) != std::string::npos ){

            std::string value = subCategory.substr( keywordPos - 1 );

            size_t valuepos = value.find( "=" );

            std::string THEVALUE = value.substr( valuepos + 1);

            return THEVALUE;
        }

    return defvalue;
}

    static bool getBool( std::string path, std::string Category, std::string keyword, bool defvalue){

    std::fstream stream(path, std::ios_base::in);
    stream << std::noskipws;
 
    if(stream.bad())
        throw std::runtime_error("Error when opening file: " + path + ".");

    std::istream_iterator<char> begin(stream), end_of_file;
    std::string buffer(begin, end_of_file);
    stream.close();

    size_t categoryPos1 = buffer.find( "[" + Category + "]" );
    size_t categoryPos2 = buffer.find( "[/" + Category + "]" );

    size_t len = categoryPos2 - categoryPos1;

    std::string subCategory = buffer.substr( categoryPos1, len );

    size_t keywordPos = 0;

    if( ( keywordPos = subCategory.find( keyword ) ) != std::string::npos ){

            std::string value = subCategory.substr( keywordPos - 1 );

            size_t valuepos = value.find( "=" );

            std::string THEVALUE = value.substr( valuepos + 1);

            int toInt = atoi( THEVALUE.c_str() );

            bool Result = 0;

            if( toInt < 0 || toInt > 1 )
                return defvalue;
            else
                Result = toInt;

            return Result;
        }

    return defvalue;
}
};


Ich hoffe manche anfänger verstehen das. Nicht vergessen ich habe es nur hier hin gepostet damit man auf Google auch was zum Inireading findet.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Fawkes« (19.06.2013, 21:42)


FSA

Community-Fossil

  • Private Nachricht senden

2

16.06.2013, 13:49

Warum dann nicht gleich xml?
<bla></bla>

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

3

16.06.2013, 14:09

Warum dann nicht gleich xml?
<bla></bla>

Ich bevorzuge meistens auch ini Dateien.
Sie haben, verglichen mit XML Dateien, wesentlich weniger overhead und sind daher auch schneller und vor allem leichter zu parsen.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Databyte

Alter Hase

Beiträge: 1 040

Wohnort: Na zu Hause

Beruf: Student (KIT)

  • Private Nachricht senden

4

16.06.2013, 14:17

Hmm, wenn es funktioniert ist es doch ok :)

Allerdings frage ich mich wieso getInteger und getBool nicht auf getString aufbauen... du öffnest und "parsed" die datei jetzt in jeder der drei funktionen... dabei ist der einzige unterschied, dass sie den string den sie extrahieren unterschiedlich behandeln...
Das problem mit dem closing-tag könntest du lösen indem du mit std::getline einfach jede zeile durchgehst und erst nach dem tag suchst ([...]) und dann nach dem key (... = ....).
Ganz abgesehen davon, sollte es in deinem code zu fehlern kommen, wenn das format eben falsch ist (kein closing-zag existiert)!!!


Weiterhin, brauchst du gar nicht substr benutzen, denn du kannst dem find einen iterator übergeben, ab dem er dann anfängt zu suchen.
Schön wäre es natürlich auch, wenn du beim konvertieren anstatt atoi und so, std:istringstream verwendest. Dann kannst du auch in alle möglichen typen konvertieren. das sehe dann mit einer getString methode so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template<typename _Ty>
static _Ty get(const std::string& path, const std::string& Category, const std::string& keyword, const _Ty& defvalue)
{
  std::string value = getString(path, Category, keyword); // erst holen wir uns den einen string mit dem int oder bool oder so
  std::istringstream iss(value);

  _Ty extr; // <- hier wird hinextrahiert
  
  iss >> extr; // <- extrahiere

  if(!iss.fail()) // <- prüfe ob ein fehler aufgetreten ist
    return extr;
  else
    return defvalue;
}

...
// Benutze es mit:
int window_width = IniReader::get("config.ini", "graphics", "width", 800);

Databyte

Alter Hase

Beiträge: 1 040

Wohnort: Na zu Hause

Beruf: Student (KIT)

  • Private Nachricht senden

5

16.06.2013, 14:20

Ich bevorzuge meistens auch ini Dateien.
Sie haben, verglichen mit XML Dateien, wesentlich weniger overhead und sind daher auch schneller und vor allem leichter zu parsen.


Benutze rapidxml und dann kannst du Geschwindigkeitsvorteile vergessen... rapidxml ist so gut optimiert, das selbst ein inireader nur vernachlässigbar schneller sein wird (wenn überhaupt),
denn ini datein sind meistens so wie so nicht so groß...

Fawkes

Frischling

  • »Fawkes« ist der Autor dieses Themas

Beiträge: 58

Beruf: Realschüler :)

  • Private Nachricht senden

6

16.06.2013, 14:21

Hmm, wenn es funktioniert ist es doch ok :)

Allerdings frage ich mich wieso getInteger und getBool nicht auf getString aufbauen... du öffnest und "parsed" die datei jetzt in jeder der drei funktionen... dabei ist der einzige unterschied, dass sie den string den sie extrahieren unterschiedlich behandeln...
Das problem mit dem closing-tag könntest du lösen indem du mit std::getline einfach jede zeile durchgehst und erst nach dem tag suchst ([...]) und dann nach dem key (... = ....).
Ganz abgesehen davon, sollte es in deinem code zu fehlern kommen, wenn das format eben falsch ist (kein closing-zag existiert)!!!


Weiterhin, brauchst du gar nicht substr benutzen, denn du kannst dem find einen iterator übergeben, ab dem er dann anfängt zu suchen.
Schön wäre es natürlich auch, wenn du beim konvertieren anstatt atoi und so, std:istringstream verwendest. Dann kannst du auch in alle möglichen typen konvertieren. das sehe dann mit einer getString methode so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template
static _Ty get(const std::string& path, const std::string& Category, const std::string& keyword, const _Ty& defvalue)
{
  std::string value = getString(path, Category, keyword); // erst holen wir uns den einen string mit dem int oder bool oder so
  std::istringstream iss(value);

  _Ty extr; // <- hier wird hinextrahiert
  
  iss >> extr; // <- extrahiere

  if(!iss.fail()) // <- prüfe ob ein fehler aufgetreten ist
    return extr;
  else
    return defvalue;
}

...
// Benutze es mit:
int window_width = IniReader::get("config.ini", "graphics", "width", 800);


Die Methode ist gut ich überarbeite das eben. :)

Edit: Oder auch nicht hehe, ich weiß leider nicht wie ich das überarbeiten soll. Aber wenn jemand hier den Code überarbeiten will, gerne. Mir geht es sowieso nur darum, dass man in google mal etwas aktuelles zum Thema Inireader findet. Als ich einen brauchte habe ich lange gesucht aber nichts gefunden. Zumindest nichts Plattformunabhängiges und akutuelles.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

7

16.06.2013, 17:19

Nur um es in den Raum zu werfen. JSon ist auch eine sehr gute Alternative. Aber ob jetzt Ini, XML oder JSon ist größtenteils Geschmackssache.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

8

16.06.2013, 17:27

Ich bevorzuge meistens auch ini Dateien.
Sie haben, verglichen mit XML Dateien, wesentlich weniger overhead und sind daher auch schneller und vor allem leichter zu parsen.


Benutze rapidxml und dann kannst du Geschwindigkeitsvorteile vergessen... rapidxml ist so gut optimiert, das selbst ein inireader nur vernachlässigbar schneller sein wird (wenn überhaupt),
denn ini datein sind meistens so wie so nicht so groß...

Gut, das mag stimmen. Aber wenn's um das selber bauen geht, würde ich immer auf ini setzen. :)
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Evrey

Treue Seele

Beiträge: 245

Beruf: Weltherrscher

  • Private Nachricht senden

9

16.06.2013, 17:27

XML D: Oh, Gott, dieses mit nutzlosen Zeichen vollgestopfte Format. Boost bietet mit seinem "property_tree" die Möglichkeit, Daten als Baumstruktur zu (de-)serialisieren und unterstützt dabei auch die Formate XML, JSON, INI, und "Info", wobei "Info" ein minimalistischer Selbstbau ist, der syntaktisch JSON/YAML ähnelt.

C-/C++-Quelltext

1
2
3
4
int main(int _argc, char** _argv) noexcept {
  asm volatile("lock cmpxchg8b %eax");
  return 0;
} // ::main
(Dieses kleine Biest vermochte einst x86-Prozessoren lahm zu legen.)

=> Und er blogt unter Hackish.Codes D:

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

10

16.06.2013, 17:33

XML D: Oh, Gott, dieses mit nutzlosen Zeichen vollgestopfte Format. Boost bietet mit seinem "property_tree" die Möglichkeit, Daten als Baumstruktur zu (de-)serialisieren und unterstützt dabei auch die Formate XML, JSON, INI, und "Info", wobei "Info" ein minimalistischer Selbstbau ist, der syntaktisch JSON/YAML ähnelt.

Ich dachte doch wirklich kurz, dass du XML und die Sprache D irgendwie in Verbindung bringst. Ich hasse umgedrehte Smileys. :D
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Werbeanzeige