Configuration file input/output

Pages: 12
Hello! I looked through the documentation on file input/output but I need a little bit more light shed on this situation. How would I go about configuration file (.ini files) input/output?
first read a line with cin.getline (or std::getline) then find '=' in it and do whatever you want to do with each half. (or use sume library to do the job for you)
Okay. Well while digging through information I found this:

http://www.cplusplus.com/forum/general/21115/

Its a little bit difficult for me in my n00bness to understand, could someone elaborate further on it?
Once again, Standard C++ fail to provide us a good library for this. If it is only strictly <name>=<value> it will be easy but what if it goes beyond that. Then someone told me Boost::RegEx will be the library we should go for.

For XML parsing, there is a C++ parser at http://projects.apache.org/projects/xerces_c++_xml_parser.html

It seems to be quite active with latest release dated 21 Apr 2010.
If he is using windows - windows have built system functions for getting vaules from *.ini
files.
The functions have names like GetProfileString or something similar.
Once again, Standard C++ fail to provide us a good library for this. If it is only strictly <name>=<value> it will be easy...

That is what I am going for, I just need the parser that I found explained a bit more to me so that I can get a good understanding of it.

Here it is again: http://www.cplusplus.com/forum/general/21115/

Here I'll post some of the sections I am having trouble understanding.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <map>
#include <string>

namespace configuration
  {
....
    struct data: std::map <std::string, std::string>
    {
    // Here is a little convenience method...
    bool iskey( const std::string& s ) const
      {
      return count( s ) != 0;
      }
    };
....

Okay here for example, where the code says "<std::string, std::string>" am I supposed to replace "string" with the information I need from the .ini file?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
....
// Skip blank lines
      if (begin == std::string::npos) continue;

      // Skip commentary
      if (std::string( "#;" ).find( s[ begin ] ) != std::string::npos) continue;

      // Extract the key value
      std::string::size_type end = s.find( '=', begin );
      key = s.substr( begin, end - begin );

      // (No leading or trailing whitespace allowed)
      key.erase( key.find_last_not_of( " \f\t\v" ) + 1 );

      // No blank keys allowed
      if (key.empty()) continue;
....

And here, where it says "if (std::string( "#;" ).find( s[ begin ] ) != std::string::npos)" am I supposed to replace "#;" with the name of the slot? and the "s[ begin ]" with the name of the section? Like

 
if (std::string::( "name" ).find( s[ stats ] ) != std::string::npos) continue;

Here is the .ini file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[stats]
Name=Player
HP1=100
HP2=100
MP1=100
MP2=100
EXP1=0
EXP2=500
STR=1
DEF=1
MDEF=1
ATK=1
MAG=1
EVA=1


I know I'm a n00b at this >.< I just need a little bit of explanation on this particular parser. I also guess I should tell you what I am doing to help you help me. Its a text based console RPG game, and the .ini file holds the players stats (among other things, but haven't gone that far yet.)
Last edited on
If it is to be installed on a Windows machine, I would suggest take guestgulkan solution and call Windows API direct.

If you want it to be generic and not tied to any platform specific API, I would recommend you take a look at Boost::RegEx library. The reason being a Regular Expression parser would scale well in future if you decide to change your config file format again.

At this current times, most config files have changed to XML format. It seems you are still using the old Windows specific INI file format. If it is a new text based console RPG game, it is a good opportunity to change from INI to XML format IMHO.

Then you can use a C++ XML Parser to help you parse the XML-based config file.

Last edited on
Well I'll look at it, but I don't know much about XML >.>

This isn't my first programming language (mSL was fist), its just this particular issue is really eating at me, its starting to get frustrating.

I wanted to use the original ini format because its what I understood and like to use. I use that ini format in all of my mSL projects as well.
Last edited on
w3schools XML to get a tutorial. Below snippet give you some idea on what XML is about. It should be self-explanatory.

<?xml version="1.0" encoding="UTF-8"?>
<Players>
<Player>
<Name>abc</Name>
<HP1>100</HP1>
<HP2>100</HP2>
...
</Player>

<Player>
<Name>def</Name>
<HP1>200</HP1>
<HP2>200</HP2>
...
</Player>

...
</Players>
Oh... That's ridiculously easy to understand.

So, for example, I could take the above snippet you posted and put into a .ini file and use GetProfileString to retreive the information?

Will a header file still be necessary? Parser?

Sorry for so many questions, my mentor/instructor disappeared a few days ago and hasn't returned so I'm taking the sink or swim approach :\
So, for example, I could take the above snippet you posted and put into a .ini file and use GetProfileString to retreive the information?


Definitely not. INI format is based on <name>=<value> so if you use Windows GetProfileString API, you of cuz cannot retrieve those config information based on XML format.

You need to decide

1. Will the program be installed on Windows machine ?

2. Do you want a platform independent config file format ?

Then based on your decision you can choose to use Windows API or use a C++ XML parser (assume you choose XML as config file format)

1. Yes windows machine

2. Yes I want a platform independent configuration file format

Then based on your decision you can choose to use Windows API or use a C++ XML parser (assume you choose XML as config file format)


Which would be the better choice?
2. Yes I want a platform independent configuration file format


Actually INI format can also be applied in Unix also as it is just plain text. To save you time you just use Windows API since you intend to install your program inside Windows machine.

Just note your program will then not run in Unix since the API does not exist in Unix.
Okay, If I wanted it to be unix compatible as well what would I use?

Examples of API?

*pops up google too*
Okay, If I wanted it to be unix compatible as well what would I use?


Then you cannot use Windows API.

Do you only want INI file format in Windows and Unix ? If yes, then I think get Boost::RegEx library and explore.

OR you can just write your own function if it is strictly <name>=<value>.
It is going to be strictly <name>=<value>

writing my own function sounds like a good way to take... Although I wouldn't know where to start with that either :\

*le sigh*
1
2
3
4
5
6
7
8
9
10
11
12

int main() {
  ifstream ifs("test.ini",fstream::in);
  string str; size_t found;
  while (ifs >> str) {
    found=str.find('=');
    if (found!=string::npos) {
      cout << str.substr(0,found) << " " << str.substr(found+1) << "\n";
    }
  }
  ifs.close();
}
O_O

I was reading a tutorial earlier that explained that. *reopens tutorial*

Thanks a lot. :)
Oh one more thing

Instead of

1
2
3
if (found!=string:npos) {
  cout << str.substr(0,found) << " " << str.substr(found+1) << "\n";
}


Can I implement it to a variable like this?
1
2
3
4
int a
if (found!=string:npos) {
  a = str.substr(0,found) << " " << str.substr(found+1);
}


I'm not sure if I got the syntax right, but now that I have a piece of code that I can actually work with, I will have it figured out. I learn better with a hands on approach from an example anyways.

Thanks again :D
<< is an operator overloaded for use with cout object. Do you mean you want to store the chopped string into variables is it ?

Then simple.

1
2
3
4
5
string a; string b;
if (found!=string:npos) {
  a = str.substr(0,found);
  b = str.substr(found+1);
}
Pages: 12