C++ 提升标记器但保留分隔符
也许这很容易,但我自己找不到答案 我想使用boost::tokenizer,但将分隔符保留在字符串中 我的字符串是一组像这样的数字C++ 提升标记器但保留分隔符,c++,boost,tokenize,C++,Boost,Tokenize,也许这很容易,但我自己找不到答案 我想使用boost::tokenizer,但将分隔符保留在字符串中 我的字符串是一组像这样的数字 "1.00299 344.2221-25.112-33112" 结果应该是: "1.00299" "344.2221" "-25.112" "-33112" 我知道这看起来有点奇怪,但文件就是这样写的 另一个问题有点复杂,因为有些字符串如下所示: "1.00299E+45 344.22E-21-25.112E+11-3.31E-12" 应该是: "1.0
"1.00299 344.2221-25.112-33112"
结果应该是:
"1.00299" "344.2221" "-25.112" "-33112"
我知道这看起来有点奇怪,但文件就是这样写的
另一个问题有点复杂,因为有些字符串如下所示:
"1.00299E+45 344.22E-21-25.112E+11-3.31E-12"
应该是:
"1.00299E+45" "344.22E-21" "-25.112E+11" "-3.31E-12"`
任何帮助都将不胜感激
问候
Julia一般来说,令牌化者会丢弃令牌,而您所指定的问题看起来比令牌化者所能处理的要复杂一些。有时您希望在+或-,但前提是它不在“E”之后。这并不是你可以很容易地向一个通用标记器解释的逻辑
你可能应该考虑编写一个方法来解析字符串本身。您甚至可以在“”上拆分标记器,然后解析子字符串以处理其他情况
如果您可以控制输入数据,则最好在值之间强制使用空格,并在“”上拆分。通常,标记化器会丢弃标记,并且您指定的问题看起来比标记化器可以处理的问题要复杂一些。有时您希望在+或-,但前提是它不在“E”之后。这并不是你可以很容易地向一个通用标记器解释的逻辑
你可能应该考虑编写一个方法来解析字符串本身。您甚至可以在“”上拆分标记器,然后解析子字符串以处理其他情况
如果您可以控制输入数据,则最好在值之间强制使用空格,并在“”上拆分。假定您需要将这些值作为双精度值读取,则可以使用以下命令在3行中执行此操作: 或者也可以使用标准流:
std::vector<double> parse(std::istream & in)
{
/** Assuming default flags for *in* */
std::vector<double> d;
for (double v; in >> v; )
d.push_back(v);
return d;
}
假设您需要将这些值读取为双倍值,您可以在3行中使用: 或者也可以使用标准流:
std::vector<double> parse(std::istream & in)
{
/** Assuming default flags for *in* */
std::vector<double> d;
for (double v; in >> v; )
d.push_back(v);
return d;
}
让我们实现一个requote操纵器,它允许您执行以下操作:
#include "requote.hpp"
#include <iostream>
int main() {
std::cout << requote(std::cin);
}
注意:我们使用相同的streambuf实例化私有的istream,因此流状态是隔离的
所有的魔法都在召唤中。下面是我如何使用Boost Spirit实现这一点的。复制的复杂性在于确保
我们不会改变输入表示精度的任何部分,除了引用之外的格式
它尽可能地高效,我们不构造任何临时字符串,异常用于解析异常
让我们实现一个requote操纵器,它允许您执行以下操作:
#include "requote.hpp"
#include <iostream>
int main() {
std::cout << requote(std::cin);
}
注意:我们使用相同的streambuf实例化私有的istream,因此流状态是隔离的
所有的魔法都在召唤中。下面是我如何使用Boost Spirit实现这一点的。复制的复杂性在于确保
我们不会改变输入表示精度的任何部分,除了引用之外的格式
它尽可能地高效,我们不构造任何临时字符串,异常用于解析异常
有人让我注意到,你可能并不真的想要那里的引用 如果您只想以完全逼真的方式解析数字,请执行以下操作:
⑨您可以使用长双精度或qi::real_解析器来选择任意精度/十进制数类型;请参见,例如,有人提请我注意,您可能实际上并不需要引用 如果您只想以完全逼真的方式解析数字,请执行以下操作: ⑨您可以使用长双精度或qi::real_解析器来选择任意精度/十进制数类型;见例
#include "requote.hpp"
namespace /*anon*/ {
struct copy_out {
mutable std::ostreambuf_iterator<char> out;
//template <typename...> struct result { typedef void type; };
template <typename R> void operator()(R const& r) const {
*out++ = '"';
out = std::copy(r.begin(), r.end(), out);
*out++ = '"';
*out++ = ' ';
}
};
}
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
std::ostream& requote::call(std::ostream& os) const {
boost::phoenix::function<copy_out> copy_out_({os});
using namespace boost::spirit::qi;
boost::spirit::istream_iterator f(_is >> std::noskipws), l;
bool ok = phrase_parse(f,l,
*('"' > *raw[long_double][copy_out_(_1)] > '"') [boost::phoenix::ref(os)<<'\n'],
space
);
if (ok && f==l)
return os;
throw std::runtime_error("parse error at '" + std::string(f,l) + "'");
}
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
struct requote {
requote(std::istream& is) : _is(is.rdbuf()) {}
friend std::ostream& operator<<(std::ostream& os, requote const& manip) {
return manip.call(os);
}
private:
std::ostream& call(std::ostream& os) const {
boost::phoenix::function<copy_out> copy_out_({os});
using namespace boost::spirit::qi;
boost::spirit::istream_iterator f(_is >> std::noskipws), l;
bool ok = phrase_parse(f,l,
*('"' > *raw[long_double][copy_out_(_1)] > '"') [boost::phoenix::ref(os)<<'\n'],
space
);
if (ok && f==l)
return os;
throw std::runtime_error("parse error at '" + std::string(f,l) + "'");
}
struct copy_out {
mutable std::ostreambuf_iterator<char> out;
//template <typename...> struct result { typedef void type; };
template <typename R> void operator()(R const& r) const {
*out++ = '"';
out = std::copy(r.begin(), r.end(), out);
*out++ = '"';
*out++ = ' ';
}
};
mutable std::istream _is;
};
#include <iostream>
int main() {
std::cout << requote(std::cin);
}
"1.00299" "344.2221" "-25.112" "-33112"
"1.00299E+45" "344.22E-21" "-25.112E+11" "-3.31E-12"
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_match.hpp>
#include <iostream>
namespace qi = boost::spirit::qi;
int main() {
std::vector<double> values;
std::cin >> std::noskipws >> qi::phrase_match(*('"'>*qi::double_>'"'), qi::space, values);
for (auto d : values)
std::cout << d << "\n";
}
1.00299
344.222
-25.112
-33112
1.00299e+45
3.4422e-19
-2.5112e+12
-3.31e-12