2017-08-14 59 views
0

我想對我使用的特殊協議的字符串執行運行長度壓縮。當運行大小或字符串中的特定字符> = 3時,運行被認爲是有效的。有人可以幫助我實現這一目標嗎?我有live demo on coliru。我非常肯定這可以用標準庫的std::adjacent_findstd::not_equal_to<>作爲搜索運行邊界的二元謂詞,並且一旦找到邊界可能使用std::equal_to<>。以下是我有這麼遠,但我有結果麻煩:使用stl來運行長度使用std :: adjacent_find編碼一個字符串

給出一個包含運行或空格等字符下面輸入的文本字符串(在這種情況下運行的字母「S」的:

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

我想上述文本字符串轉換成包含是純的> 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,--, 

編輯:我修正了以前的代碼使這個版本更接近最終的解決方案。具體而言,我添加了運行大小的明確測試,將其包括在內。我似乎不過是具有邊界的情況下的問題 - 所有的空間情況與字符串末尾的幾個空格結束的情況下:

#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; 
} 
+0

why not_equal_to <>()(* adjIter,* next)而不是* adjIter!= * next? –

+0

我沒有什麼區別,它與解決我的算法缺點無關。 – johnco3

回答

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

這應該是if (next.length() <= 2)。如果長度爲12,則需要爲當前標記添加相同字符的運行。

我似乎不過是具有邊界的情況下的問題 - 所有的空間 情況與字符串末尾的幾個空格

stringWithoutRun不是循環結束後,空結束的情況下,累積在其中的字符不會被添加到令牌數組中。你可以這樣修復:

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