【问题标题】:boost::split to split only if delimiter is present in c++boost::split 仅当 C++ 中存在分隔符时才拆分
【发布时间】:2021-03-26 19:22:25
【问题描述】:

我正在使用boost::split,但如果字符串没有分隔符,那么它将返回向量中的字符串。如果字符串中没有分隔符,我希望它不返回任何内容。

#include <iostream>
#include <string>
#include <bits/stdc++.h>
#include <boost/algorithm/string.hpp>
using namespace std;
  
int main()
{
    string input("abcd");
    vector<string> result;
    boost::split(result, input, boost::is_any_of("\t"));
  
    for (int i = 0; i < result.size(); i++)
        cout << result[i] << endl;
    return 0;
}

输出为 abcd。如果字符串中不存在分隔符,我希望向量为空。请提出建议。

【问题讨论】:

  • 您可以检查结果向量是否包含单个元素,如果是则清除它。

标签: c++ boost split c++14 delimiter


【解决方案1】:

看起来您可能需要一个验证解析器。正则表达式可能是一个很好的起点,但我建议使用解析器生成器,因为您很可能需要更多

我的水晶球悄悄说你可能正在解析命令行输出或 CSV/TSV 文件

这是你可以用 Boost Spirit X3 做的:

template <typename Cont>
bool parse_columns(std::string_view input, Cont& container,
                   unsigned required = 2) {
    namespace x3 = boost::spirit::x3;

    auto valid = [required](auto& ctx) {
        x3::_pass(ctx) = x3::_val(ctx).size() >= required;
    };

    auto delim = x3::char_('\t');
    auto field = *(~delim);
    auto rule
        = x3::rule<struct _, Cont, true>{"rule"} 
        = (field % delim)[valid];

    return parse(begin(input), end(input), rule, container);
}

这是一个带有测试用例的现场演示:

Live On Compiler Explorer

#include <boost/spirit/home/x3.hpp>
#include <fmt/ranges.h>

template <typename Cont>
bool parse_columns(std::string_view input, Cont& container,
                   unsigned required = 2) {
    namespace x3 = boost::spirit::x3;

    auto valid = [required](auto& ctx) {
        x3::_pass(ctx) = x3::_val(ctx).size() >= required;
    };

    auto delim = x3::char_('\t');
    auto field = *(~delim);
    auto rule
        = x3::rule<struct _, Cont, true>{"rule"} 
        = (field % delim)[valid];

    return parse(begin(input), end(input), rule, container);
}

int main() {
    for (auto input : {
             "",
             "\t",
             "abcd\t",
             "ab cd\tef",
             "\tef",
             "ab\tc\t\tdef",
             "abcd",
         }) {
        std::vector<std::string> columns;

        if (parse_columns(input, columns)) {
            fmt::print("'{}' -> {}\n", input, columns);
        } else {
            fmt::print("'{}' -> not matched\n", input);
        }
    }
}

打印

'' -> not matched
'   ' -> {"", ""}
'abcd   ' -> {"abcd", ""}
'ab cd  ef' -> {"ab cd", "ef"}
'   ef' -> {"", "ef"}
'ab c       def' -> {"ab", "c", "", "def"}
'abcd' -> not matched

调整

  • 要将重复的\t 视为单个分隔符,只需将field % delim 更改为field % +delim
  • 您可以轻松替换为另一个容器,例如std::set

Live On Compiler Explorer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-18
    • 2019-05-08
    • 1970-01-01
    • 2021-07-28
    • 2013-12-06
    相关资源
    最近更新 更多