Reading from a configuration file
Now I have a good working environment, I have started to develop a gaming engine based around Erik Yuzwa's PeonEngine (http://www.gameprogrammingstarttofinish.wazooinc.com/)  and Tim Jones' game engine tutorial (http://www.sdltutorials.com/sdl-tutorial-basics/). One of my requirements was the ability to configure the game engine using a configuration file. This initially looked to be quite simple as a function was already available, but still took several hours to work the way I wanted it to - all because of UNICODE.

By default unicode is automatically enabled in Visual C++ 2010 and to convert sting (char*) variables proved quite tasking. In the end though I had learn't that unicode can be disabled by setting the project properties "Configuration Properties --> General --> Project Defaults --> Charater Set" to "Not Set".

The function to read values from the configuration file is called GetPrivateProfileString or GetPrivateProfileInt. In unicode the functions pass wide characters (16 bit - 2 bytes) and therefore a normal char variable would require conversion. One way around this issue is to pass the string with an 'L' prefix (i.e. L"New String").

Example Unicode GetPrivateProfileString funciton


DWORD dwStatus = 0;
TCHAR strReturnString[260];
ZeroMemory( &strTemp, sizeof( strTemp ) );
         
dwStatus = GetPrivateProfileString(L"APPLICATION",L"STRING_VALUE", L"ERROR", strReturnString, 260, lpFilename);

Even though I could pass wide strings I preferred to use char's as this was easier to understand and debug for a beginner such as myself. The following code is a stand-alone solution with unicode turned off, this will be incorporated into my game engine classes.

Config.ini - Configuration File

[FIRST_VALUES]
INTEGER_VALUE=800
STRING_VALUE=ABC

[SECOND_VALUES]
BOOL_VALUE=TRUE
FLOAT_VALUE=9.87654

iniReader - Configuration File Reader Code

/*! 
 \file iniReader.cpp
 \brief My First Steps : C++ Game Development - ini Confuration File Reader

 A Configuration File Reader demo allows for Strings, Integers, Boolean and Floats.

 NOTE : UNICODE HAS BEEN DISABLED!

 \author Matt Wakeling
 \date 25th May 2010
*/

#include <Windows.h>
#include <string>

using namespace std;

/// DECLARATION : Declare Int2String Function.
string Int2String(int intNumber);

/// DECLARATION : Declare Float2String Function.
string Float2String(float number);

/// DECLARATION : Declare GetStringValue Function.
string GetStringValue(LPCTSTR lpApp, LPCTSTR lpKeyName, LPCTSTR lpFilename, LPCTSTR lpDefault);

/// DECLARATION : Declare GetIntegerValue Function.
UINT GetIntegerValue(LPCTSTR lpApp, LPCTSTR strKeyName, LPCTSTR lpFilename, int iDefault);

/// DECLARATION : Declare GetBoolValue Function.
bool GetBoolValue(LPCTSTR lpApp, LPCTSTR lpKeyName, LPCTSTR lpFilename, LPCTSTR lpDefault);

/// DECLARATION : Declare GetFloatValue Function.
float GetFloatValue(LPCTSTR lpApp, LPCTSTR lpKeyName, LPCTSTR lpFilename, LPCTSTR lpDefault);


/*! 
 \brief DEFINITION : Define main function, allows arguments to be passed.

 DESCRIPTION : C++ Main code entry point, no arguements have been passed to the function.
 
 \param argc - Set the number of arguements passed to the function.
 \param argv[] - Array of arguements passed to the function.
 \return int - Returns an integer value to show completion status (0 = Successful).
*/
int main(int argc, char* argv[])
{ 
 /// COMMENT : Start Function.
 
 /// COMMENT : Get String value from Configuration File.
 printf("lpApp                  : %s\n","FIRST_VALUES");
 printf("lpKey                  : %s\n","STRING_VALUE");
 printf("lpFilename             : %s\n","C:\\Config.ini");
 printf("Return Value (String)  : %s\n",GetStringValue("FIRST_VALUES", "STRING_VALUE", "C:\\Config.ini","ERROR").c_str());

 printf("\n");

 /// COMMENT : Get Integer value from Configuration File.
 printf("lpApp                  : %s\n","FIRST_VALUES");
 printf("lpKey                  : %s\n","INTEGER_VALUE");
 printf("lpFilename             : %s\n","C:\\Config.ini");
 printf("Return Value (Integer) : %s\n",Int2String(GetIntegerValue("FIRST_VALUES", "INTEGER_VALUE", "C:\\Config.ini",-1)).c_str());

 printf("\n");

 /// COMMENT : Get Boolean value from Configuration File.
 printf("lpApp                  : %s\n","SECOND_VALUES");
 printf("lpKey                  : %s\n","BOOL_VALUE");
 printf("lpFilename             : %s\n","C:\\Config.ini");
 
 if (GetBoolValue("SECOND_VALUES", "BOOL_VALUE", "C:\\Config.ini","FALSE"))
  printf("Return Value (Bool)    : %s\n","TRUE");
 else
  printf("Return Value (Bool)    : %s\n","FALSE");
 
 printf("\n");

 /// COMMENT : Get Float value from Configuration File.
 printf("lpApp                  : %s\n","SECOND_VALUES");
 printf("lpKey                  : %s\n","FLOAT_VALUE");
 printf("lpFilename             : %s\n","C:\\Config.ini");
 printf("Return Value (Float)   : %s\n",Float2String(GetFloatValue("SECOND_VALUES", "FLOAT_VALUE", "C:\\Config.ini","0.0")).c_str());
 
 /// COMMENT : Exit Program and Return no errors code (0 = Successful).
  return 0;

  /// COMMENT : End Function.
}


/*! 
 \brief DEFINITION : Define convert integer to string function.

 DESCRIPTION : Converts integer values to string, so the number can be output via PRINTF.
 
 \param intNumber - Integer value requiring conversion.
 \return string - String value of converted output.
*/
string Int2String(int intNumber)
{
    if (intNumber == 0)
        return "0";
    string strTemp="";
    string strReturnValue="";
    while (intNumber>0)
    {
        strTemp+=intNumber%10+48;
        intNumber/=10;
    }
    for (int i=0;i<strTemp.length();i++)
        strReturnValue+=strTemp[strTemp.length()-i-1];
    return strReturnValue;
}


/*! 
 \brief DEFINITION : Define convert Float to string function.

 DESCRIPTION : Converts float values to string, so the number can be output via PRINTF.
 
 \param fltNumber - Float value requiring conversion.
 \return string - String value of converted output.
*/
string Float2String(float fltNumber)
{
 char* strTest = new char[MAX_PATH];
 
 int intResult = 0;
 
 intResult = _snprintf_s(strTest, MAX_PATH, MAX_PATH, "%f", fltNumber);

 return (string) strTest;
}


/*! 
 \brief DEFINITION : Define get string value from configuration file function.

 DESCRIPTION : Gets a string value from a configuration file.
 
 \param lpApp - Application header in configuration file [APPLICATION].
 \param lpKeyName - Key name in configuration file KEYNAME=.
 \param lpFilename - File name and path for the configuration.
 \param lpDefault - Default string return value.
 
 \return string - String value from configuration file.
*/
string GetStringValue(LPCTSTR lpApp, LPCTSTR lpKeyName, LPCTSTR lpFilename, LPCTSTR lpDefault)
{
 DWORD dwResult = 0;
 CHAR strReturn[MAX_PATH];

 dwResult = GetPrivateProfileString(lpApp, lpKeyName, lpDefault, strReturn, MAX_PATH, lpFilename);
 
 return strReturn;
}


/*! 
 \brief DEFINITION : Define get integer value from configuration file function.

 DESCRIPTION : Gets an integer value from a configuration file.
 
 \param lpApp - Application header in configuration file [APPLICATION].
 \param lpKeyName - Key name in configuration file KEYNAME=.
 \param lpFilename - File name and path for the configuration.
 \param iDefault - Default integer return value.
 
 \return UINT Unsigned Integer - Integer value from configuration file.
*/
UINT GetIntegerValue(LPCTSTR lpApp, LPCTSTR lpKeyName, LPCTSTR lpFilename, int iDefault)
{
 UINT iResult;

 iResult = GetPrivateProfileInt(lpApp,
        lpKeyName,
        iDefault,
        lpFilename);
 return iResult;
}


/*! 
 \brief DEFINITION : Define get boolean value from configuration file function.

 DESCRIPTION : Gets an boolean value from a configuration file.
 
 \param lpApp - Application header in configuration file [APPLICATION].
 \param lpKeyName - Key name in configuration file KEYNAME=.
 \param lpFilename - File name and path for the configuration.
 \param lpDefault - Default boolean return value.
 
 \return bool - Boolean value from configuration file.
*/
bool GetBoolValue(LPCTSTR lpApp, LPCTSTR lpKeyName, LPCTSTR lpFilename, LPCTSTR lpDefault)
{
 string strStringValue = GetStringValue(lpApp, lpKeyName, lpFilename, lpDefault);
 
 if(strStringValue == "TRUE")
  return true;
 else
  return false;
}


/*! 
 \brief DEFINITION : Define get float value from configuration file function.

 DESCRIPTION : Gets an float value from a configuration file.
 
 \param lpApp - Application header in configuration file [APPLICATION].
 \param lpKeyName - Key name in configuration file KEYNAME=.
 \param lpFilename - File name and path for the configuration.
 \param lpDefault - Default float return value.
 
 \return float - Float value from configuration file.
*/
float GetFloatValue(LPCTSTR lpApp, LPCTSTR lpKeyName, LPCTSTR lpFilename, LPCTSTR lpDefault)
{
 string strStringValue = GetStringValue(lpApp, lpKeyName, lpFilename, lpDefault);
 
 return (float)strtod(strStringValue.c_str(),TEXT('\0'));
}


When compliled the stand-alone version should produce the following output to show everything is working correctly.