• Welcome to Valhalla Legends Archive.
 

[C++] INI file functions

Started by TruffleShuffle, May 12, 2003, 08:40 AM

Previous topic - Next topic

TruffleShuffle

Hey, I've been trying to make a function that will retrieve a line from a config. I've got the concept down, but I get an error.


void Get( char parameter[255], char &result )
{
   char text[255] = "";
   char returned[255];
   ifstream config_file;   // Create an in file instance

   config_file.open( "settings.ini", ios::in );   // Open the settings file
   if(config_file)
   {
      while( !config_file.eof() )
      {
         config_file >> text;
         if(!strnicmp( text, parameter, strlen(parameter)) )
         {
            strcpy( returned, (text + strlen(parameter)) );
         }
      }
   }
   else
   {
      cout << "File not found.\n";
   }
   config_file.close();
   strcpy(&result, returned);
}

int main()
{
   char username[255];
   char password[255];

   Get("username=", username);
   Get("password=", password);
   return 0;
}


The error is:
error C2664: 'Get' : cannot convert parameter 2 from 'char (*)[255]' to 'char &'
       A reference that is not to 'const' cannot be bound to a non-lvalue

Any ideas? I dunno why its not passing by reference.

K

char &c
means c is a reference to one character.
try char *c.

tA-Kane

#2
Quote from: TruffleShuffle on May 12, 2003, 08:40 AMvoid Get( char parameter[255], char &result)
Use char *result, instead.

Quote from: TruffleShuffle on May 12, 2003, 08:40 AMstrcpy(&result, returned);
For returned, point the address to the first character in the array. Also, for result, since the address of result was already passed, you don't need to pass the address again (doing so would be passing a double-pointer... a pointer to a pointer to the actual value, which I don't beleive is what you want), like this:
strcpy(result,&returned[0]);
Macintosh programmer and enthusiast.
Battle.net Bot Programming: http://www.bash.org/?240059
I can write programs. Can you right them?

http://www.clan-mac.com
http://www.eve-online.com

Eibro

while( !config_file.eof() )
{
   config_file >> text;
   if(!strnicmp( text, parameter, strlen(parameter)) )
   {
      strcpy( returned, (text + strlen(parameter)) );
   }
}
You're going to read past the end of the file when testing for EOF in this manner. Use something like:

while (config_file >> text) // Work with text
See here for more information: http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5
Eibro of Yeti Lovers.

Camel

Quote from: Maddox on May 12, 2003, 06:19 PM
Why don't you use GetPrivateProfileString() ?

apparantly, "real men" don't take "shortcuts."
whatever.

l)ragon

#5
Globals

char            Username[128];
char            Password[128];
char            Server[128];
char            HomeChannel[128];


your get function

void Get(char *username, char *password, char *server, char *homechan)
{
   FILE *fstream = fopen("yay.cfg", "r");
   char buffer[1024] = "";
      if(fstream)
         {
            while(fgets(buffer, sizeof(buffer), stream))
            {
               strtok(buffer, "\r\n");
               if(!strnicmp(buffer, "username=", 9))
                  strcpy(username, buffer + 9);
               if(!strnicmp(buffer, "password=", 9))
                  strcpy(password, buffer + 9);
               if(!strnicmp(buffer, "server=", 7))
                  strcpy(server, buffer + 7);
               if(!strnicmp(buffer, "homechannel=", 12))
                  strcpy(homechan, buffer + 12);
            }
         }
      fclose(fstream);
}


How to use

             Get(Username,
                  Password,
                  Server,
                  HomeChannel);


dont like it you'll get over it
*^~·.,¸¸,.·´¯`·.,¸¸,.-·~^*ˆ¨¯¯¨ˆ*^~·.,l)ragon,.-·~^*ˆ¨¯¯¨ˆ*^~·.,¸¸,.·´¯`·.,¸¸,.-·~^*

Eibro

Perhaps a more robust solution:
#include <map>
#include <fstream>
#include <string>

using namespace std;

bool LoadConfig(const string& file, map<string, string>& vars)
{
   ifstream fin(file.c_str());
   string iniEntry;

   if (!fin.is_open())
      return false;
   
   while (getline(fin, iniEntry))
   {
      if (iniEntry[0] == '[' || iniEntry[0] == ';' || iniEntry.size() <= 1)
         continue;
      
      string::size_type split = iniEntry.find('=');
      if (split == string::npos)
         continue;

      string variable(iniEntry.begin(), split);
      string value(iniEntry.begin() + split + 1, iniEntry.end());

      while (*(variable.end() - 1) == ' ')
         variable.erase(variable.end() - 1);

      while (*value.begin() == ' ')
         value.erase(value.begin());

       vars[variable] = value;
   }
   return true;
}
Now I don't know if that works 100%, I didn't test it :)
Eibro of Yeti Lovers.

Kp

Quote from: Maddox on May 12, 2003, 06:19 PMWhy don't you use GetPrivateProfileString() ?
That only exists under Windows.  As written, the other versions of the code posted should work anywhere with an iostream library. :)
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

Kp

Quote from: Maddox on May 15, 2003, 01:01 AMTrue, but aren't ini configs created for and used mostly on windows?
Though tradition alone is rarely a good reason to keep up with anything.  Most Unix users tend to shy away from INI files in favor of more cryptic .conf files (in my experience), but INI files are still perfectly valid there.  Besides, learning how to load a config file is good practice working with reading/parsing files (for new programmers -- for veterans it'd just be an annoying subitem that must be completed before the fun stuff starts).
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

OriOn

If ur programm is under windiows, try to put ur config data in the registry.
It is easier to read/write than a .ini file.

MrRaza

Quote from: OriOn on May 17, 2003, 01:35 PM
If ur programm is under windiows, try to put ur config data in the registry.
It is easier to read/write than a .ini file.


I disagree. I found INI files much easier(in VB) to manipulate than the system registry. I only had to use 5 windows API functions for accessing private INI files, compared to the 25 Windows API system registry functions, although in my solution it really didnt call for use of the registry.

Grok

Quote from: OriOn on May 17, 2003, 01:35 PM
If ur programm is under windiows, try to put ur config data in the registry.
It is easier to read/write than a .ini file.

There are umpteen zillion reasons why using the registry for important information sucks.  Mainly is the registry is as stable as Microsoft Windows itself, and once any part of the registry is corrupt, you can kiss the whole thing goodbye.

INI files have the overhead of managing their physical location, (registry is always THE registry) and you can mindlessly and easily back up a copy of an INI file.  To do the same in a registry you might have to export 10-20 different sections to a .reg file, before backing up to some media.

INI files make it simple to have a test and production version of a program's settings.  In test mode?  Just replace the INI.

OriOn

You only need 5 api to do ur works. I use the registry for many years and i have no problem with it. It's more flexible and easiest than an .ini file. I don t see why you speak about the "legendary" stability of the microsoft os, this argument has no value ( Flame ??) . Backup ur data isn't a problem too . Today u have the same chance to corrupt your registry than ur .ini file. (Do u know the security mechanisms of the registry ?, or u have windows 95).
why 99.9 % of the developpers use the registry ? 99.9 of the developpers are in the wrong way ? :)
For few data, (config data), i repeat that the registry is very simple to use. (i have try registry and ini files)

Sorry for my poo english

OriOn

#13
For information, this is my read/write methods written with c++builder.


void __fastcall TSetupForm::OkSetupButtonClick(TObject *Sender)
{
       TRegIniFile *Reg = new TRegIniFile("Software\\ExBnetChat");

       Reg->WriteString("Setup","Username",UsernameEdit->Text);
       Reg->WriteString("Setup","Password",PasswordEdit->Text);
       Reg->WriteString("Setup","Cdkey",CdkeyEdit->Text);
       Reg->WriteString("Setup","Server",ServerEdit->Text);
       Reg->WriteString("Setup","Channel",ChannelEdit->Text);
       Reg->WriteBool("Setup","Auto",AutoCheck->Checked);
       
       delete  Reg;
       SetupForm->Close();
}
//---------------------------------------------------------------------------

void __fastcall TSetupForm::FormShow(TObject *Sender)
{
       TRegIniFile *Reg = new TRegIniFile("Software\\ExBnetChat");

       if ( Reg->KeyExists("Setup") == false )
       {
               Reg->WriteString("Setup","Username",UsernameEdit->Text);
               Reg->WriteString("Setup","Password",PasswordEdit->Text);
               Reg->WriteString("Setup","Cdkey",CdkeyEdit->Text);
               Reg->WriteString("Setup","Server",ServerEdit->Text);
               Reg->WriteString("Setup","Channel",ChannelEdit->Text);
               Reg->WriteBool("Setup","Auto",AutoCheck->Checked);
         }

       UsernameEdit->Text = Reg->ReadString("Setup","Username","Entrer Username");
       PasswordEdit->Text = Reg->ReadString("Setup","Password","Entrer Password");
       CdkeyEdit->Text =  Reg->ReadString("Setup","Cdkey","Entrer CdKey");
       ServerEdit->Text = Reg->ReadString("Setup","Server","Entrer Server");
       ChannelEdit->Text =  Reg->ReadString("Setup","Channel","Enter Channel");
       AutoCheck->Checked = Reg->ReadBool("Setup","Auto",false);

       delete  Reg;
}


More simple ?

Banana fanna fo fanna

#14
BAH. TWhatever :(