c++ - 如何用转义空格分割句子?

标签 c++ boost split whitespace delimiter

我想使用空格作为我的分隔符来分割我的句子,但转义的空格除外。使用 boost::split 和正则表达式,如何拆分它?如果不可能,还有什么办法?

例子:

std::string sentence = "My dog Fluffy\\ Cake likes to jump";

结果:
我的

蓬松\蛋糕
喜欢

跳跃

最佳答案

三种实现方式:

  1. 拥有 boost spirit
  2. 使用 Boost 正则表达式
  3. 手写解析器

boost spirit

以下是我如何使用 Boost Spirit 执行此操作。这似乎有些过分,但经验告诉我,一旦您拆分输入文本,您可能需要更多的解析逻辑。

当您从“仅拆分标记”扩展到具有生产规则的真实语法时,Boost Spirit 会大放异彩。

Live On Coliru

#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;

int main() {
    std::string const sentence = "My dog Fluffy\\ Cake likes to jump";
    using It = std::string::const_iterator;
    It f = sentence.begin(), l = sentence.end();

    std::vector<std::string> words;

    bool ok = qi::phrase_parse(f, l,
            *qi::lexeme [ +('\\' >> qi::char_ | qi::graph) ], // words
            qi::space - "\\ ", // skipper
            words);

    if (ok) {
        std::cout << "Parsed:\n";
        for (auto& w : words)
            std::cout << "\t'" << w << "'\n";
    } else {
        std::cout << "Parse failed\n";
    }

    if (f != l)
        std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}

使用 Boost 正则表达式

这看起来很简洁但是

Live On Coliru

#include <iostream>
#include <boost/regex.hpp>
#include <boost/algorithm/string_regex.hpp>
#include <vector>

int main() {
    std::string const sentence = "My dog Fluffy\\ Cake likes to jump";

    std::vector<std::string> words;
    boost::algorithm::split_regex(words, sentence, boost::regex("(?<!\\\\)\\s"), boost::match_default);

    for (auto& w : words)
        std::cout << " '" << w << "'\n";
}

Using c++11 raw literals you could write the regular expression slightly less obscurely: boost::regex(R"((?<!\\)\s)"), meaning "any whitespace not following a backslash"

手写解析器

这有点乏味,但是像 Spirit 语法一样是完全通用的,并且性能不错。

但是,一旦您开始向语法添加复杂性,它就不会像 Spirit 方法那样优雅地扩展。一个优点是与 Spirit 版本相比,您编译代码所花费的时间更少。

Live On Coliru

#include <iostream>
#include <iterator>
#include <vector>

template <typename It, typename Out>
Out tokens(It f, It l, Out out) {
    std::string accum;
    auto flush = [&] { 
        if (!accum.empty()) {
            *out++ = accum;
            accum.resize(0);
        }
    };

    while (f!=l) {
        switch(*f) {
            case '\\': 
                if (++f!=l && *f==' ')
                    accum += ' ';
                else
                    accum += '\\';
                break;
            case ' ': case '\t': case '\r': case '\n':
                ++f;
                flush();
                break;
            default:
                accum += *f++;
        }
    }
    flush();
    return out;
}

int main() {
    std::string const sentence = "My dog Fluffy\\ Cake likes to jump";

    std::vector<std::string> words;

    tokens(sentence.begin(), sentence.end(), back_inserter(words));

    for (auto& w : words)
        std::cout << "\t'" << w << "'\n";
}

关于c++ - 如何用转义空格分割句子?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29380897/

相关文章:

c++ - 具有不完整值类型的映射

c++ - 仅调用一次构造函数的数组初始化

c++ - vector 派生类的复制构造函数

c++ - QPushButton 文字的阴影效果

c++ - Division_Euclidean_space.h 错误 : ‘vertex_t’ is not a type

c++ - 已定义构造函数的无法识别的构造函数

file - hadoop 拆分文件大小相等

python - 链接 boost::python::numpy 时出现问题

r - 使用 dplyr 为每组应用 ggplot 函数并为每组设置标题

python - Pandas 按列值拆分 DataFrame