C ++ / Boost: writing a more powerful sscanf replacement

I want to write a function in C ++ to replace C sscanf, which assigns matches to an iterator.

Basically, I need something like:

string s = "0.5 6 hello"; std::vector<boost::any> any_vector; sscanv(s, "%f %i %s", any_vector); cout << "float: " << any_cast<float>(any_vector[0]); cout << "integer: " << any_cast<integer(any_vector[1]); cout << "string: " << any_cast<string>(any_vector[2]); 

The exact details may vary, but you get this idea. Any ideas for implementation?

Options so far along with problems:

  • std :: istringstream : no manipulator for matching constant expressions
  • Boost.Regex : not sure if this will work, and it seems a lot more complicated than necessary
  • Boost.Spirit : don't think this will work for dynamically generated format strings, and it also seems more complicated than necessary
  • sscanf : it will work, but it is non-standard, etc., and it will take a lot of overhead to use, since the number of arguments is determined at compile time
+7
source share
2 answers

How about this?

 void sscanf(std::string str, const std::string& format, std::vector<boost::any>& result) { std::string::const_iterator i = format.begin(); while (i != format.end()) { if (*i == '%') { ++i; // now *i is the conversion specifier char specifier = *i; ++i; // now *i is the next seperator std::string extract = str.substr(0, str.find(*i)); switch (specifier) { // matching an integer case 'i': result.push_back(boost::lexical_cast<int>(extract)); break; // matching a floating point number case 'a': case 'e': case 'f': case 'g': result.push_back(boost::lexical_cast<float>(extract)); break; // matching a single character case 'c': result.push_back(boost::lexical_cast<char>(extract)); break; // matching a string case 's': result.push_back(extract); break; // Invalid conversion specifier, throwing an exception default: throw std::runtime_error("invalid conversion specifier"); break; } } else { // if it not a %, eat! str.erase(0, str.find(*i)+1); ++i; } } } 

Some conversion specifiers are missing, but mostly it works.

+2
source

If your format string is defined at compile time, there are some varadic-template printf . Inverting should work quite well.

Then you can use the istream → operator to read or the c-stdlib function.

+2
source

All Articles