2

Possible Duplicate:
How do I tokenize a string in C++?

I have a string of the following form , which is a user input.

a1 10.2 lib_t 50 sv 60 out 'true'

Here, a1 is a parameter of type double, and its value is 10.2 . Similarly, lib_t = 50, sv = 60 and out = 'true' is a string.

This input can be specified in any order.. such as lib_t 50 a1 10.2

The spaces in between the words may vary.

Edit: Boost tokenizer can handle this. I have written the necessary code. But I want to see if there is any other standard way to handle this WITHOUT using boost library.

The input is pretty short. I am not very keen on the efficiency here (sorry for using the word 'efficient' in my original edit).

2
  • any other efficient way? What efficiency are you looking for? Write the code which first works, then think about efficiency and all! Commented Sep 15, 2011 at 17:16
  • There is no actual question here, or at least I'm not seeing it. Commented Sep 15, 2011 at 17:17

2 Answers 2

2
#include <sstream>
#include <ostream>
#include <istream>
#include <string>
#include <stdexcept>

int main() {
    std::string parameters = "a1 10.2 lib_t 50 sv 60 out 'true'";

    std::stringstream ss(parameters);
    std::string param;
    double a1;
    int libt; //names ending in _t are not allowed
    short sv;
    std::string out;
    while( ss >> param) {
        if (param == "a1")
            ss >> a1;
        else if (param == "lib_t")
            ss >> libt;
        else if (param == "sv")
            ss >> sv;
        else if (param == "out")
            ss >> out;
        else {
            std::stringstream err;
            err << "unknown parameter type: \"" << param << "\"";
            throw std::runtime_error(err.str());
        }
        if (!ss) {
            std::stringstream err;
            err << "error parsing parameter: \"" << param << "\"";
            throw std::runtime_error(err.str());
        }
    }
}

http://ideone.com/zz1r8

It's possible to make more optimized code, but it would be a LOT more complicated, whereas this is fairly fast, and simple. And has all the error checking built right in.

1
  • I made a slightly more complicated version (ideone.com/SUg9G) which is slightly faster (especially with more parameters) and handles more complex arguments better. Commented Sep 15, 2011 at 18:07
0

If you have sufficiently conforming C++11 compiler, you can write your grammar in AXE (not tested):

std::string input = "a1 10.2 lib_t 50 sv 60 out 'true'";
double d;
unsigned u;
std::string str;

auto space = axe::r_any(" \t");
auto a1_rule = *space & "a1" & +space & axe::r_double(d);
auto lib_t_rule = *space & "lib_t" & +space & axe::r_unsigned(u);
auto string_rule = axe::r_any() - ''';
auto out_rule = *space & "out" & +space & ''' & string_rule >> str & ''';

auto input_rule = +(a1_rule | lib_t_rule | out_rule) & *space & axe::r_end();
input_rule(input.begin(), input.end());

Notice that I cheated in the last rule, it's actually more permissive. If input string can be incorrect and validation is required, then you can write a longer rule using conjunction and disjunction operators, enumerating all legal possibilities. Also, you need to decide what the actual definitions of space and string_rule are. It's typical to define space as ' ' or '\t'. The string_rule in this example permits any character, except '''. You might want to make it more restrictive. And it also worth mentioning that this parser will work with any other input container, not just string. It will also parse wide character input, the only change required is to define str correspondingly as std::wstring str;

2
  • I'm not familiar with AXE, but it kinda looks like you forgot to qualify r_unsigned(u) with axe:: Commented Sep 15, 2011 at 18:10
  • @Mooing Duck -- you are right, fixed that. Commented Sep 15, 2011 at 23:21

Not the answer you're looking for? Browse other questions tagged or ask your own question.