解析具有提升精神的简单 csv 表
Parsing simple csv table with boost-spirit
我试图使用boost-spirit
来解析一个相当简单的cvs文件格式。
我的csv文件看起来像这样:
测试.txt
2
5. 3. 2.
6. 3. 6.
第一个整数表示要读取的行数,每行正好由三个双精度值组成。
这就是我到目前为止得到的。
主.cpp
#include <vector>
#include <fstream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/phoenix/object/construct.hpp>
std::vector<std::vector<double>> parseFile(std::string& content)
{
std::vector<std::vector<double>> ret;
using namespace boost::phoenix;
using namespace boost::spirit::qi;
using ascii::space;
int no;
phrase_parse(content.begin(), content.end(),
int_[ref(no) = _1] >> repeat(ref(no))[(double_ >> double_ >> double_)[
std::cout << _1 << _2 << _3
]], space
);
return ret;
}
int main(int arg, char **args) {
auto ifs = std::ifstream("Test.txt");
std::string content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
parseFile(content);
}
现在,我需要的不是行std::cout << _1 << _2 << _3
,而是附加包含三个值的std::vector<double>
的东西。
我已经尝试过_val=construct<std::vector<double>>({_1,_2,_3})
,但它不起作用。那我做错了什么?
它比您想象的要简单得多¹
std::vector<std::vector<double>> parseFile(std::string const& content) {
namespace px = boost::phoenix;
using namespace boost::spirit::qi;
int no;
std::vector<std::vector<double>> data;
bool ok = phrase_parse(content.begin(), content.end(),
int_ [ px::ref(no) = _1 ] >> eol
>> repeat(px::ref(no)) [ repeat(3) [double_] >> (eol|eoi)],
blank,
data
);
if (!ok)
throw std::runtime_error("Parse failure");
return data;
}
在科利鲁上观看直播。它使用自动属性传播 - Spirit最有用的功能开始 - 和blank
船长而不是space
,所以我们仍然可以解析eol
现在,我建议让它更简单:
住在科里鲁
bool ok = phrase_parse(
content.begin(), content.end(),
int_ >> eol >> *(+double_ >> (eol|eoi)) >> *eol >> eoi,
blank,
no, data
);
if (!ok && (no == data.size()))
throw std::runtime_error("Parse failure");
或者,事实上,仅使用标准库甚至更简单:
住在科里鲁
#include <vector>
#include <iostream>
#include <fstream>
#include <iterator>
std::vector<std::vector<double>> parseFile(std::string const& fname) {
std::vector<std::vector<double>> data;
auto ifs = std::ifstream(fname);
size_t no = -1;
if (ifs >> no && ifs.ignore(1024, 'n')) {
double a, b, c;
while (ifs >> a >> b >> c)
data.push_back({a, b, c});
}
if (!(ifs.eof() && (no == data.size())))
throw std::runtime_error("Parse failure");
return data;
}
int main() {
for (auto& row : parseFile("input.txt"))
std::copy(row.begin(), row.end(), std::ostream_iterator<double>(std::cout << "n", " "));
}
它们都成功地解析和打印:
5 3 2
6 3 6
¹ 提升精神:"语义行为是邪恶的"?
奖励:自动自定义属性类型
而不是不透明的向量,为什么不使用这样的结构
struct Point {
double x,y,z;
};
并解析为std::vector<Point>
.作为奖励,您基本上免费获得输出和解析器:
BOOST_FUSION_ADAPT_STRUCT(Point, x, y, z)
// parser:
auto_ >> eol >> *(auto_ >> (+eol|eoi)) >> eoi,
在科里鲁现场观看
相关文章:
- 在c++中用vector填充一个简单的动态数组
- (C++)分析树以计算返回错误值的简单算术表达式
- 我的简单if-else语句是如何无法访问的代码
- 正在将csv文件读取为双精度矢量
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 一种在C++中读取TXT配置文件的简单方法
- 关于简单C++函数(is_palindrome)的逻辑的问题
- 显示错误输出的简单数组排序程序
- 当无法使用模板和宏时,生成类型变体C++代码的最简单方法是什么?
- 退出简单while循环时出现问题
- 为什么简单的算术减法在"if"条件下不起作用?
- C++-字符串是否包含一个带有简单循环的单词
- 关于 c++ 函数中指针赋值的简单问题
- 如何选择在 csv 文件中输出的位置
- 从函数返回任意简单类型的数据
- 如何在没有函数的情况下编写此代码并使C++更简单?
- 有没有办法简单地从 GPU 调用多个 cpp 输出文件?
- 解析具有提升精神的简单 csv 表
- 读取映射到内存的CSV文件的最简单方法