C ++ / Boost:编写更强大的sscanf替代品

时间:2011-02-17 22:04:24

标签: c++ boost boost-spirit boost-regex boost-spirit-qi

我想用C ++编写一个函数来替换C的sscanf,它将匹配分配给迭代器。

基本上,我想要这样的东西:

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]);

确切的细节可能会有所不同,但你明白了。有任何实施的想法吗?

到目前为止的选项以及目前的问题:

  • std :: istringstream :没有用于匹配常量表达式的操纵器
  • Boost.Regex :不确定这是否有效,而且似乎要比此更复杂
  • Boost.Spirit :不要认为这会对动态生成的格式字符串起作用,而且看起来似乎也更复杂
  • sscanf :它可以工作,但是非标准等,并且使用它会需要很多开销,因为参数的数量是在编译时确定的

2 个答案:

答案 0 :(得分:2)

如果在编译时确定了格式字符串,则会写入一些variadic-template printf替换。倒置那些应该合理地工作。

然后你可以使用istream的&gt;&gt;用于读取的运算符或c-stdlib函数。

答案 1 :(得分:2)

那是什么?

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's not a %, eat!
      str.erase(0, str.find(*i)+1);
      ++i;
    }
  }
}

缺少某些转换说明符 - 但主要是它有效。