【问题标题】:Efficient parsing of std::stringstream data into std::vector<std::vector<double>>将 std::stringstream 数据高效解析为 std::vector<std::vector<double>>
【发布时间】:2014-02-17 09:09:49
【问题描述】:

我正在将双精度值对的数据流解析为 std::vector>。我使用 boost 因为我认为它更有效。我的代码如下。

                std::stringstream tmp_stream;                
                typedef double data_type;            
                typedef ::std::vector < data_type > V_d;
                // type below describes type of the container of all data
                typedef ::std::vector < V_d > V_v_d;
                // list container 
                //typedef ::std::list < V_d > V_v_d;

                V_v_d data;

                ::data_parser::Data_parser < V_v_d > data_parser;
                data_parser ( tmp_stream, data );

我的输入文本文件被格式化为 { (132.181,0.683431), (136.886,0.988517), (137.316,0.504297), (133.653,0.602269), (150.86,0.236839) } 这些对没有正确解析,我收到了空对。可能是什么问题呢? 谢谢

【问题讨论】:

  • 您将不得不向我们展示您的 data_parser 代码。
  • 为什么不使用 std::pair
  • 不确定它是否与问题有关,但如果您总是使用成对的双打,使用std::vector&lt;std::pair&lt;double,double&gt; &gt; 进行存储可能会更有效。
  • 不确定是什么代码在执行字符串 -> 浮点转换,但如果您使用的是 Intel,我建议您使用 Intel Numeric String Conversion 库:software.intel.com/en-us/node/485147
  • 您是否跳过了所有其他内容,例如(,{})?如果您使用istringstream 并尝试将这些字符提取到double 中,可能会发生奇怪的事情。另外,按照之前评论者的建议进行操作,并使用std::pair 来存储对。

标签: c++ boost stl


【解决方案1】:

使用一点Boost Spirit,就可以使用一行:

if (tmp_stream >> std::noskipws >> 
       qi::phrase_match((+qi::double_) % qi::eol, qi::blank, data))
{

另外一行显示结果作为奖励:

    std::cout << karma::format((karma::double_ % ", ") % karma::eol, data) << "\n";
}

注意它处理inf-infnan :)

看到它Live on Coliru

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi_match.hpp>

namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;

int main()
{
    std::vector<std::vector<double>> data;

    std::stringstream tmp_stream(
            "123 45 inf -inf nan .7e-99\n"
            "42\n"
            "-1");

    if (tmp_stream >> std::noskipws >> qi::phrase_match((+qi::double_) % qi::eol, qi::blank, data))
    {
        std::cout << karma::format((karma::double_ % ", ") % karma::eol, data) << "\n";
    }
}

更新稍微适应您的输入语法,我建议改为解析成对的向量:

#include <boost/fusion/adapted/std_pair.hpp> // handle std::pair
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi_match.hpp>

namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;

int main()
{
    std::vector<std::pair<double, double>> data;

    std::stringstream tmp_stream("{ (132.181,0.683431), (136.886,0.988517), (137.316,0.504297), (133.653,0.602269), (150.86,0.236839) }");

    if (tmp_stream >> std::noskipws >> qi::phrase_match(
                   '{' 
                >> 
                     ( '(' >> qi::double_ >> "," >> qi::double_ >> ')' )
                     % ','
                >> '}',
                qi::space, data))
    {
        std::cout << karma::format(karma::delimit(" ") [karma::auto_] % karma::eol, data) << "\n";
    }
}

哪些打印:(请参阅Live On Coliru

132.181 0.683 
136.886 0.989 
137.316 0.504 
133.653 0.602 
150.86 0.237 

注意为了让事情变得更快,请考虑不要从流中解析,而是使用

  • streambuf_iterator
  • 如果你在内存中有底层字节数据

【讨论】:

猜你喜欢
  • 2020-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-20
  • 2020-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多