0

I have a config file:

#X,Name,hostid,processid,executecommand,Max Runs, Max failure time 
X,Main_XYZ_service,1,1,/opt/bada/bin,3,6,300

I parsed the above config file and stored each of the values in a vector of type string.

This is stored in vector<string> scanned:

//scanned[0]=X
//scanned[1]=Main_XYZ_service.........
 long H_hostid = atoi(scanned[5].c_str()); 

how can I detect the type of the elements present in the vector?

If I call atoi() with a string that doesn't have a number, atoi() returns 0, but it also returns 0 if the string contains the number 0. How can I correctly assign a value to H_hostid?

Nathan Fellman
  • 122,701
  • 101
  • 260
  • 319
shakirgooty
  • 134
  • 2
  • 8

4 Answers4

1

In an absolute sense, you can't. If you encounter the string "0", you can't know whether the user intended a string, an integer or a floating point value. On the other hand, if you know what you need, you can try to convert (say by using boost::lexical_cast), and generate an error if it doesn't match. Alternatively, you can use regular expressions for pattern matching, and decide what type you want as a result of what pattern matches.

For a configuration file, I'd suggest the former. Just keep everything as a string until you know what you need, then try the conversion (using something reasonable for the conversion, which will report an error, and not atoi).

James Kanze
  • 150,581
  • 18
  • 184
  • 329
0

Don't use atoi() - as you say, there is no way to detect errors. Use std::istringstream in C++, or strtol() in C.

long H_hostid;
std::istringstream stream(scanned[5]);
if (!(stream >> H_hostid)) {
    // handle error
}

You could also use boost::lexical_cast, which does the same thing as that example, and throws an exception if the conversion fails.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • strtol("a",NULL,NULL) ; returns 0 and strtol("0",NULL,NULL) also returns 0. strtol() function does the same.Even i have used sscanf() but for sscan("1a","%ld",&temp); returns 1 where for me it should return 0 – shakirgooty Oct 17 '11 at 17:18
  • @user958719: If you really want to use `strtol()`, than use the second argument (`char **endptr`) to determine how many characters were read. That will tell you whether the input was actually a number. You might find things simpler if you use the C++ library. – Mike Seymour Oct 17 '11 at 17:21
0

If this is the data stored as a single string:

X,Main_XYZ_service,1,1,/opt/bada/bin,3,6,300

then the solution is, split this string using , as separator, and store each token in an array of size 8, then you can interpret each token based on the index as shown below:

char,string, int, int, string, int, int, int
 0     1      2    3     4      5    6    7

Code would look like this:

std::string s = "X,Main_XYZ_service,1,1,/opt/bada/bin,3,6,300";
std::vector<std::string> tokens = split(s); //write the function yourself!

char c = tokens[0]; //token with index 0 is char
std::string service = tokens[1]; //token with index 1 is string
std::string path = tokens[4]; //token with index 4 is string


int int_indices[] = {2,3,5,6,7}; //rest of the index has int : total 5
for(int i = 0 ; i < 5 ; i++ )
{
    try
    {
         int value = boost::lexical_cast<int>(tokens[int_indices[i]]);
         //store value
    }
    catch(const bad_lexical_cast &) 
    {
         std::cout <<  tokens[int_indices[i]] <<" is not an int" << std::endl;
    }
}
Nawaz
  • 353,942
  • 115
  • 666
  • 851
0

Whenever you write a config file to be used by your application, you know in advance in what order the values will appear in that file. Otherwise, an xml or key value coding will be a better option to write a config file for general case. Personally, I would never create a config file as you have shown in your example.

Abhinav
  • 1,496
  • 3
  • 15
  • 31