[INFO]
I'm new here and... new to programming. I'm learning C (with very little of C++) for about a year and now I'm stuck. I'm currently writing my first bigger application for training purposes and as every programist - I'm trying to be as lazy as I could. My application is based on Simple Fast Multimedia Library (SFML) for drawing graphics and of course C/C++ for logic. I was tired of having lots of different variables hidden in code (like Window Resolution, Window Position etc.) soo I started writing class for reading *txt files with configuration (You know: config.ini with something like "iWindowResolutionX=1920;"). Algorythm that opens *txt files, interprets them and pulls out needed data is working (proppably it is very bad - but hey, it is working :P)
[QUESTION] I'm stuck with very basic thing. I have object of my config file reader class and I want to achieve something like this:
Int main()
{
int WindowResolutionX = 0; //nothing special - int with value of 0.
CfgReader cfg_object("config.ini"); // object of CfgReader class with custom
constructor passing name of *txt
configuration file.
WindowResolutionX = cfg_object.Search("iWindowResolutionX"); // As you see - I want to write a code that calls method "Search" on cfg_object. This method takes variable name as parameter and after sucsess (value found) returns it.
And here I am stuck. How to force method to return different basic data types( char, int, float etc. )? }
I've tried defining method return type as "auto", but it gives me an error "a function that returns 'auto' cannot be used before it is defined" (I don't understand what's VS is talking to me here) and then errors about trying to return different datatypes than firstly selected (this is simple, if compiler see "return value" for the first time, it can't allow me to return any other datatype).
Next thing I've tried was template methods, but I'm to stupid to understand it ;)
Ok, there is simple solution - I can copy my Search method X times for X datatypes I want and just simply overload it - but this is not elegant solution and won't teach me anything new. Below my code:
"CfgReader.h"
#pragma once
#include "fstream"
#include <iostream>
#include <string>
class CfgReader
{
public:
FILE *fp;
const char * cfg_filename;
size_t filesize;
std::string line;
int int_val;
float float_val;
char char_val;
bool bool_val;
long long_val;
std::string string_val;
size_t size_t_val;
public:
void OpenFile(const char * filename);
void CloseFile();
auto Search(const char * search_val);
void Show_content();
int r_int();
char r_char();
float r_float();
size_t r_size_t();
long r_long();
bool r_bool();
std::string r_string();
CfgReader();
CfgReader(const char *);
~CfgReader();
};
"CfgReader.cpp"
#include "CfgReader.h"
#pragma warning(disable: 4996)
CfgReader::CfgReader()
{
CfgReader("");
}
CfgReader::CfgReader(const char * filename)
{
if ((sizeof(filename) == 1) && (filename[0] == 0))
{
std::cout << "\n CfgReader No filename.";
cfg_filename = "";
fp = NULL;
}
else
{
std::cout << "\n test";
line = "";
int_val = NULL;
float_val = NULL;
char_val = NULL;
bool_val = false;
long_val = NULL;
string_val = "";
size_t_val = NULL;
cfg_filename = filename;
OpenFile(cfg_filename);
}
}
void CfgReader::OpenFile(const char * filename)
{
fp = fopen(filename, "rb");
if (fp != NULL)
{
std::cout << "\n good!";
}
else
{
std::cout << "\n Error, could not open file.";
}
rewind(fp);
fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
rewind(fp);
std::cout << "\n filesize: " << filesize;
//system("pause");
}
void CfgReader::Search(const char * search_val)
{
size_t search_val_length = 0;
for (search_val_length; search_val[search_val_length] != '\0';
search_val_length++);
std::string test;
if (fp == NULL)
{
std::cout << "\n Error, file not loaded!";
}
else
{
char first_letter = 0;
bool match = false;
size_t counter = 0;
rewind(fp);
while (match == false)
{
while (first_letter != 13)
{
fread(&first_letter, sizeof(char), 1, fp);
}
if (first_letter == 13)
{
fread(&first_letter, sizeof(char), 1, fp);
if (first_letter == 10)
{
do
{
fread(&first_letter, sizeof(char), 1, fp);
if (first_letter == search_val[counter])
{
test += first_letter;
counter++;
if(counter==search_val_length)
{
match = true;
break;
}
}
else
{
counter = 0;
test = "";
break;
}
} while (first_letter != 61);
if (test == search_val || match == true)
{
match = true;
break;
}
}
}
std::cout << "\n ftell(fp): " << ftell(fp);
if (ftell(fp) == filesize) break;
}
if (match == false)
{
std::cout << "\n ERROR, no such VALUE!";
}
else
{
std::cout << "\n test string = " << test;
//system("pause");
//Show_content();
///line = test;
///test = "";
while (first_letter != 13)
{
fread(&first_letter, sizeof(char), 1, fp);
if (first_letter == 61)continue;
test += first_letter;
}
std::cout << "\n test string VALUE (string):" << test << std::endl;
switch (line[0])
{
case 'i':
int_val = std::stoi(test);
std::cout << "\n int_val: " << int_val;
//return int_val;
//a = int_val;
break;
case 'f':
float_val = std::stof(test);
std::cout << "\n float_val: " << float_val;
//return float_val;
//a = float_val;
break;
case 'b':
if (test[0] == 'f' || test[0] == '0') bool_val = false;
else bool_val = true;
std::cout << "\n bool_val: " << bool_val;
//return bool_val;
//a = bool_val;
break;
case 'l':
long_val = std::stol(test);
std::cout << "\n long_val: " << long_val;
//return long_val;
//a = long_val;
break;
case 's':
string_val = test;
std::cout << "\n string_val: " << string_val;
//return string_val;
// a = string_val;
break;
case 't':
size_t_val = std::stoul(test);
std::cout << "\n size_t_val: " << size_t_val;
//return size_t_val;
//a = size_t_val;
break;
}
}
}
}
int CfgReader::r_int()
{
return int_val;
}
char CfgReader::r_char()
{
return char_val;
}
float CfgReader::r_float()
{
return float_val;
}
size_t CfgReader::r_size_t()
{
return size_t_val;
}
long CfgReader::r_long()
{
return long_val;
}
bool CfgReader::r_bool()
{
return bool_val;
}
std::string CfgReader::r_string()
{
return string_val;
}
void CfgReader::Show_content()
{
std::cout << "\n //--------------------------CfgReader.Show_content()------------------------\\"<<std::endl;
if (fp != NULL)
{
rewind(fp);
fseek(fp, 0, SEEK_END);
int filesize = ftell(fp);
char literka;
rewind(fp);
while (ftell(fp) != filesize)
{
fread(&literka, sizeof(char), 1, fp);
std::cout << "\n" << (short)literka << " - " << literka;
}
}
else
{
std::cout << "\n Error: fp == NULL.";
}
std::cout << "\n \\--------------------------/CfgReader.Show_content()------------------------// \n";
}
void CfgReader::CloseFile()
{
fclose(fp);
}
CfgReader::~CfgReader()
{
}
"Source.cpp"
#pragma warning(disable:4996)
#include "CfgReader.h"
int main()
{
CfgReader Config("config.ini");
Config.Search("iBitDepth");
system("pause");
return 0;
}
"config.ini"
//------------------------ M_UPTIME config FILE ------------------------//
[Window]
iWindowResX=1920
iWindowResY=1080
fWindowScale=1
iWindowPosX=-1920
iWindowPosY=0
iBitDepth=32
[Screen Saver]
iScreenSaverTimeLimit=600
[TestValues]
bThisIsBool=false
bThisIsBoolToo=true
sThisIsString=Ala ma kota a kot ma ale
Anyone can point me out how to convert Search method for being able to either return different datatypes:
int main()
{
int value_1 = 0;
CfgReader Config("config.ini");
value_1 = Config.Search("iBitDepth");
return 0;
}
or work as here: (CfgReader object gets reference to variable as a parameter)
int main()
{
int value_1 = 0;
CfgReader Config("config.ini");
Config.Search("iBitDepth", &value_1);
return 0;
}
If someone could also give me a example on how to properly convert my Search method for template method. Thanks for responces, I'm out of ideas...
I'd suggest to implement separate methods for each data type. You know data type of the target variable, right? Then you can do few methods like this:
int GetInt(const char* name, int defaultValue = 0) const;
std::string GetString(const char* name, const char* defaultValue = "") const;
And call appropriate method:
int bitDepth = config.GetInt("Window.iBitDepth", 24);