[譯]C++如何切分字符串

聲明:html

  • 翻譯僅以技術學習和交流爲目的,如需轉載請務必標明原帖連接。
  • http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c

水平有限,若有翻譯不當,歡迎探討、批評與指正。ios

帖子內容:算法

C++ 切分字符串的最優雅的方式是什麼?咱們假定字符串中每一個單詞分隔符是空格。(備註:我對C的字符串函數或者那種字符處理/存取方式不是很感興趣。所以,請優先選擇優雅而不是效率)函數


我如今能想到的最好的方式是:學習

#include <iostream>
#include <sstream>
#include <string>
using namespace std;

int main()
{
    string s("Somewhere down the road");
    istringstream iss(s);

    do
    {
        string sub;
        iss >> sub;
        cout << "Substring: " << sub << endl;
    } while (iss);

    return 0;
}

另外一種方式去萃取輸入字符串的分隔符,使用標準庫函數很容易實現。下面是使用 STL 的設計方案(健壯而且優雅):spa

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>

int main() {
    using namespace std;
    string sentence = "Something in the way she moves...";
    istringstream iss(sentence);
    copy(istream_iterator<string>(iss),
             istream_iterator<string>(),
             ostream_iterator<string>(cout, "\n"));
}

若是想要把分割後的字符串放到一個容器中,而不是控制檯的話,使用相同的泛型算法便可。翻譯

vector tokens;
    copy(istream_iterator(iss),
         istream_iterator(),
         back_inserter >(tokens));[/c]

評:這種方案只能分割空格,沒有伸縮性。設計


使用 boost 庫:code

std::vector strs;
boost::split(strs, "string to split", boost::is_any_of("\t "));

我打賭這個要比使用 stringstream 快的多。而且這是一個泛型模板方法,它能夠用來分割任意類型的字符串(wchar,etc. or UTF-8),使用任意的分隔符。具體請看文檔htm

評:不是每一個人都用 boost 的。


把 delim 做爲做爲分隔符,第一個函數把結果放到一個已經存在構造好了的 vector 中,第二個函數返回一個新的 vector。

std::vector &split(const std::string &s, char delim, std::vector &elems) {
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

std::vector split(const std::string &s, char delim) {
    std::vector elems;
    return split(s, delim, elems);

}

注意:這種方法不能跳過空的符號,好比下面有四個數據項,其中的一個是空的。

std::vector x = split("one:two::three", ':');
template < class ContainerT >
void tokenize(const std::string& str, ContainerT& tokens,
              const std::string& delimiters = " ", const bool trimEmpty = false)
{
   std::string::size_type pos, lastPos = 0;
   while(true)
   {
      pos = str.find_first_of(delimiters, lastPos);
      if(pos == std::string::npos)
      {
         pos = str.length();

         if(pos != lastPos || !trimEmpty)
            tokens.push_back(ContainerT::value_type(str.data()+lastPos,
                  (ContainerT::value_type::size_type)pos-lastPos ));

         break;
      }
      else
      {
         if(pos != lastPos || !trimEmpty)
            tokens.push_back(ContainerT::value_type(str.data()+lastPos,
                  (ContainerT::value_type::size_type)pos-lastPos ));
      }

      lastPos = pos + 1;
   }
};
#include <vector>
#include <string>
#include <sstream>

using namespace std;

int main()
{
    string str("Split me by whitespaces");
    string buf; // Have a buffer string
    stringstream ss(str); // Insert the string into a stream

    vector<string> tokens; // Create vector to hold our words

    while (ss >> buf)
        tokens.push_back(buf);

}

筆者注:

  • 文中的優雅也就是咱們平時所說的代碼美感。
  • 原本打算把全部的英文都翻譯過來的,後來發現不少實在是難以拿捏。因此後面就直接貼了代碼,其實對於咱們常常看代碼的人,代碼也許要比文字直觀的多。上文代碼我在 vs2010 上驗證無誤。
相關文章
相關標籤/搜索