C/C++ 字串分割的3種方法

本篇 ShengYu 介紹 C/C++ 字串分割的3種方法,寫程式中字串分割是基本功夫,而且也蠻常會用到的,所以這邊紀錄我曾經用過與所知道的字串分割的幾種方式,
以下為 C/C++ 字串分割的內容章節,

  • C 語言的 strtok
  • C++ std::string::find() 與 std::string::substr() 完成字串分割功能
  • C++ std::getline() 完成字串分割功能

那我們就開始吧!

C 語言的 strtok

C 語言要字串分割通常會使用 strtok,要使用 strtok 的話需要引入的標頭檔 <string.h>,如果要使用 C++ 的標頭檔則是引入 <cstring>
strtok 函式原型為

1
char * strtok(char * str, const char * delimiters);

strtok() 會將 str 依據給入的 delimiters (分割符號/分隔符號) 進行字串分割,如果成功的話會回傳指向分割結果的字串開頭,否則會回傳 NULL,來看看下面的 strtok 用法範例吧!

如下範例所示,d 是分割符號/分隔符號,這邊示範用空格與逗號進行分割,如果有需要的話還可以在 delimiters 加入更多的分割符號,
p 是指向每次分割的結果,
要注意的是除了第一次是將 str 帶入 strtok 分割以外,第二次以上都是將 NULL 帶入 strtok 繼續作字串分割,

cpp-string-split.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// g++ cpp-string-split.cpp -o a.out
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // strtok

int main() {
char str[] = "Hello world, nice to meet you";
const char* d = " ,";
char *p;
p = strtok(str, d);

while (p != NULL) {
printf("%s\n", p);
p = strtok(NULL, d);
}
return 0;
}

結果如下,

1
2
3
4
5
6
Hello
world
nice
to
meet
you

因為 strtok 的實做原理是發現分割字元時,就把字元改為 \0 字元,意味著使用 strtok() 完後,原字串會被修改,
修改後的結果是 Hello\nworld\n\nnice\nto\nmeet\nyou 這樣的形式,所以原本的字串如果之後另有用途的話,記得先複製一份。

C++ std::string::find() 與 std::string::substr() 完成字串分割功能

這邊介紹使用 C++ 的 std::string::find()std::string::substr() 來完成字串分割的功能,std::string::find() 可以用來作字串搜尋的功能,之前在這篇有介紹過了,再將每次找到的位置搭配 std::string::substr() 取出子字串並放入 std::vector 裡,最後再回傳這個結果 std::vector<std::string> result,這種方式的好處是原字串不會被修改,

cpp-string-split2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// g++ cpp-string-split2.cpp -o a.out
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

const std::vector<std::string> split(const std::string& str, const std::string& pattern) {
std::vector<std::string> result;
std::string::size_type begin, end;

end = str.find(pattern);
begin = 0;

while (end != std::string::npos) {
if (end - begin != 0) {
result.push_back(str.substr(begin, end-begin));
}
begin = end + pattern.size();
end = str.find(pattern, begin);
}

if (begin != str.length()) {
result.push_back(str.substr(begin));
}
return result;
}

int main() {
std::string str = " This is a c++ string";
std::string pattern = " ";

std::vector<std::string> ret = split(str, pattern);

for (auto& s : ret) {
cout << s << "\n";
}
return 0;
}

結果輸出如下,

1
2
3
4
5
This
is
a
c++
string

C++ std::getline() 完成字串分割功能

這邊介紹使用 C++ 的 std::getline() 來完成字串分割的功能,先將 std::string 建立 std::stringstream,再用 std::getline() 來處理std::stringstream,將每一次取出的字串放到 std::vector,最後再回傳這個結果 std::vector<std::string> result,這種方式的好處是原字串不會被修改,

cpp-string-split3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// g++ cpp-string-split3.cpp -o a.out
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
using namespace std;

const std::vector<std::string> split(const std::string &str, const char &delimiter) {
std::vector<std::string> result;
std::stringstream ss(str);
std::string tok;

while (std::getline(ss, tok, delimiter)) {
result.push_back(tok);
}
return result;
}

int main() {
std::string str = "This is a c++ string";
std::vector<std::string> ret = split(str, ' ');

for (auto& s : ret) {
cout << s << "\n";
}
return 0;
}

結果如下,

1
2
3
4
5
This
is
a
c++
string

以上就是 C/C++ 字串分割的3種方法介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它參考
strtok - C++ Reference
https://www.cplusplus.com/reference/cstring/strtok/
string::find - C++ Reference
https://www.cplusplus.com/reference/string/string/find/
std::getline - cppreference.com
https://en.cppreference.com/w/cpp/string/basic_string/getline

其它相關文章推薦
如果你想學習 C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
C/C++ 字串比較的3種方法
C/C++ 字串連接的3種方法
C/C++ 字串搜尋的3種方法