[程式設計] C++ 的字串切割

簡介

C++的字串切割,我看過解釋最詳細的是這篇。推薦大家看看。

字串切割是撰寫程式中常有的需求,舉例來說

  • 將一個字串依空白切割成數個子字串。如 "15 19 12" 切成 "15","19" 以及 "12"。
  • 將字串依規定的符號切割成數個子字串。如 "15,19,12",切成 "15","19" 以及 "12",這是切割符號為逗點。
  • 將字串依規定的符號切割成數個子字串,但這個符號可以有多種。例如 "15,19!12",切成 "15","19" 以及 "12",這是切割符號為 , 以及 !。

這篇文章,要談的,是最後一種的切割方式。

進入正文中的閒話

如果只有一種切割符號,那直接用 stringstream 以及 getline 就可以解決。

但多個切割符號,就很麻煩了。函式庫內建的 stringstream 以及 getline 並沒有法子達到這個功能,所以只能自己動手來搞定了。

好在 C++ 的字串有提供 find_first_of 這個字串的尋找函式,可以幫我們省下很多麻煩。

題外話,由於字串切割真的是很重要,而且常見的任務。這種自幹的作法也是會讓程式設計師增加很多麻煩,所以著名的 Boost 函式庫就提供了功能強大的 split 函式。祈禱這個功能可以加入下一版的 C++ 中囉 (例如 C++ 20 中)。

好了,要開始進入正文了,但先說明,底下版本會略掉「空字串」。

這什麼意思呢?看一下底下的例子。

"12,|15 19"

分割符號為 逗點,空白,以及 |。

可以看到 12 和 15 間夾了 ,|

這兩個符號間,夾了一個空字串,這個字串在底下的程式中,是會被忽略的。

find_first_of 

find_first_of 是 C++ 字串的一個成員函式,它最常用的形式為

find_first_of("切割字元", 位置);

舉例來說


在上面的例子中, 我們要在 s 中,找到 " ,|" 中第一個出現的字元。

" ,|" 包含三個字元,即 空白,逗點,以及 |。 C++ 只要遇到其中一個,就會中斷尋找,並回傳所在的位置。

所以這個例子中, pos 為 2,因為第一個出現的分割字元為 逗點,它出現在字串的第 2 個位置。

搭配 substr 來切出子字串

接著我們就可以用 substr 來把字串中的子字串找出來。

substr 常用的形式為

substr( 位置, 長度 )

它會在字串中,由位置指定處,切出某個長度的子字串。

還是搭配個例子吧。

在上面的例子中, current 代表開始搜尋的位置。它的初始值為 0。

pos 為第一個分割字元的位值,其值為 2。

所以 pos - current 便為 2。也就是第一個子字串的長度。

因此第12行便印出 15 了。

把 while 加上去,切出所有的子字串吧!

瞭解這些後,我們就可以把前述的程式碼放到 loop 中,不斷的切割,就可以切出所有的子字串了。

在底下的例子中,會把所有的子字串都放到一個 vector 中,並且忽略空字串。

上面的程式碼中,我把字串切割的功能寫成了函式。

由 16 行開始,splitStr2Vec 會把字串中的子字串切割出來,並放入 vector 中。

current 變數代表搜尋的起點

它的邏輯蠻簡單的,只要切出一個子字串後,若它不是空字串,就放到 vector 中。

然後更新 current 的位置,也就是改變搜尋的位置,由目前分割字元的「下一個」字元開始搜尋。

結論

這篇文章談到了如何依照多個「分割字元」來切割子串。並且把切割字串的功能寫成了函式。

這個函式還有可以改善的地方。

例如我把 「分割字元」 寫死在函式中了,但其實分割字元可以當成參數傳給函式。


留言

  1. 可以解釋一下這段的作用嗎?

    for (string tmp : buf)
    cout << tmp << endl;

    回覆刪除
    回覆
    1. 作者已經移除這則留言。

      刪除
    2. 這是一個C++比較新版的方法,可用冒號走訪vector各元素。

      刪除
  2. 謝謝分享!

    不過這一段似乎有BUG哦

    next = s.find_first_of(" ,|", current);
    if (next != current)
    {
    string tmp = s.substr(current, next - current);
    if (tmp.size() != 0) //忽略空字串
    buf.push_back(tmp);
    }

    當 find() return -1 的時候,您的 substr 會是 s.substr(current, -1-current)
    所以應該另外判斷!

    回覆刪除
  3. Learn and apply all the latest language code with us here codeprozone.

    回覆刪除

張貼留言

這個網誌中的熱門文章

由 Pandas 的 DataFrame 中取得資料

[C++]在 cin 後呼叫 getline 所遇到的問題