【问题标题】:How to tokenize string by delimiters?如何通过分隔符标记字符串?
【发布时间】:2015-02-05 22:19:54
【问题描述】:

我需要用分隔符标记字符串。

例如:

对于"One, Two Three,,, Four",我需要得到{"One", "Two", "Three", "Four"}

我正在尝试使用这个解决方案https://stackoverflow.com/a/55680/1034253

std::vector<std::string> strToArray(const std::string &str,
                                    const std::string &delimiters = " ,")
{
    boost::char_separator<char> sep(delimiters.c_str());
    boost::tokenizer<boost::char_separator<char>> tokens(str.c_str(), sep);

    std::vector<std::string> result;
    for (const auto &token: tokens) {
        result.push_back(token);
    }

    return result;
}

但我得到了错误:

boost-1_57\boost/tokenizer.hpp(62): 错误 C2228: '.begin' 的左边必须有类/结构/联合 类型是'const char *const'

【问题讨论】:

  • 该错误是否与您向我们展示的代码行之一有关?
  • 您链接到的解决方案不使用c_str()。我假设 boost 要求参数是以 STL 为中心的,即有一个 begin() 迭代器。
  • @DrewDormann 该错误是指 tokenizer.hpp: template tokenizer(const Container& c,const TokenizerFunc& f) : first_(c.begin()), last_(c.end() ), f_(f) { }
  • 作为@PaulMcKenzie,它需要std::string,而不是const char*

标签: c++ c++11 boost tokenize boost-tokenizer


【解决方案1】:

改变这个:

boost::tokenizer<boost::char_separator<char>> tokens(str.c_str(), sep);

到这里:

boost::tokenizer<boost::char_separator<char>> tokens(str, sep);

链接: http://www.boost.org/doc/libs/1_57_0/libs/tokenizer/tokenizer.htm

容器类型需要一个begin()函数,而一个const char*(这是c_str())返回的不满足这个要求。

【讨论】:

  • 我认为 boost::char_separator 需要char *
  • @Ufx - 好的。我从答案中删除了第一行。
【解决方案2】:

对于您描述的任务,Boost 的标记器可能是矫枉过正。

boost::split 是为这个确切的任务而写的。

std::vector<std::string> strToArray(const std::string &str,
                                    const std::string &delimiters = " ,")
{
    using namespace boost;
    std::vector<std::string> result;
    split( result, str, is_any_of(delimiters), token_compress_on );
    return result;
}

可选的token_compress_on 表示您的,,, 输入不应在这些逗号之间暗示空字符串标记

【讨论】:

  • 我见过这个解决方案。当达到某个大小时,我可以停止添加令牌吗?
  • @Ufx 一次性完成,所以如果你想要返回向量的最大尺寸,你可以在返回之前调整它的大小。
【解决方案3】:

捷径。

string tmp = "One, Two, Tree, Four";
int pos = 0;
while (pos = tmp.find(", ") and pos > 0){
    string s = tmp.substr(0, pos);
    tmp = tmp.substr(pos+2);
    cout << s;
}

【讨论】:

    【解决方案4】:

    我看到很多boost 的答案,所以我想我会提供一个非boost 的答案:

    template <typename OutputIter>
    void Str2Arr( const std::string &str, const std::string &delim, int start, bool ignoreEmpty, OutputIter iter )
    {
        int pos = str.find_first_of( delim, start );
        if (pos != std::string::npos) {
            std::string nStr = str.substr( start, pos - start );
            trim( nStr );
    
            if (!nStr.empty() || !ignoreEmpty)
                *iter++ = nStr;
            Str2Arr( str, delim, pos + 1, ignoreEmpty, iter );
        }
        else
        {
            std::string nStr = str.substr( start, str.length() - start );
            trim( nStr );
    
            if (!nStr.empty() || !ignoreEmpty)
              *iter++ = nStr;
        }
    }
    
    std::vector<std::string> Str2Arr( const std::string &str, const std::string &delim )
    {
        std::vector<std::string> result;
        Str2Arr( str, delim, 0, true, std::back_inserter( result ) );
        return std::move( result );
    }
    

    trim 可以是任何修剪功能,我使用了this SO answer。它利用std::back_inserter 和递归。您可以轻松地循环执行此操作,但这听起来更有趣:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-03
      • 1970-01-01
      • 1970-01-01
      • 2012-07-31
      • 2014-03-02
      • 2015-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多