本篇 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()
:回傳是否為空,空則回傳true
size()
:回傳目前長度
length()
:回傳目前長度
C++ string 字串初始化
C++ std::string 以下有四種常見的字串初始化方式,建構 string 一開始沒有指定初始字串的話會是一個空字串,std::string 建構子可以帶入 C-Style 字串來初始化 std::string,或者 std::string 建構子可以帶入另一個 std::string 來初始化,另外也可以在宣告 std::string 變數同時用 =
來指定初始字串,如下範例所示,
std-string.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <iostream> #include <string>
int main() { std::string str1; std::string str2("abc"); std::string str3(str2); 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 4
| str1: str2: abc str3: abc str4: def
|
以下是 C-Style 字串來初始化 std::string 的幾種用法,
std-string2.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <iostream> #include <string>
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 4
| str1: abc str2: abcde str3: abcde str4: ABCDE
|
以下是 std::string 預先初始化連續同樣字元的用法,
std-string3.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <iostream> #include <string>
int main() { std::string str1(5, 0); std::string str2(5, '\0'); std::string str3(10, 'A'); std::string str4(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 4
| str1: str2: str3: AAAAAAAAAA str4: AAAAAAAAAA
|
C++ string 字串比對 / 字串比較
以下介紹 C++ string 字串比較的方式,直接使用 operator==
的話是比較直覺且簡單的方式,除了用 operator==
的方式以外,還可以用 std::string::compare()
來做字串比較,
std-string4.cpp1 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
| #include <iostream> #include <string> 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 4
| not equal equal not equal equal
|
C++ string 取得子字串
C++ 使用 std::string::substr()
來取得子字串,substr 第一個參數為起始位置,從0開始,第二個參數為長度,不帶入第二個參數的話會一直到結尾,另外實務上也常會用 std::string::find()
搜尋目標字串的起始位置後再搭配 std::string::substr()
來取得子字串,如下範例,
std-string5.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <iostream> #include <string> 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 4
| world world !! 6 world !!
|
C++ string 字串搜尋 / 字串尋找
C++ 使用 std::string::find()
來字串搜尋,std::string::find()
如果有搜尋到目標字串的話會回傳起始位置,沒搜尋到的話會回傳 std::string::npos
,另外 std::string::find()
回傳的起始位置可以搭配 std::string::substr()
來取得子字串,如下範例,
std-string6.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include <iostream> #include <string> 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 5
| 0 3 6 world !! abc not found
|
想要瞭解 std::string::find()
的詳細用法可以參考這篇。
C++ string 字串相加
字串相加在 C 裡是用 strcat,這邊示範一下 C++ std::string 的字串相加用法,std::string 用 operator+
不但可以跟 std::string 相加以外,也可以跟 C-Style 字串相加,如下範例,
std-string7.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <iostream> #include <string> int main() { char str[] = "wrold"; std::string str2 = "hello "; str2 = str2 + str; std::cout << str2 << '\n';
std::string str3 = " !!"; str3 = str2 + str3; str3 = str3 + " this is " + "c++ string " + "example"; std::cout << str3 << '\n'; return 0; }
|
結果輸出如下,
1 2
| hello wrold hello wrold !! this is c++ string example
|
除了用 operator+=
來添加字串以外,還可以用 std::string::append()
來做字串添加,如下範例,
std-string8.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <iostream> #include <string> 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 3
| hello wrold hello wrold ! hello wrold ! this is c++ string example
|
C++ string 取得長度大小
這邊介紹 C++ string 取得長度大小,可以使用 std::string::length()
來取得長度,也可以使用 std::string::size()
來取得大小,兩者內部實作其實都是一樣的,都可以達成同樣的目的,如下範例,
std-string9.cpp1 2 3 4 5 6 7 8 9 10
| #include <iostream> #include <string> int main() { std::string str = "hello"; std::cout << "size: " << str.size() << '\n'; std::cout << "length: " << str.length() << '\n'; return 0; }
|
結果輸出如下,
for 迴圈尋訪 string 容器
以下介紹 for 迴圈尋訪 string 容器的使用範例,使用 operator[]
來存取索引值[i]的字元,就跟 C-Style 字元陣列的操作一樣,
std-string10.cpp1 2 3 4 5 6 7 8 9 10 11
| #include <iostream> #include <string> int main() { std::string str = "hello"; for (int i = 0; i < str.length(); i++) { std::cout << str[i] << '\n'; } return 0; }
|
結果輸出如下,
如果是要使用 range-based for loop 寫法的話,因為 range-based for loop 是 C++11 中增加的新特性,所以編譯時要加上 C++11 的編譯選項,使用範例如下,
std-string11.cpp1 2 3 4 5 6 7 8 9 10 11
| #include <iostream> #include <string> int main() { std::string str = "world"; for (auto &c : str) { std::cout << c << '\n'; } return 0; }
|
結果輸出如下,
清空 string 容器
這邊介紹 C++ 清空 string 容器的用法,要清空 string 的話可以使用 std::string::clear()
或者賦值空字串,如下範例,
std-string12.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <iostream> #include <string> 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 4
| str: hello str: str2: world str2:
|
判斷 string 容器是否為空
這邊介紹 C++ 如何判斷 string 容器是否為空,要判斷是否為空的話可以使用 std::string::empty()
來作判斷,如果為空字串的話則回傳 ture,反之回傳 false,如下範例,
std-string13.cpp1 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
| #include <iostream> #include <string> 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; }
|
結果輸出如下,
C++ string size() 與 capacity() 的差異
string 使用 size()
是取得目前 string 裡的元素個數,而 string 使用 capacity()
是取得目前 string 裡的預先配置的空間大小,當容量(capacity)空間不夠使用時 string 就會重新申請空間,容量(capacity)會增加為原來的容量約 2 倍,各個編譯器可能不同,來看看下面範例,
std-string14.cpp1 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
| #include <iostream> #include <string>
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 7
| size=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 6
| string 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 3
| size=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 11
| string 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 3
| size=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 11
| string s(2, 'A'); cout << "size=" << s.size() << ", capacity=" << s.capacity() << "\n"; s += 'B'; s += 'C'; s += 'D'; 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 4
| size=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 8
| string 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 3
| size=5, capacity=22
0 0 0 0 0
|
resize 如果要順便指定元素初始值的話,可以將初始值帶入 resize()
的第二個引數,像這樣寫,
1 2 3 4 5 6 7 8
| string 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 3
| size=5, capacity=22 AAAAA 65 65 65 65 65
|
如果 resize 的大小超過 capacity 容量大小會怎麼樣呢?
1 2 3 4 5 6 7 8 9
| string 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 4
| size=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 用法與範例