Reputation: 12745
I have the following code snippet which is working fine:
ifstream NDSConfig( "NDS.config" ) ;
string szConfigVal ;
while( getline( NDSConfig, szConfigVal ) )
{
//code
}
But the problem is I need to update a check box state by comparing the line values. The code then will similar to the following:
ifstream NDSConfig( "NDS.config" ) ;
string szConfigVal ;
while( getline( NDSConfig, szConfigVal ) )
{
if(szConfigVal == "AutoStart = 1")
{
//Set Check Box True
}
else if(szConfigVal == "AutoStart = 0")
{
//Set Check Box False
}
if(szConfigVal == "AutLogHistory = 1")
{
//Set Check Box True
}
else if(szConfigVal == "AutLogHistory = 0")
{
//Set Check Box False
}
if(szConfigVal == "AutoScan = 1")
{
//Set Check Box True
}
else if(szConfigVal == "AutoScan = 0")
{
//Set Check Box False
}
if(szConfigVal == "AutoMount = 1")
{
//Set Check Box True
}
else if(szConfigVal == "AutoMount = 0")
{
//Set Check Box False
}
if(szConfigVal == "AutoOpen = 1")
{
//Set Check Box True
}
else if(szConfigVal == "AutoOpen = 0")
{
//Set Check Box False
}
if(szConfigVal == "LastConnectedSvr = 1")
{
//Set Check Box True
}
else if(szConfigVal == "LastConnectedSvr = 0")
{
//Set Check Box False
}
}
If I am going to use while loop then my state will be over riden and only last in the loop value or state will be updated. Is there any other way out. I need to set the check box values after reading from config file . The Config file looks as below:
AutoStart = 0
AutLogHistory = 1
AutoScan = 1
AutoMount = 0
AutoOpen = 0
LastConnectedSvr = 1
Though I can have only single if and everything else as else if will help but I need a better way.
Upvotes: 0
Views: 342
Reputation: 33655
Alternatively, use boost::program_options
, this is designed perfectly for what you require!
EDIT: little more detail, program_options has a method to parse a config file, such as yours, and as you configure program_options, you can pass in the variable to store the value from the config file in. Have a look at their simple example, it will become abundantly clear...
Other option is for you to store your keys in a map, with a default value of 0, and then as you parse through your file, set the key to the value you read from the file...
EDIT:
using program options (this is untested code, please try refer to the documentation and fix as needed!)
int AutoStart;
int AutLogHistory;
int AutoScan;
int AutoMount;
int AutoOpen;
int LastConnectedSvr;
po::options_description desc("Allowed options");
desc.add_options()
("help", "produce help message")
("AutoStart", po::value<int>(&AutoStart)->default_value(0),"AutoStart")
("AutLogHistory", po::value<int>(&AutLogHistory)->default_value(0),"AutLogHistory")
("AutoScan", po::value<int>(&AutoScan)->default_value(0),"AutoScan")
("AutoMount", po::value<int>(&AutoMount)->default_value(0),"AutoMount")
("AutoOpen", po::value<int>(&AutoOpen)->default_value(0),"AutoOpen")
("LastConnectedSvr", po::value<int>(&LastConnectedSvr)->default_value(0),"LastConnectedSvr")
;
std::ifstream config("NDS.config");
po::parse_command_line(config, desc, true);
When that lot runs, the various integers will have the values from the file (or be defaulted to 0).
The neat thing with this approach is that you can have different types in your config files, and as long as they are formatted as INI files, then this will work.
The other approach using std::map, well @Moo-Juice has already added working code...
Upvotes: 3
Reputation: 64303
You can use boost program arguments parser with specifically config file parser to get all program arguments.
This is the example from boost (small modifications are mine) :
#include <boost/program_options.hpp>
namespace po = boost::program_options;
#include <iostream>
#include <fstream>
#include <iterator>
using namespace std;
// A helper function to simplify the main part.
template<class T>
ostream& operator<<(ostream& os, const vector<T>& v)
{
copy(v.begin(), v.end(), ostream_iterator<T>(cout, " "));
return os;
}
int main(int ac, char* av[])
{
std::cout<<av[0]<<std::endl;
std::vector<std::string> incsss;
std::vector<std::string> filsss;
try {
int opt;
string config_file;
// Declare a group of options that will be
// allowed only on command line
po::options_description generic("Generic options");
generic.add_options()
("version,v", "print version string")
("help,h", "produce help message")
("config,c", po::value<string>(&config_file)->default_value("multiple_sources.cfg"),
"name of a file of a configuration.")
;
// Declare a group of options that will be
// allowed both on command line and in
// config file
po::options_description config("Configuration");
config.add_options()
("optimization", po::value<int>(&opt)->default_value(10),
"optimization level")
("include-path,I",
po::value< vector<string> >(&incsss)->composing(),
"include path")
;
// Hidden options, will be allowed both on command line and
// in config file, but will not be shown to the user.
po::options_description hidden("Hidden options");
hidden.add_options()
("input-file", po::value< vector<string> >(&filsss), "input file")
;
po::options_description cmdline_options;
cmdline_options.add(generic).add(config).add(hidden);
po::options_description config_file_options;
config_file_options.add(config).add(hidden);
po::options_description visible("Allowed options");
visible.add(generic).add(config);
po::positional_options_description p;
p.add("input-file", 3);
po::variables_map vm;
store(po::command_line_parser(ac, av).
options(cmdline_options).positional(p).run(), vm);
notify(vm);
ifstream ifs(config_file.c_str());
if (!ifs)
{
cout << "can not open config file: " << config_file << "\n";
return 0;
}
else
{
store(parse_config_file(ifs, config_file_options), vm);
notify(vm);
}
if (vm.count("help")) {
cout << visible << "\n";
cout<<"here"<<std::endl;
return 0;
}
if (vm.count("version")) {
cout << "Multiple sources example, version 1.0\n";
return 0;
}
if (vm.count("include-path"))
{
cout << "Include paths are: "
<< vm["include-path"].as< vector<string> >() << "\n";
}
if (vm.count("input-file"))
{
cout << "Input files are: "
<< vm["input-file"].as< vector<string> >() << "\n";
}
cout << "Optimization level is " << opt << "\n";
cout << "incsss constains : " <<incsss << std::endl;
cout << "filsss constains : " <<filsss << std::endl;
}
catch(exception& e)
{
cout << e.what() << "\n";
return 1;
}
return 0;
}
Upvotes: 1
Reputation: 38810
The problem you're having is with your logic of reading this lines in. You could use boost::program_options as mentioned before, or even some kind of xml reader, but for a quick and dirty solution to your problem:
#include <string>
#include <map>
#include <algorithm>
// typedef some stuff so our fingers don't die.
typedef std::map<std::string, bool> CheckMap;
typedef CheckMap::iterator CheckMap_it;
typedef std::pair<std::string, bool> CheckPair;
std::string szKey, szVal;
// declare our map that will store the state
CheckMap map;
// insert possible config values
map.insert(CheckPair("AutoStart", false));
map.insert(CheckPair("AutLogHistory", false));
map.insert(CheckPair("AutoScan", false));
map.insert(CheckPair("AutoMount", false));
map.insert(CheckPair("AutoOpen", false));
map.insert(CheckPair("LastConnectedSvr", false));
// now loop through the file
ifstream NDSConfig( "NDS.config" ) ;
string szConfigVal ;
while( getline( NDSConfig, szConfigVal ) )
{
// erase any spaces in the line
szConfigVal.erase(std::remove_if(szConfigVal.begin(), szConfigVal.end(), isspace), szConfigVal.end());
// locate equals, split in to <key> <value> using that.
std::string::size_type equals(szConfigVal.find('='));
if(equals != std::string::npos) // exists?
{
szKey = szConfigVal.substr(0, equals);
szVal = szConfigVal.substr(equals + 1);
// locate key and set value
CheckMap_it it(map.find(szKey));
if(it != map.end()) // sanity check
{
// could use a boost-type cast here, but I'm keeping it simple
it->second = (szVal == "1") ? true : false;
};
};
}
Now, at the end, the map holds the values with the values from the file in them. You can iterate through them and do what you like with them.
Upvotes: 2