Your code has quite a few problems, as cire has already pointed out.
But based on this post and your other one...
pass string to double
http://www.cplusplus.com/forum/beginner/168093/
... I think you're going about it in a rather inefficient way. Well, it does looks like you might be intending to search the file for one value at a time.
If you intend to extract multiple values from your configuration file it makes more sense to parse the file once, to extract the values into a std::vector or std::map, and then search the vector or map for your values.
I prefer to use a std:vector (of std::pair values) for this kind of thing, as I want the values in the same order when I save them. std::map sorts the values by key value so imposes alphabetical order which not what I always want (I like to group by category.)
(Aside: in passing I guess you're going to need an expression evaluator, too. You could code your own, but I would consider using an existing library, e.g.
http://muparser.beltoforion.de/ )
Andy
Basic example of how to load name-value pairs from file (using istringstream for testing so C++ Shell friendly) into a vector and then searching vector for required values.
I have kept the approach deliberately basic here and pre-C++11 (e.g. for the search I would have prob use std::find_if() algorithm with a lambda function rather than a for loop.)
I am using a return code to indicate that a value is not found as (a) a blank string might be an acceptable value, (b) raising an exception is not appropriate as successfuly not finding a value is not (necessarily) an error condition. You could use a special string (e.g. "NOT_FOUND") instead but this would prob make the code using the functionality that bit messier.
And it would be much better to encapsulate the functionality in a class.
(Some of code borrowed from other thread...)
Test_SearchConfig with EoGUESS
EoGUESS found at index = 1
EoGUESS = 1e10
Test_SearchConfig with NtsGUESS
NtsGUESS found at index = 0
NtsGUESS = 1e10*1e4
Test_SearchConfig with varystep
varystep found at index = 14
varystep = sqrt(10.0)
Test_SearchConfig with NOT_THERE
NOT_THERE not found |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
// comment this line out to use file
#define TESTING
#include <iostream>
#ifndef TESTING
#include <fstream>
#else
#include <sstream> // use stringstream (rather than fstream) for C++ Shell testing
#endif
#include <string>
#include <vector>
#ifdef TESTING
// pretend file for testing
const char g_testData[] =
"NtsGUESS = 1e10*1e4\n"
"EoGUESS = 1e10\n"
"EoDEFAULT = 4\n"
"NtsDEFAULT = 1e19*1e4\n"
"paramSTEP = 1.2,\n"
"deltx = 1e-8\n"
"\n"
"Na = 1e16*1e6\n"
"Nd = 1e15*1e6\n"
"Brad = 1e-10*1e-6\n"
"sigma = 1e-12 *1e-4\n"
"sigmaneutral = sigma*1e-3\n"
"&vary = Nd\n"
"varystart = 1e16*1e6\n"
"varymax = 1e16*1e6\n"
"varystep = sqrt(10.0)\n"
"\n"
"T = 300";
#endif
typedef std::pair<std::string, std::string> NVP; // Name Value Pair
bool LoadConfig(std::vector<NVP>& configValues);
int SearchConfig(std::vector<NVP>& configValues, const std::string& name, std::string& value);
void Test_SearchConfig(std::vector<NVP>& configValues, const std::string& name);
int main()
{
std::vector<NVP> configValues;
if (LoadConfig(configValues))
{
Test_SearchConfig(configValues, "EoGUESS");
Test_SearchConfig(configValues, "NtsGUESS");
Test_SearchConfig(configValues, "varystep");
Test_SearchConfig(configValues, "NOT_THERE");
}
else
{
std::cout << "LoadConfig failed?" << std::endl;
}
return 0;
}
// http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring/347974#347974
namespace StringUtils {
const std::string WHITESPACE = " \t";
inline std::string TrimLeft (const std::string& s)
{
size_t startpos = s.find_first_not_of(WHITESPACE);
return (startpos == s.npos) ? "" : s.substr(startpos);
}
inline std::string TrimRight (const std::string& s)
{
size_t endpos = s.find_last_not_of(WHITESPACE);
return (endpos == s.npos) ? "" : s.substr(0, endpos + 1);
}
inline std::string Trim (const std::string& s)
{
return TrimRight(TrimLeft(s));
}
bool SplitNameValuePair(const std::string& s, char c, std::string& name, std::string& value)
{
std::string::size_type pos = s.find(c);
if (pos == std::string::npos)
return false;
name = Trim(s.substr(0, pos));
value = Trim(s.substr(pos + 1));
return true;
}
} // end namespace StringUtils
bool LoadConfig(std::vector<NVP>& configValues)
{
#ifndef TESTING
// use constructor which opens file rather than default
// constructor plus open() method
std::ifstream Myfile("in1.txt");
if(!Myfile.is_open())
{
// this way round the logic works better with the #ifdefs
std::cout << "Unable to open this file." << std::endl;
return false;
}
#else
std::istringstream Myfile(g_testData);
#endif
std::string line;
int lineNum = 0;
while (getline(Myfile, line))
{
++lineNum;
line = StringUtils::Trim(line);
if (line.empty()) // skip blank lines
continue;
std::string name;
std::string value;
if (StringUtils::SplitNameValuePair(line, '=', name, value))
{
name = StringUtils::Trim(name);
value = StringUtils::Trim(value);
configValues.push_back(std::make_pair(name, value));
}
else
{
std::cout << "skipping line " << lineNum << std::endl;
}
}
// no need for Myfile.close() as ifstream destructor handles this
return true;
}
int SearchConfig(std::vector<NVP>& configValues, const std::string& name, std::string& value)
{
value.clear();
const int count = configValues.size();
for (int index = 0; index < count; ++index)
{
if (configValues[index].first == name)
{
value = configValues[index].second;
return index;
}
}
return -1; // not found
}
void Test_SearchConfig(std::vector<NVP>& configValues, const std::string& name)
{
std::cout << "Test_SearchConfig with " << name << std::endl;
std::cout << std::endl;
std::string value;
int found_index = SearchConfig(configValues, name, value);
if (-1 == found_index)
{
std::cout << name << " not found" << std::endl;
}
else
{
std::cout << name << " found at index = " << found_index << std::endl;
std::cout << name << " = " << value << std::endl;
}
std::cout << std::endl;
}
|