2015-05-10 49 views
13

我想將一個字符串分隔成多個字符串來製作一個自定義的終端。到目前爲止,我一直在使用strtok來分離控制信號,但是我不明白如何區分特定的角色實例。例如:在C++中分隔字符串

string input = "false || echo \"hello world\" | grep hello";

當試圖函數strtok這個input並嘗試使用|分離輸出將是:

falseecho "hello world"grep hello

相反,我想輸出到成爲:

false || echo "hello world"grep hello

我該如何讓strtok以不同的方式對待|||而不是說它們是相同的?

+1

「*我怎麼能有strtok的治療?|和||不同,而不是它說他們是一樣的*」 - 這是因爲'strtok'認爲每個字符在第二個參數是一個分隔符。而且,它不會返回空字符串。相關[1](http://stackoverflow.com/questions/29847915/implementing-strtok-whose-delimiter-has-more-than-one-character),[2](http://stackoverflow.com/questions/ 7079694/is-there-a-way-split-a-string-on-multiple-characters-in-c?lq = 1) –

回答

8
#include <iostream> 
#include <string> 
#include <algorithm> 
#include <vector> 
using namespace std; 

vector<string> split(string sentence,char delim) 
{ 
    string tempSentence = ""; 
    tempSentence += delim; 
    tempSentence += sentence; 
    tempSentence += delim; 

    string token; 
    vector<string> tokens; 
    for (int i=1;i<tempSentence.length()-1;++i) 
    { 
     if (tempSentence[i] == delim && tempSentence[i-1] != delim && tempSentence[i+1] != delim) 
     { 
      if (token.length()) tokens.push_back(token); 
      token.clear(); 
     } 
     else 
     { 
      token += tempSentence[i]; 
     } 
    } 
    if (token.length()) tokens.push_back(token); 

    return tokens; 
} 

int main() { 
    string sentence = "false || echo \"hello world\" | grep hello"; 
    char delim='|'; 

    vector<string> tokens = split(sentence,delim); 


    for_each(tokens.begin(), tokens.end(), [&](string t) { 
     cout << t << endl; 
    }); 

} 

難看又長!但工作!

+0

問題在用戶想要分隔字符串的情況下,如何更改代碼使用'||'來替代,因爲使用你的代碼是行不通的,因爲'char delim'只能是一個字符。 也謝謝你,因爲如果你正在尋找一個單一的分界,它的工作完美。 – divyanshch

+1

這很容易修復,只需用一個字符串替換即可。但是,使用多個可能的分隔符之一是一個不容易添加的功能。 –

1

strtok()將逐個字符地掃描字符,而不考慮它尋找的前後字符。如果你想更聰明的掃描,你需要自己實施額外的檢查。

由於strtok只是返回找到標記的字符串中的位置,您必須手動檢查要返回的標記的第一個字符以查看它是否也是「|」,然後相應地執行。

更好的解決方案是查看這裏使用正則表達式。這聽起來像你想要分裂的符號不僅僅是|,而是|被空間包圍 - 也就是說,你實際上是在三個字符符號(空間 - 管道空間)上搜索和分割

1

我想說你的問題的答案首先不是使用strtok(),的問題,甚至在手冊頁中都有記錄(至少在Linux上)。

其次,確保你有測試。使用測試驅動的開發對於這些任務來說是必須的,因爲這裏有幾個簡單的事情可能會相互影響,並且在一個地方修復錯誤會導致另一個錯誤。此外,還有一些工具(例如各種YACC變體和類似的生成器),允許您指定抽象語法,然後將此定義轉換爲C++代碼。我建議這些用於任何非平凡的任務。最後,如果你只是爲了好玩而學習,那麼編寫一個循環或一組函數來從字符串中提取各種令牌是一種好方法。

1
#include <iostream> 
#include <string> 
#include <algorithm> 

using namespace std; 

int main() { 
    string input = "false || echo \"hello world\" | grep hello"; 

    string::iterator itr; 

    itr = input.begin(); 

    do { 
     itr = search_n(itr, input.end(), 1, '|'); 

     if (itr < input.end() - 1) 
     { 
      if (*(itr + 1) == '|') 
      { 
       itr = itr + 2; 
       continue; 
      } 
     }   

     if (itr < input.end()) 
     { 
       *itr = ','; 
       itr ++; 
     } 

    } while (itr < input.end()); 

    cout << input << endl; 

    return 0; 
} 
1

一個相當簡單和直接的解決方案,似乎解決您的問題。

的的std :: string :: find()方法搜索第一次出現由它的參數指定的序列 (在這種情況下,字符串 '分隔符')的字符串。當指定pos時, 搜索僅包含位置pos處或之後的字符。

編輯

#include <iostream> 
    #include <string> 
    int main(int argc, char const *argv[]) 
    { 
     std::string s = "false || echo \"hello world\" | grep hello"; 
     std::string delimiter = "|"; 

     size_t pos = 0, pos1 = 0, flag = 0; 
     std::string token, token1; 
     while ((pos = s.find(delimiter)) != std::string::npos) { 
      pos1 = s.find(delimiter, pos + delimiter.length()); 
      while (pos1 == pos+1){ 
       pos = pos1; 
       pos1 = s.find(delimiter, pos + delimiter.length()); 
       flag = 1; 
      } 
      if (flag) { 
       token = s.substr(0, pos1); 
       std::cout << token << std::endl; 
       if (pos1 > s.length()) 
        exit(0); 
       s.erase(0, pos1 + delimiter.length()); 
      } 
      else{ 
       token = s.substr(0, pos); 
       std::cout << token << std::endl; 
       s.erase(0, pos + delimiter.length()); 
      } 

     } 
     std::cout << s << std::endl; 
     return 0; 
    } 

輸出

假||回聲的「Hello World」

的grep你好

+0

此代碼在 'echo「hello world」的情況下不起作用| grep hello | grep的world' 輸出應該預計: '回聲的 「Hello World」'' grep的hello' 'grep的world' 而它是: '回聲的 「Hello World」 | grep hello' 'grep world' – divyanshch

+0

立即試用!這似乎很好。 – mrdoubtful

+0

你可以嘗試優化代碼,但... – mrdoubtful