【问题标题】:splitting a string but keeping empty tokens c++拆分字符串但保留空标记c ++
【发布时间】:2015-06-12 07:38:06
【问题描述】:

我正在尝试拆分字符串并将其放入向量中

但是,只要有连续的分隔符,我也想保留一个空标记:

例如:

string mystring = "::aa;;bb;cc;;c"

我想在 :; 上标记这个字符串分隔符 但在分隔符之间,例如 :: 和 ;; 我想在我的向量中推入一个空字符串;

so my desired output for this string is:

"" (empty)
aa
"" (empty)
bb
cc
"" (empty)
c

另外我的要求是不要使用 boost 库。

如果有的话可以给我一个想法。

谢谢

标记字符串但不包含空标记的代码

void Tokenize(const string& str,vector<string>& tokens, const string& delim)
{
       // Skip delimiters at beginning.
     string::size_type lastPos = str.find_first_not_of(delimiters, 0);
     // Find first "non-delimiter".
     string::size_type pos     = str.find_first_of(delimiters, lastPos);

while (string::npos != pos || string::npos != lastPos)
 {
    // Found a token, add it to the vector.
    tokens.push_back(str.substr(lastPos, pos - lastPos));
    // Skip delimiters.  Note the "not_of"
    lastPos = str.find_first_not_of(delimiters, pos);
    // Find next "non-delimiter"
    pos = str.find_first_of(delimiters, lastPos);
  }
}

【问题讨论】:

  • 你有没有尝试过?
  • 我尝试了上面的代码来标记我的字符串,但它只排除了空标记
  • 为什么不在tokens.push_back(str.substr(lastPos, pos - lastPos)); 之后添加tokens.push_back("");
  • 我猜这不可能,如果是不同的字符串呢?
  • 尝试用其他东西替换find_first_not_of(可能是简单的加1)。

标签: c++ tokenize


【解决方案1】:

您可以通过一些简单的更改使您的算法正常工作。首先,不要跳过开头的分隔符,然后不要跳过字符串中间的分隔符,只需将位置加一即可。此外,您的npos 检查应确保两个 位置都不是npos,所以它应该是&amp;&amp; 而不是||

void Tokenize(const string& str,vector<string>& tokens, const string& delimiters)
{
    // Start at the beginning
    string::size_type lastPos = 0;
    // Find position of the first delimiter
    string::size_type pos = str.find_first_of(delimiters, lastPos);

    // While we still have string to read
    while (string::npos != pos && string::npos != lastPos)
    {
        // Found a token, add it to the vector
        tokens.push_back(str.substr(lastPos, pos - lastPos));
        // Look at the next token instead of skipping delimiters
        lastPos = pos+1;
        // Find the position of the next delimiter
        pos = str.find_first_of(delimiters, lastPos);
    }

    // Push the last token
    tokens.push_back(str.substr(lastPos, pos - lastPos));
}

【讨论】:

  • "// Find next "non-delimiter" 没有描述pos = str.find_first_of(delimiters, lastPos); 做了什么,并且你没有在最后一个分隔符之后添加标记(或str 没有任何分隔符)。生成方法虽然是合理的。
  • 如果不为空,您是否应该在末尾添加tokens.push_back(str.substr(lastPos, pos - lastPos)); 以添加最后一个字符串?
  • 哇..太棒了..它工作..我怀疑||是我有无限循环的原因......我只有一个问题,当字符串的最后一个字符是分隔符时,这是否也有效?例如如果是 "::aa;;bb;cc;;c:" 最后一个标记应该是 "" 。
  • @XDProgrammer 是的,如果最后一个字符是分隔符,向量的末尾会有一个空字符串。
  • @TartanLIama 谢谢伙计,我还没有看到你在我发布之前添加的最后一个 push_back.. 它按预期工作.. 无论如何,我需要研究这段代码.. 因为我还不完全理解什么继续……我发现的所有类似主题都在使用 boost 库。当您使用该库时,它看起来确实很容易,但如果我只是使用它,我将无法理解.. 再次感谢
【解决方案2】:

我有一个使用迭代器的版本:

std::vector<std::string> split_from(const std::string& s
    , const std::string& d, unsigned r = 20)
{
    std::vector<std::string> v;
    v.reserve(r);

    auto pos = s.begin();
    auto end = pos;

    while(end != s.end())
    {
        end = std::find_first_of(pos, s.end(), d.begin(), d.end());
        v.emplace_back(pos, end);
        pos = end + 1;
    }

    return v;
}

使用您的界面:

void Tokenize(const std::string& s, std::vector<std::string>& tokens
    , const std::string& delims)
{
    auto pos = s.begin();
    auto end = pos;

    while(end != s.end())
    {
        end = std::find_first_of(pos, s.end(), delims.begin(), delims.end());
        tokens.emplace_back(pos, end);
        pos = end + 1;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多