本篇 ShengYu 介紹 C++ std::string 用法與範例,C++ string 是一個存放 char 的序列容器,相較於 C-Style 字串可以自由地相加字串,std::string 會負責管理記憶體的工作,大幅減輕開發者的字串操作負擔。C++ std::string 字串操作是必須要學會的基本功,我把 C++ 常用到的 std::string 用法與範例彙整在這邊,並提供完整的 std::string C++ 範例程式碼。
以下 C++ string 內容將分為這幾部份,
- C++ string 常用功能
- C++ string 字串初始化
- C++ string 字串比對 / 字串比較
- C++ string 取得子字串
- C++ string 字串搜尋 / 字串尋找
- C++ string 字串相加
- C++ string 取得長度大小
- for 迴圈尋訪 string 容器
- 清空 string 容器
- 判斷 string 容器是否為空
- C++ string size() 與 capacity() 的差異
- C++ string reserve() 預先配置容器大小的用法
- C++ string resize() 的用法
C++ 要使用 string 容器的話,需要引入的標頭檔:<string>
C++ string 常用功能
以下是 C++ std::string 內常用的成員函式,operator=
:指定字串operator+=
:添加字串operator+
:字串相加operator==
:比較兩個字串的內容是否相同operator[]
:存取索引值[i]的字元,跟陣列一樣索引值從 0 開始at(i)
:存取索引值[i]的字元,跟上面 operator[] 差異是 at(i) 會作邊界檢查,存取越界會拋出一個例外find()
:字串搜尋substr()
:取得子字串empty()
:回傳是否為空,空則回傳truesize()
:回傳目前長度length()
:回傳目前長度
C++ string 字串初始化
C++ std::string 以下有四種常見的字串初始化方式,建構 string 一開始沒有指定初始字串的話會是一個空字串,std::string 建構子可以帶入 C-Style 字串來初始化 std::string,或者 std::string 建構子可以帶入另一個 std::string 來初始化,另外也可以在宣告 std::string 變數同時用 =
來指定初始字串,如下範例所示,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// g++ std-string.cpp -o a.out
int main() {
std::string str1; // 初始化為空字串
std::string str2("abc"); // 從 C-Style 字串來初始化 std::string
std::string str3(str2); // 從另一個 std::string 來初始化
std::string str4 = "def";
std::cout << "str1: " << str1 << '\n';
std::cout << "str2: " << str2 << '\n';
std::cout << "str3: " << str3 << '\n';
std::cout << "str4: " << str4 << '\n';
return 0;
}
結果輸出如下,1
2
3
4str1:
str2: abc
str3: abc
str4: def
以下是 C-Style 字串來初始化 std::string 的幾種用法,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// g++ std-string2.cpp -o a.out
int main() {
const char *p = "abcde";
std::string str1(p, 3);
std::string str2(p, 5);
std::string str3(p);
std::cout << "str1: " << str1 << '\n';
std::cout << "str2: " << str2 << '\n';
std::cout << "str3: " << str3 << '\n';
char arr[] = "ABCDE";
std::string str4(arr);
std::cout << "str4: " << str4 << '\n';
return 0;
}
結果輸出如下,1
2
3
4str1: abc
str2: abcde
str3: abcde
str4: ABCDE
以下是 std::string 預先初始化連續同樣字元的用法,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// g++ std-string3.cpp -o a.out
int main() {
std::string str1(5, 0); // 初始化 5 個 0
std::string str2(5, '\0'); // 初始化 5 個 '\0' 字元
std::string str3(10, 'A'); // 初始化 10 個 A 字元
std::string str4(10, 65); // 初始化 10 個 65
std::cout << "str1: " << str1 << '\n';
std::cout << "str2: " << str2 << '\n';
std::cout << "str3: " << str3 << '\n';
std::cout << "str4: " << str4 << '\n';
return 0;
}
結果輸出如下,1
2
3
4str1:
str2:
str3: AAAAAAAAAA
str4: AAAAAAAAAA
C++ string 字串比對 / 字串比較
以下介紹 C++ string 字串比較的方式,直接使用 operator==
的話是比較直覺且簡單的方式,除了用 operator==
的方式以外,還可以用 std::string::compare()
來做字串比較,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// g++ std-string4.cpp -o a.out
int main() {
std::string str1 = "hello";
std::string str2 = "world";
if (str1 == str2) {
std::cout << "equal\n";
} else {
std::cout << "not equal\n";
}
if (str1 == "hello") {
std::cout << "equal\n";
} else {
std::cout << "not equal\n";
}
if (str1.compare(str2) == 0) {
std::cout << "equal\n";
} else {
std::cout << "not equal\n";
}
if (str1.compare("hello") == 0) {
std::cout << "equal\n";
} else {
std::cout << "not equal\n";
}
return 0;
}
結果輸出如下,1
2
3
4not equal
equal
not equal
equal
C++ string 取得子字串
C++ 使用 std::string::substr()
來取得子字串,substr 第一個參數為起始位置,從0開始,第二個參數為長度,不帶入第二個參數的話會一直到結尾,另外實務上也常會用 std::string::find()
搜尋目標字串的起始位置後再搭配 std::string::substr()
來取得子字串,如下範例,1
2
3
4
5
6
7
8
9
10
11
12
13
14// g++ std-string5.cpp -o a.out
int main() {
std::string str = "hello world !!";
std::cout << str.substr(6, 5) << '\n';
std::cout << str.substr(6) << '\n';
std::size_t pos = str.find("world");
std::cout << pos << '\n';
std::cout << str.substr(pos) << '\n';
return 0;
}
結果輸出如下,1
2
3
4world
world !!
6
world !!
C++ string 字串搜尋 / 字串尋找
C++ 使用 std::string::find()
來字串搜尋,std::string::find()
如果有搜尋到目標字串的話會回傳起始位置,沒搜尋到的話會回傳 std::string::npos
,另外 std::string::find()
回傳的起始位置可以搭配 std::string::substr()
來取得子字串,如下範例,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22// g++ std-string6.cpp -o a.out
int main() {
std::string str = "hello world !!";
std::size_t pos1 = str.find("hello");
std::size_t pos2 = str.find("lo");
std::size_t pos3 = str.find("world");
std::cout << pos1 << '\n';
std::cout << pos2 << '\n';
std::cout << pos3 << '\n';
std::cout << str.substr(pos3) << '\n';
std::size_t pos4 = str.find("abc");
if (found != std::string::npos) {
std::cout << "found at " << found << "\n";
} else {
std::cout << "abc not found\n";
}
return 0;
}
結果輸出如下,1
2
3
4
50
3
6
world !!
abc not found
想要瞭解 std::string::find()
的詳細用法可以參考這篇。
C++ string 字串相加
字串相加在 C 裡是用 strcat,這邊示範一下 C++ std::string 的字串相加用法,std::string 用 operator+
不但可以跟 std::string 相加以外,也可以跟 C-Style 字串相加,如下範例,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// g++ std-string7.cpp -o a.out
int main() {
char str[] = "wrold";
std::string str2 = "hello ";
str2 = str2 + str; // 跟 C-Style 字串相加
std::cout << str2 << '\n';
std::string str3 = " !!";
str3 = str2 + str3; // 跟 std::string 字串相加
str3 = str3 + " this is " + "c++ string " + "example";
std::cout << str3 << '\n';
return 0;
}
結果輸出如下,1
2hello wrold
hello wrold !! this is c++ string example
除了用 operator+=
來添加字串以外,還可以用 std::string::append()
來做字串添加,如下範例,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// g++ std-string8.cpp -o a.out
int main() {
std::string str = "hello ";
std::string str2 = "wrold";
str += str2;
std::cout << str << '\n';
str += " !";
std::cout << str << '\n';
str.append(" this is c++ string example");
std::cout << str << '\n';
return 0;
}
結果輸出如下,1
2
3hello wrold
hello wrold !
hello wrold ! this is c++ string example
C++ string 取得長度大小
這邊介紹 C++ string 取得長度大小,可以使用 std::string::length()
來取得長度,也可以使用 std::string::size()
來取得大小,兩者內部實作其實都是一樣的,都可以達成同樣的目的,如下範例,1
2
3
4
5
6
7
8
9
10// g++ std-string9.cpp -o a.out
int main() {
std::string str = "hello";
std::cout << "size: " << str.size() << '\n';
std::cout << "length: " << str.length() << '\n';
return 0;
}
結果輸出如下,1
2size: 5
length: 5
for 迴圈尋訪 string 容器
以下介紹 for 迴圈尋訪 string 容器的使用範例,使用 operator[]
來存取索引值[i]的字元,就跟 C-Style 字元陣列的操作一樣,1
2
3
4
5
6
7
8
9
10
11// g++ std-string10.cpp -o a.out
int main() {
std::string str = "hello";
for (int i = 0; i < str.length(); i++) {
std::cout << str[i] << '\n';
}
return 0;
}
結果輸出如下,1
2
3
4
5h
e
l
l
o
如果是要使用 range-based for loop 寫法的話,因為 range-based for loop 是 C++11 中增加的新特性,所以編譯時要加上 C++11 的編譯選項,使用範例如下,1
2
3
4
5
6
7
8
9
10
11// g++ std-string11.cpp -o a.out -std=c++11
int main() {
std::string str = "world";
for (auto &c : str) {
std::cout << c << '\n';
}
return 0;
}
結果輸出如下,1
2
3
4
5h
e
l
l
o
清空 string 容器
這邊介紹 C++ 清空 string 容器的用法,要清空 string 的話可以使用 std::string::clear()
或者賦值空字串,如下範例,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// g++ std-string12.cpp -o a.out
int main() {
std::string str = "hello";
std::cout << "str: " << str << '\n';
str.clear();
std::cout << "str: " << str << '\n';
std::string str2 = "world";
std::cout << "str2: " << str2 << '\n';
str2 = "";
std::cout << "str2: " << str2 << '\n';
return 0;
}
結果輸出如下,1
2
3
4str: hello
str:
str2: world
str2:
判斷 string 容器是否為空
這邊介紹 C++ 如何判斷 string 容器是否為空,要判斷是否為空的話可以使用 std::string::empty()
來作判斷,如果為空字串的話則回傳 ture,反之回傳 false,如下範例,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// g++ std-string13.cpp -o a.out
int main() {
std::string str1;
std::string str2 = "";
std::string str3 = "wrold";
if (str1.empty()) {
std::cout << "empty\n";
} else {
std::cout << "not empty\n";
}
if (str2.empty()) {
std::cout << "empty\n";
} else {
std::cout << "not empty\n";
}
if (str3.empty()) {
std::cout << "empty\n";
} else {
std::cout << "not empty\n";
}
return 0;
}
結果輸出如下,1
2
3empty
empty
not empty
C++ string size() 與 capacity() 的差異
string 使用 size()
是取得目前 string 裡的元素個數,而 string 使用 capacity()
是取得目前 string 裡的預先配置的空間大小,當容量(capacity)空間不夠使用時 string 就會重新申請空間,容量(capacity)會增加為原來的容量約 2 倍,各個編譯器可能不同,來看看下面範例,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// g++ std-string14.cpp -o a.out
using namespace std;
int main() {
std::string s;
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
s += "abcdefghij";
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
s += "abcdefghij";
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
s += "abcdefghij";
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
s += "abcdefghij";
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
s += "abcdefghij";
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
s += "abcdefghij";
s += "abcdefghij";
s += "abcdefghij";
s += "abcdefghij";
s += "abcdefghij";
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
return 0;
}
輸出結果如下,從以下的輸出可以發現在我使用的 clang 編譯器中 capacity 是以這樣的方式增長下去,1
2
3
4
5
6
7size=0, capacity=22
size=10, capacity=22
size=20, capacity=22
size=30, capacity=47
size=40, capacity=47
size=50, capacity=95
size=100, capacity=191
C++ string reserve() 預先配置容器大小的用法
string 使用 reserve()
是預留空間的意思,如果我們一開始就知道容器的裡要放置多少個元素的話,可以透過 reserve()
來預先配置容器大小,這樣可以減少一直配置記憶體的機會。
如下例所示,先宣告一個 string,假設我想要預先配置好 10 個大小的話可以這樣寫 string.reserve(10)
,這樣會預留大於或等於 10 個元素的空間,使用 capacity()
會得到 22,但裡面還沒有任何元素所以使用 size()
會得到 0,之後用 operator+=
將元素新增進去,然後我們來觀察看看 size 與 capacity 的變化,
之後將 string 新增 5 個字元進去,再次使用 capacity()
還是 22,而使用 size()
會得到 20,1
2
3
4
5
6string s;
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
s.reserve(10);
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
s += "AAAAA";
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
輸出如下,1
2
3size=0, capacity=22
size=0, capacity=22
size=5, capacity=22
那 string reserve 預留 22 個元素的空間後,之後使用超過 22 個元素 capacity 會發生什麼變化呢?1
2
3
4
5
6
7
8
9
10
11string s;
s.reserve(22);
s += "AAAAAAAAAA";
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
s += "AAAAAAAAAA";
s += "AAAAAAAAAA";
s += "AAAAAAAAAA";
s += "AAAAAAA";
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
s += "A";
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
輸出如下,可以發現當 string 的元素超過預留的 22 個元素時,會將容量增長為原本 capacity 的約兩倍,1
2
3size=10, capacity=22
size=47, capacity=47
size=48, capacity=95
在 string 建構子帶入數量 n 會初始化 n 個元素且預設初始值為 'A'
字元(或者其他字元或其他數字,例如:0),所以使用 size()
會回傳 n,跟上述的 reserve()
用途是不一樣的,詳見下列範例,1
2
3
4
5
6
7
8
9
10
11string s(2, 'A');
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
s += 'B'; // AAB
s += 'C'; // AABC
s += 'D'; // AABCD
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
cout << s << "\n";
for (int i = 0; i < s.size(); i++) {
cout << (int)s[i] << " ";
}
cout << "\n";
輸出如下,一開始在 string 建構子帶入的數量 2 跟 'A'
字元會初始化 2 個 'A'
字元,1
2
3
4size=2, capacity=22
size=5, capacity=22
AABCD
65 65 66 67 68
C++ string resize() 的用法
C++ string 使用 resize 跟 reserve 不太一樣,resize 變大時會把多的元素補 0,例如:1
2
3
4
5
6
7
8string s;
s.resize(5);
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
cout << s << "\n";
for (int i = 0; i < s.size(); i++) {
cout << (int)s[i] << " ";
}
cout << "\n";
輸出如下,印出來的元素都是 0,1
2
3size=5, capacity=22
0 0 0 0 0
resize 如果要順便指定元素初始值的話,可以將初始值帶入 resize()
的第二個引數,像這樣寫,1
2
3
4
5
6
7
8string s;
s.resize(5, 'A');
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
cout << s << "\n";
for (int i = 0; i < s.size(); i++) {
cout << (int)s[i] << " ";
}
cout << "\n";
輸出如下,這些新增的元素初始值都設成 'A'
字元也就是 65,1
2
3size=5, capacity=22
AAAAA
65 65 65 65 65
如果 resize 的大小超過 capacity 容量大小會怎麼樣呢?1
2
3
4
5
6
7
8
9string s = "AAAAAAAAAABBBBBBBBBBCC";
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
s.resize(30);
cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n";
cout << s << "\n";
for (int i = 0; i < s.size(); i++) {
cout << (int)s[i] << " ";
}
cout << "\n";
輸出如下,原本的 AAAAAAAAAABBBBBBBBBBCC
元素有保留以外,剩下新增的元素補 0,1
2
3
4size=22, capacity=22
size=30, capacity=47
AAAAAAAAAABBBBBBBBBBCC
65 65 65 65 65 65 65 65 65 65 66 66 66 66 66 66 66 66 66 66 67 67 0 0 0 0 0 0 0 0
以上就是 C++ std::string 用法與範例的介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!
其他參考
string - C++ Reference
https://www.cplusplus.com/reference/string/string/
std::basic_string - cppreference.com
https://en.cppreference.com/w/cpp/string/basic_string
其它相關文章推薦
如果你想學習 C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
std::string::find 搜尋字串
std::vector 用法與範例
std::sort 用法與範例