C++/Boost:编写一个更强大的sscanf替代品 我想用C++编写一个函数来代替C的SCANF,它将匹配项分配给迭代器。

C++/Boost:编写一个更强大的sscanf替代品 我想用C++编写一个函数来代替C的SCANF,它将匹配项分配给迭代器。,c++,boost,boost-spirit,boost-regex,boost-spirit-qi,C++,Boost,Boost Spirit,Boost Regex,Boost Spirit Qi,基本上,我想要的是: 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

基本上,我想要的是:

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]);
string s=“0.5 6 hello”;
std::vector任意_向量;
sscanv(s,“%f%i%s”,任何向量);

cout如果您的格式字符串是在编译时确定的,则会编写一些替换。反转这些应该可以很好地工作

然后可以使用istream的>>运算符进行读取,或者使用c-stdlib函数

那是怎么回事

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;
    }
  }
}
void sscanf(std::string str,
const std::字符串和格式,
标准:向量和结果)
{
std::string::const_迭代器i=format.begin();
while(i!=format.end())
{
如果(*i='%'))
{
++i、 //现在*i是转换说明符
字符说明符=*i;
++i、 //现在*我是下一个分离者
std::string extract=str.substr(0,str.find(*i));
开关(说明符)
{
//匹配整数
案例“i”:
结果:推回(boost::词法转换(extract));
打破
//匹配浮点数
案例“a”:案例“e”:案例“f”:案例“g”:
结果:推回(boost::词法转换(extract));
打破
//匹配单个字符
案例“c”:
结果:推回(boost::词法转换(extract));
打破
//匹配字符串
案例s:
结果:推回(提取);
打破
//转换说明符无效,引发异常
违约:
抛出std::runtime_错误(“无效转换说明符”);
打破
}
}
其他的
{
//如果它不是一种食物,就吃吧!
str.erase(0,str.find(*i)+1);
++一,;
}
}
}

缺少一些转换说明符,但基本上是有效的

你愿意使用c++0x概念吗?@Bradley:我还以为这些概念已经从本标准草案中删除了呢?@Bradley:当然。我使用的是GCC4.5.1,并且使用-std=c++0x进行编译,所以只要它能够使用它,我就愿意使用它。但我不想等待尚未提供的东西。当然,即使它还不可用,我仍然对它感兴趣,但我现在需要一个解决方案。我想变量模板可能比向量模板更方便,尽管解析格式字符串仍然是最大的问题。@UncleBens:谢谢,我会研究这些,但你是对的,它们不能解决我的主要问题。这可能是最好的解决方案,但理想情况下,我更喜欢能够处理动态格式字符串的东西(即在运行时加载),但我认为只有在编译时指定格式时,这才有效,这与sscanf的限制基本相同。我明白了。那也不难。如果您的解析需求是基本的,我不明白为什么不能使用istream从缓冲区中读取int/float/string,然后将它们填充到任意向量中(或者如果您喜欢,将其存储在输出迭代器中)。Oth,如果您的格式字符串是动态的,那么向量的类型和长度也将是动态的,因此,您必须非常通用地处理那里的内容,但您的用例和其他代码可能与此匹配。(我有点好奇你想做什么…:)我说我的解析需求不仅仅是基本的,而不是高级的。我基本上想复制sscanf的功能,但要使其更具动态性。如果没有人有更好的建议,我可能最终会使用istream选项。谢谢。哦,没有看到你最后的评论。。。是的,我的向量也必须是动态的。用例需要它(至少要得到一个通用的解决方案)。我计划使用Boost。任何或可能基于这个概念制作我自己的版本,更好地满足我的需要。简言之,有很多不同格式的“文本文件”我想要解析,并从中创建趋势数据。我更喜欢编写和编译一次,然后使用配置文件添加对新文件格式的支持,而不是总是添加更多代码。谢谢,这看起来真的很好。在速度方面,你认为这与scanf相比如何?@deuberger lexical_cast、string::find、string::erase……可能相当昂贵——我认为这会慢得多