使用stl运行长度使用std :: adjacent_find

时间:2017-08-14 01:57:30

标签: algorithm c++11 stl-algorithm

我正在尝试对字符串执行运行长度压缩以获取我正在使用的特殊协议。当字符串中的运行大小或特定字符>> 3时,运行被认为是有效的。有人可以帮助我实现这一目标。我有 live demo on coliru 。我很确定这可以通过标准库std::adjacent_findstd::not_equal_to<>组合作为二进制谓词来搜索运行边界,并且可能在我找到后使用std::equal_to<>边界。以下是我到目前为止所得到的结果:

给出以下输入文本字符串,其中包含运行或空格和其他字符(在这种情况下是字母的运行&#39;:

"---thisssss---is-a---tesst--"

我正在尝试将上面的文本字符串转换为包含纯粹运行&gt;元素的向量。 2个字符或混合字符。结果几乎是正确但不完全,我无法发现错误。

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
expected the following
======================
---,thi,sssss,---,is-a,---,tesst--,
actual results
==============
---,thi,sssss,---,is-a,---,te,ss,--,

编辑:我修复了以前的代码,使这个版本更接近最终解决方案。具体来说,我将运行大小的显式测试添加为&gt; 2包括在内。我似乎遇到了边界案例问题 - 所有空格案例以及字符串结尾在几个空格中结束的情况:

#include <iterator>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>

int main()
{
    // I want to convert this string containing adjacent runs of characters
    std::string testString("---thisssss---is-a---tesst--");

    // to the following 
    std::vector<std::string> idealResults = {
        "---", "thi", "sssss",
        "---", "is-a",
        "---", "tesst--"
    };

    std::vector<std::string> tokenizedStrings;
    auto adjIter = testString.begin();
    auto lastIter = adjIter;
    // temporary string used to accumulate characters that 
    // are not part of a run.
    std::unique_ptr<std::string> stringWithoutRun;
    while ((adjIter = std::adjacent_find(
        adjIter, testString.end(), std::not_equal_to<>())) !=
        testString.end()) {
        auto next = std::string(lastIter, adjIter + 1);
        // append to foo if < run threshold
        if (next.length() < 2) {
            if (!stringWithoutRun) {
                stringWithoutRun = std::make_unique<std::string>();
            }
            *stringWithoutRun += next;
        } else {
            // if we have encountered non run characters, save them first
            if (stringWithoutRun) {
                tokenizedStrings.push_back(*stringWithoutRun);
                stringWithoutRun.reset();
            }
            tokenizedStrings.push_back(next);
        }
        lastIter = adjIter + 1;
        adjIter = adjIter + 1;
    }
    tokenizedStrings.push_back(std::string(lastIter, adjIter));

    std::cout << "expected the following" << std::endl;
    std::cout << "======================" << std::endl;
    std::copy(idealResults.begin(), idealResults.end(), std::ostream_iterator<std::string>(std::cout, ","));
    std::cout << std::endl;

    std::cout << "actual results" << std::endl;
    std::cout << "==============" << std::endl;
    std::copy(tokenizedStrings.begin(), tokenizedStrings.end(), std::ostream_iterator<std::string>(std::cout, ","));
    std::cout << std::endl;
}

1 个答案:

答案 0 :(得分:1)

if (next.length() < 2) {
    if (!stringWithoutRun) {
        stringWithoutRun = std::make_unique<std::string>();
    }
    *stringWithoutRun += next;
}

这应该是if (next.length() <= 2)。如果长度为12,则需要向当前令牌添加一系列相同的字符。

  

我似乎遇到了边界案例问题 - 所有空格   case和字符串结尾以几个空格结束的情况

循环结束后stringWithoutRun不为空时,其中累积的字符不会添加到标记数组中。你可以像这样解决它:

// The loop has finished
if (stringWithoutRun)
    tokenizedStrings.push_back(*stringWithoutRun);
tokenizedStrings.push_back(std::string(lastIter, adjIter));