boost::spirit::x3 phrase_parse 在进入 Vector 之前进行算术运算
boost::spirit::x3 phrase_parse doing arithmetic operations before pushing into vector
我正在为我的大学研究做一个项目。我的目标是将大文件(2,6 GB(中的双精度数读取为双精度向量。
我正在使用带有 mmap 的提升精神 x3 库。我在网络上找到了一些代码:我正在使用的 https://github.com/sehe/bench_float_parsing。
在将这些双精度值推入向量之前,我想对这些值进行一些算术运算。所以我被困在这里。如何在推送值之前执行一些工件操作以加倍值?
template <typename source_it>
size_t x3_phrase_parse<data::float_vector, source_it>::parse(source_it f, source_it l, data::float_vector& data) const {
using namespace x3;
bool ok = phrase_parse(f, l, *double_ % eol, space, data);
if (ok)
std::cout << "parse successn";
else
std::cerr << "parse failed: '" << std::string(f, l) << "'n";
if (f != l) std::cerr << "trailing unparsed: '" << std::string(f, l) << "'n";
std::cout << "data.size(): " << data.size() << "n";
return data.size();
}
很
抱歉没有完全回答你的问题。但提升精神不是合适的工具。Spirit是一个解析器生成器(作为一个子集当然也是词法分析(。因此,在乔姆斯基语言等级制度中,有一个层次到很高。您不需要解析器,而是需要正则表达式:std:regex
使用正则表达式可以轻松找到双精度。在附加的代码中,我为双打创建了一个简单的模式。正则表达式可用于搜索它。
因此,我们将从 istream 读取(可以是文件、字符串流、控制台输入或其他任何内容(。我们将逐行读取,直到整个输入被消耗掉。
对于每一行,我们将检查输入是否与预期模式匹配,是否为 1 双精度。
然后我们读取这个双精度,做一些计算,然后将其推入向量。
请参阅以下非常简单的代码。
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <regex>
std::istringstream input{R"(0.0
1.5
2.0
3.0
4.0
-5.0
)"};
using VectorDouble = std::vector<double>;
const std::regex reDouble{R"(([-+]?[0-9]*.?[0-9]*))"};
std::istream& get(std::istream& is, VectorDouble& dd)
{
// Reset vector to empty before reading
dd.clear();
//Read all data from istream
std::string line{};
while (getline(is, line)) {
// Search for 2 doubles
std::smatch sm;
if (std::regex_search(line, sm, reDouble)) {
// Convert found strings to double
double d1{std::stod(sm[1])};
// Do some calculations
d1 = d1 + 10.0;
// Push back into vector
dd.emplace_back(d1);
}
else
std::cerr << "Error found in line: " << line << "n";
}
return is;
}
int main()
{
// Define vector and fill it
VectorDouble dd{};
(void)get(input, dd);
// Some debug output
for (double& d : dd) {
std::cout << d << "n";
}
return 0;
}
为什么不使用语义操作来执行算术运算?
在下面的代码中:
#include <iostream>
#include <sstream>
#include <string>
#include <cstdio>
#include <vector>
using VectorDouble = std::vector<double>;
void show( VectorDouble const& dd)
{
std::cout<<"vector result=n";
for (double const& d : dd) {
std::cout << d << "n";
}
}
auto arith_ops=[](double&x){ x+=10.0;};
std::string input_err_yes{R"(0.0
1.5
2.0xxx
not double
4.0
-5.0
)"};
std::string input_err_not{R"(0.0
1.5
2.0
3.0
4.0
-5.0
)"};
void stod_error_recov(std::string const&input)
//Use this for graceful error recovery in case input has syntax errors.
{
std::cout<<__func__<<":n";
VectorDouble dd;
std::istringstream is(input);
std::string line{};
while (getline(is, line) ) {
try {
std::size_t eod;
double d1(std::stod(line,&eod));
arith_ops(d1);
dd.emplace_back(d1);
auto const eol=line.size();
if(eod!=eol) {
std::cerr << "Warning: trailing chars after double in line: "<< line << "n";
}
}
catch (const std::invalid_argument&) {
if(!is.eof())
std::cerr << "Error: found in line: " << line << "n";
}
}
show(dd);
}
void stod_error_break(std::string const&input)
//Use this if input is sure to have correct syntax.
{
std::cout<<__func__<<":n";
VectorDouble dd;
char const*d=input.data();
while(true) {
try {
std::size_t eod;
double d1(std::stod(d,&eod));
d+=eod;
arith_ops(d1);
dd.emplace_back(d1);
}
catch (const std::invalid_argument&) {
//Either syntax error
//Or end of input.
break;
}
}
show(dd);
}
#include <boost/spirit/home/x3.hpp>
void x3_error_break(std::string const&input)
//boost::spirit::x3 method.
{
std::cout<<__func__<<":n";
VectorDouble dd;
auto f=input.begin();
auto l=input.end();
using namespace boost::spirit::x3;
auto arith_action=[](auto&ctx)
{ arith_ops(_attr(ctx));
};
phrase_parse(f, l, double_[arith_action] % eol, blank, dd);
show(dd);
}
int main()
{
//stod_error_recov(input_err_yes);
//stod_error_break(input_err_not);
x3_error_break(input_err_not);
return 0;
}
与Armin不同,stod_*功能不需要regex
因为std:stod 进行解析,因为它没有使用regex
它可能会运行得更快一些。
有 2 个 stod_* 函数显示在源代码注释中指示应使用哪个。
为了完整起见,使用 boost::spirit::x3 的 3ird 函数是显示。 恕我直言,它的可读性比其他的更好;然而编译可能需要更多时间。
相关文章:
- 算术运算的结果类似于:C浮点变量中的1/3
- 更快的C++算术运算
- 为什么循环体中的一个基本算术运算执行得比两个算术运算慢
- 为什么对无符号字符进行算术运算会将它们提升为有符号整数
- 如何在 C++ 中计算字符串的算术运算
- 复数的算术运算
- 具有非常非常大数字的算术运算
- 如何使用C++中的处理器指令来实现快速算术运算
- boost::spirit::x3 phrase_parse 在进入 Vector 之前进行算术运算
- C++中混合数据类型的算术运算
- C++:编译器是否优化整数 + 浮点算术运算?
- 如何在特征中对二维数组的列执行简单的算术运算
- 使用数字列表和算术运算获取目标数字
- C++:“enable_if”用于限制支持特定算术运算的类型
- 如何正确避免 SIGFPE 和算术运算溢出
- 编译器用于编译 128 位整数的基本算术运算的技巧
- 将临时值存储为某种数据类型时,算术运算的标准规则是什么
- 相同的算术运算在 C++ 和 Python 中给出不同的结果
- 带有空的算术运算
- 算术运算和编译器优化