C++ 提升标记器但保留分隔符

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

也许这很容易,但我自己找不到答案

我想使用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.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