Valhalla Legends Forums Archive | Battle.net Bot Development | [C++] INI file functions

AuthorMessageTime
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.

[code]
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;
}
[/code]

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.
May 12, 2003, 1:40 PM
K
[code]char &c[/code]
means c is a reference to one character.
try char *c.
May 12, 2003, 3:27 PM
tA-Kane
[quote author=TruffleShuffle link=board=17;threadid=1310;start=0#msg9761 date=1052746801][code]void Get( char parameter[255], char &result)[/code][/quote]Use char *result, instead.

[quote author=TruffleShuffle link=board=17;threadid=1310;start=0#msg9761 date=1052746801][code]strcpy(&result, returned);[/code][/quote]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:
[code]strcpy(result,&returned[0]);[/code]
May 12, 2003, 7:35 PM
Eibro
[code]while( !config_file.eof() )
{
config_file >> text;
if(!strnicmp( text, parameter, strlen(parameter)) )
{
strcpy( returned, (text + strlen(parameter)) );
}
}[/code]You're going to read past the end of the file when testing for EOF in this manner. Use something like:
[code]
while (config_file >> text) // Work with text
[/code]See here for more information: http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5
May 12, 2003, 8:00 PM
Camel
[quote author=Maddox link=board=17;threadid=1310;start=0#msg9802 date=1052781561]
Why don't you use GetPrivateProfileString() ?
[/quote]

apparantly, "real men" don't take "shortcuts."
whatever.
May 13, 2003, 1:13 AM
dRAgoN
Globals
[code]
char            Username[128];
char            Password[128];
char            Server[128];
char            HomeChannel[128];
[/code]

your get function
[code]
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);
}
[/code]

How to use
[code]
       Get(Username,
                Password,
                Server,
                HomeChannel);
[/code]

dont like it you'll get over it
May 14, 2003, 4:35 AM
Eibro
Perhaps a more robust solution:
[code]#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;
}[/code]Now I don't know if that works 100%, I didn't test it :)
May 14, 2003, 11:11 AM
Kp
[quote author=Maddox link=board=17;threadid=1310;start=0#msg9802 date=1052781561]Why don't you use GetPrivateProfileString() ?[/quote]That only exists under Windows. As written, the other versions of the code posted should work anywhere with an iostream library. :)
May 14, 2003, 4:27 PM
Kp
[quote author=Maddox link=board=17;threadid=1310;start=0#msg10017 date=1052978485]True, but aren't ini configs created for and used mostly on windows?[/quote]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).
May 15, 2003, 4:05 PM
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.
May 17, 2003, 6:35 PM
MrRaza
[quote author=OriOn link=board=17;threadid=1310;start=0#msg10141 date=1053196544]
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.
[/quote]


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.
May 17, 2003, 9:19 PM
Grok
[quote author=OriOn link=board=17;threadid=1310;start=0#msg10141 date=1053196544]
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.
[/quote]

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.
May 18, 2003, 1:41 AM
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
May 18, 2003, 4:00 AM
OriOn
For information, this is my read/write methods written with c++builder.

[code]
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;
}
[/code]

More simple ?
May 18, 2003, 4:21 AM
St0rm.iD
BAH. TWhatever :(
May 18, 2003, 7:41 PM
Yoni
delete (TSt0rm*)iD;
May 18, 2003, 8:12 PM
Eibro
[quote author=OriOn link=board=17;threadid=1310;start=15#msg10175 date=1053231692]
For information, this is my read/write methods written with c++builder.

[code]
// Garbage
[/code]

More simple ?

[/quote]Guess what? Not everyone uses Borland. Using the registry limits you to Windows, using TRegIniFile limits you to Borland. Do you understand all the API calls going on underneath the TRegIniFile class? Try using the Win32 API calls to manipulate the registry... I think you'll quickly see manipulating ini files is much easier.
May 18, 2003, 11:46 PM
OriOn
Yes i know what behind the TRegistry Class Mr the master programmer. And i know how to use the win32api Mr the master programmer. And use the win32api isnt a lot of more difficult than use the vcl so stop to say wrong things plize and learn :/.
May 19, 2003, 1:03 AM
Eibro
[quote author=OriOn link=board=17;threadid=1310;start=15#msg10223 date=1053306186]
Yes i know what behind the TRegistry Class Mr the master programmer. And i know how to use the win32api Mr the master programmer. And use the win32api isnt a lot of more difficult than use the vcl so stop to say wrong things plize and learn :/.
[/quote]No need to get defensive. I never said the Win32 API was any more difficult to use than VCL (I've never used VCL anyway) I was just pointing out that when others refer to manipulating the registry, they're probably not talking about using VCL to do so. That would be like me coming on here and saying it's simple to make a binary bot, it only requires three statements:
[code]BnetBot myBot("useast.battle.net", 6112);
myBot.LoadConfig("config.ini");
myBot.Connect();[/code]Unless others use the same libraries I do, making such comparisons is pretty useless.
May 19, 2003, 1:33 AM
MrRaza
If you just using 5 API functions your not using the registry to your full advantage.
May 19, 2003, 2:53 AM
OriOn
Ok this my last post about registry and .ini files.
I repeat. Depends af the case, i will be more effective to store data in a file or in the registry.
For fiew config data, i think that the registry is more effective.

To Eibro : i prefer and i have done my own bot for A to Z. I don t use some libraries or like that. In your last post you don t print the code of your LoadConfig procedure. Your post is a joke ?

To MrRaza : I agree that they are more api routines to use the registry. But i speak about "store and read config data". And for this works u only need 5 api :
- RegOpenKey
- RegCloseKey
- RegCreateKey / RegCreateKeyHex
- RegQueryValue / RegQueryValueHex
- RegSetValue / RegSetValueHex

I make my best effort to be understood with my poor english.
May 19, 2003, 12:54 PM
St0rm.iD
Both have their merits. Live with it and pick the best choice for your project.
My 2cents: use registry to store stuff like window positions, and ini files for user profiles, like username/password/cdkey/etc.
May 19, 2003, 7:33 PM
OriOn
Yes, i store the log of the chan in a file not in the registry :p
May 20, 2003, 12:26 AM
St0rm.iD
Not really what I meant...but that works.
May 20, 2003, 1:35 AM
Skywing
[quote author=OriOn link=board=17;threadid=1310;start=0#msg10174 date=1053230419]
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
[/quote]
I'm not sure if this is a meaningful response, as I can barely understand your post.

Windows keeps the registry locked when running. In particular, you can't read from it while you've got Windows up, which means you can't make a copy of it. Under Windows NT, there's a (complicated) API for backing up and restoring registry keys.

If part of a registry hive file is damaged, Windows tends to not load the whole thing and refuse to boot. There's no really easy way to restore a working copy on a dead system - either you reinstall with the exact same file paths and (somehow) copy over the old registry database and hope it works, or if you're using Win2K, you might be able to use the "emergancy recovery disks", if you made those.

I can easily boot from a floppy and edit an INI file - however, again, there's no simple or easy way to do this with the registry. Windows 9x Regedit can be used in DOS, but it's unwieldy and difficult to use at the best (I've had the misfortune of having to spend many hours trying to use it to change a few values to make a Windows 98 system bootable again).

Plus, you've got the added advantage of configuration files portable between operating systems. For example, there are Unreal Tournament versions for Linux and Win32 which both share the exact same INI configuration file format; you can swap configuration files from Windows and Linux and have them work perfectly (something I've done myself; it's a useful feature, not something you'd rarely touch). You can hardly say the same for the registry.
May 20, 2003, 4:29 PM

Search