C++之STL--string的使用
深入探索 C++ STL 中的 std::string
在 C++ 編程中,字符串處理是一個(gè)常見的任務(wù),而 C++ 標(biāo)準(zhǔn)模板庫(kù)(STL)中的 std::string
類為我們提供了強(qiáng)大的功能來(lái)簡(jiǎn)化這一過(guò)程。
一、std::string 的基本概念
std::string
是 C++ STL 中的一個(gè)類,用于表示和操作字符串。它屬于 <string>
頭文件,是基于模板的 std::basic_string
類的一個(gè)特化版本,專門用于處理字符類型為 char
的字符串。與傳統(tǒng)的 C 風(fēng)格字符串(以空字符結(jié)束的字符數(shù)組)相比,std::string
提供了更高的安全性和更豐富的功能。
1. 內(nèi)存管理
std::string
內(nèi)部會(huì)動(dòng)態(tài)管理內(nèi)存,這意味著你不需要手動(dòng)分配和釋放內(nèi)存。
當(dāng)你對(duì)字符串進(jìn)行修改時(shí),std::string
會(huì)自動(dòng)調(diào)整內(nèi)存大小以適應(yīng)新的內(nèi)容。
- 例如:
std::string str = "Hello"; str += ", World!"; // 內(nèi)部自動(dòng)調(diào)整內(nèi)存大小
2. 安全性
std::string
不會(huì)像 C 風(fēng)格字符串那樣容易出現(xiàn)越界訪問(wèn)或內(nèi)存泄漏的問(wèn)題。
它提供了邊界檢查和異常處理機(jī)制,確保字符串操作的安全性。
二、std::string 的構(gòu)造與初始化
std::string
提供了多種構(gòu)造方式,可以根據(jù)不同的需求選擇合適的構(gòu)造函數(shù)。
1. 默認(rèn)構(gòu)造
std::string str; // 創(chuàng)建一個(gè)空字符串
2. 從 C 風(fēng)格字符串構(gòu)造
const char* c_str = "Hello"; std::string str(c_str); // 使用 C 風(fēng)格字符串初始化
3. 從字符串的一部分構(gòu)造
std::string str1 = "Hello World"; std::string str2(str1, 6, 5); // 從 str1 的第 6 個(gè)字符開始,取 5 個(gè)字符 // str2 的內(nèi)容為 "World"
4. 使用重復(fù)字符構(gòu)造
std::string str(5, 'a'); // 創(chuàng)建一個(gè)包含 5 個(gè) 'a' 的字符串 // str 的內(nèi)容為 "aaaaa"
三、std::string 的常用操作
1. 字符串拼接
std::string
提供了多種方式來(lái)拼接字符串,包括使用 +
運(yùn)算符和 +=
運(yùn)算符。
std::string str1 = "Hello"; std::string str2 = "World"; std::string str3 = str1 + ", " + str2 + "!"; // 使用 + 拼接 str1 += " "; // 使用 += 拼接 str1 += str2; // str1 的內(nèi)容為 "Hello World"
2. 字符串比較
std::string
支持使用比較運(yùn)算符(如 ==
、!=
、<
、>
等)來(lái)比較字符串內(nèi)容。
std::string str1 = "apple"; std::string str2 = "banana"; if (str1 < str2) { std::cout << "apple is less than banana" << std::endl; }
3. 字符串查找
std::string
提供了 find
方法,用于查找子字符串的位置。
std::string str = "Hello World"; size_t pos = str.find("World"); if (pos != std::string::npos) { std::cout << "Found 'World' at position " << pos << std::endl; }
4. 字符串替換
std::string
的 replace
方法可以用來(lái)替換字符串中的部分內(nèi)容。
std::string str = "Hello World"; str.replace(6, 5, "Universe"); // str 的內(nèi)容變?yōu)?"Hello Universe"
5. 字符串分割
雖然 std::string
沒(méi)有直接提供分割字符串的方法,但可以通過(guò)循環(huán)和 find
方法實(shí)現(xiàn)。
std::string str = "apple,banana,orange"; std::string delimiter = ","; size_t pos = 0; std::string token; while ((pos = str.find(delimiter)) != std::string::npos) { token = str.substr(0, pos); std::cout << token << std::endl; str.erase(0, pos + delimiter.length()); } std::cout << str << std::endl; // 輸出最后一個(gè)子字符串
6. 字符串大小和容量
std::string
提供了 size
和 capacity
方法來(lái)獲取字符串的長(zhǎng)度和當(dāng)前分配的內(nèi)存容量。
std::string str = "Hello"; std::cout << "Size: " << str.size() << std::endl; // 輸出 5 std::cout << "Capacity: " << str.capacity() << std::endl; // 輸出實(shí)際分配的容量
7. 字符訪問(wèn)
可以通過(guò)下標(biāo)運(yùn)算符 []
或 at
方法訪問(wèn)字符串中的字符。
std::string str = "Hello"; char c = str[0]; // 使用下標(biāo)訪問(wèn) char d = str.at(1); // 使用 at 方法訪問(wèn)
四.string類對(duì)象的訪問(wèn)及遍歷操作
std::string的容量相關(guān)概念
在深入了解容量操作之前,我們需要明確幾個(gè)與std::string
容量相關(guān)的重要概念:
1. size(或length)
size
函數(shù)返回字符串中實(shí)際存儲(chǔ)的字符數(shù)量,不包括末尾的空字符'\0'
。length
函數(shù)與size
功能完全相同,只是名字不同。
std::string str = "Hello, World!"; std::cout << "Size: " << str.size() << std::endl; // 輸出:Size: 13
2. capacity
capacity
函數(shù)返回字符串當(dāng)前分配的內(nèi)存容量,單位是字符數(shù)。
capacity
通常大于或等于size
,因?yàn)?code>std::string會(huì)預(yù)留一些額外的內(nèi)存,以便在字符串?dāng)U展時(shí)減少內(nèi)存分配的次數(shù)。
std::string str = "Hello, World!"; std::cout << "Capacity: " << str.capacity() << std::endl; // 輸出:Capacity: 15(具體值可能因?qū)崿F(xiàn)而異)
3. max_size
max_size
函數(shù)返回std::string
能夠存儲(chǔ)的最大字符數(shù)。
這個(gè)值通常取決于系統(tǒng)的內(nèi)存限制和std::string
的實(shí)現(xiàn)。
std::string str; std::cout << "Max size: " << str.max_size() << std::endl; // 輸出:Max size: 18446744073709551615(64位系統(tǒng))
reserve:預(yù)留內(nèi)存
reserve
函數(shù)用于顯式地為std::string
預(yù)留一定量的內(nèi)存。這可以減少在字符串頻繁擴(kuò)展時(shí)的內(nèi)存分配次數(shù),從而提高性能。
使用場(chǎng)景
當(dāng)你知道字符串將要存儲(chǔ)大量字符時(shí),可以使用reserve
預(yù)先分配足夠的內(nèi)存。
例如,當(dāng)你從文件中讀取大量文本并拼接到字符串中時(shí),reserve
可以顯著提高效率。
示例代碼
std::string str; str.reserve(1000); // 預(yù)留1000個(gè)字符的內(nèi)存 for (int i = 0; i < 1000; ++i) { str += 'a'; } std::cout << "Size: " << str.size() << std::endl; // 輸出:Size: 1000 std::cout << "Capacity: " << str.capacity() << std::endl; // 輸出:Capacity: 1000
注意事項(xiàng)
reserve
不會(huì)改變字符串的內(nèi)容,只是改變其容量。- 如果
reserve
的參數(shù)小于當(dāng)前capacity
,std::string
的容量不會(huì)減少。 reserve
是一個(gè)非強(qiáng)制性操作,具體行為可能因標(biāo)準(zhǔn)庫(kù)的實(shí)現(xiàn)而異。
shrink_to_fit:收縮內(nèi)存
shrink_to_fit
函數(shù)用于收縮std::string
的容量,使其盡可能接近實(shí)際的size
。
這可以減少不必要的內(nèi)存占用,但需要注意的是,shrink_to_fit
是一個(gè)非強(qiáng)制性操作,具體行為可能因標(biāo)準(zhǔn)庫(kù)的實(shí)現(xiàn)而異。
使用場(chǎng)景
當(dāng)你完成了一個(gè)字符串的頻繁修改操作后,可以使用shrink_to_fit
來(lái)釋放多余的內(nèi)存。
例如,在字符串拼接完成后,調(diào)用shrink_to_fit
可以優(yōu)化內(nèi)存使用。
示例代碼
std::string str = "Hello"; str += "World"; str.shrink_to_fit(); std::cout << "Size: " << str.size() << std::endl; // 輸出:Size: 10 std::cout << "Capacity: " << str.capacity() << std::endl; // 輸出:Capacity: 10(具體值可能因?qū)崿F(xiàn)而異)
注意事項(xiàng)
shrink_to_fit
不會(huì)改變字符串的內(nèi)容,只是嘗試減少其容量。shrink_to_fit
是一個(gè)非強(qiáng)制性操作,可能不會(huì)立即生效。
resize:調(diào)整字符串大小
resize
函數(shù)用于調(diào)整字符串的大小。如果新的大小大于當(dāng)前size
,則會(huì)用指定的字符填充新分配的部分;如果新的大小小于當(dāng)前size
,則會(huì)截?cái)嘧址?/p>
示例代碼
std::string str = "Hello, World!"; str.resize(5); // 截?cái)嘧址? std::cout << "Resized string: " << str << std::endl; // 輸出:Hello str.resize(10, 'x'); // 擴(kuò)展字符串并用'x'填充 std::cout << "Resized string: " << str << std::endl; // 輸出:Helloxxxxx
注意事項(xiàng)
resize
會(huì)改變字符串的內(nèi)容,而reserve
和shrink_to_fit
不會(huì)。resize
的第二個(gè)參數(shù)是可選的,默認(rèn)填充字符為空字符'\0'
。
容量操作的性能優(yōu)化
合理使用std::string
的容量操作可以顯著提高程序的性能。
以下是一些優(yōu)化建議:
1. 預(yù)留足夠的內(nèi)存
如果你知道字符串將要存儲(chǔ)大量字符,使用reserve
預(yù)先分配足夠的內(nèi)存可以減少內(nèi)存分配的次數(shù)。
2. 及時(shí)收縮內(nèi)存
在完成字符串的頻繁修改操作后,使用shrink_to_fit
可以釋放多余的內(nèi)存,優(yōu)化內(nèi)存使用。
3. 避免不必要的拷貝
std::string
的拷貝構(gòu)造和賦值操作可能會(huì)導(dǎo)致不必要的內(nèi)存分配和拷貝。如果可能,盡量使用引用或std::move
來(lái)避免拷貝。
五.string類對(duì)象的修改操作
std::string的修改操作概述
std::string
提供了多種方法來(lái)修改字符串的內(nèi)容,包括插入、刪除、替換、直接修改字符等。
這些操作使得字符串的編輯變得非常靈活,同時(shí)也避免了C語(yǔ)言中直接操作字符數(shù)組時(shí)可能出現(xiàn)的內(nèi)存錯(cuò)誤。
直接修改字符
std::string
支持通過(guò)下標(biāo)操作符[]
或at
函數(shù)直接修改字符串中的字符。
這兩種方式的主要區(qū)別在于,[]
操作符不進(jìn)行邊界檢查,而at
函數(shù)會(huì)進(jìn)行邊界檢查并拋出異常。
示例代碼
std::string str = "Hello, World!"; str[0] = 'h'; // 將第一個(gè)字符修改為小寫的'h' str.at(7) = 'w'; // 將第8個(gè)字符(索引為7)修改為小寫的'w' std::cout << str << std::endl; // 輸出:hello, world!
注意事項(xiàng)
- 使用
[]
操作符時(shí),如果索引超出字符串范圍,行為是未定義的。 - 使用
at
函數(shù)時(shí),如果索引超出范圍,會(huì)拋出std::out_of_range
異常。
插入操作
std::string
提供了多種插入操作,允許你在字符串的任意位置插入字符、字符串或字符數(shù)組。
1. 插入單個(gè)字符
std::string str = "Hello, World!"; str.insert(5, "X"); // 在索引5的位置插入字符'X' std::cout << str << std::endl; // 輸出:HelloX, World!
2. 插入字符串
std::string str = "Hello, World!"; str.insert(7, "C++"); // 在索引7的位置插入字符串"C++" std::cout << str << std::endl; // 輸出:Hello, C++World!
3. 插入字符數(shù)組
std::string str = "Hello, World!"; char arr[] = "Python"; str.insert(7, arr); // 在索引7的位置插入字符數(shù)組"Python" std::cout << str << std::endl; // 輸出:Hello, PythonWorld!
注意事項(xiàng)
- 插入操作會(huì)改變字符串的
size
和capacity
。 - 如果插入位置超出字符串范圍,行為是未定義的。
刪除操作
std::string
提供了erase
函數(shù),用于刪除字符串中的一部分內(nèi)容。
示例代碼
std::string str = "Hello, World!"; str.erase(7, 5); // 從索引7開始刪除5個(gè)字符 std::cout << str << std::endl; // 輸出:Hello, !
參數(shù)說(shuō)明
- 第一個(gè)參數(shù)是刪除的起始位置(索引)。
- 第二個(gè)參數(shù)是刪除的字符數(shù)。
注意事項(xiàng)
- 如果刪除的起始位置超出字符串范圍,行為是未定義的。
- 刪除操作會(huì)改變字符串的
size
,但不會(huì)改變capacity
。
替換操作
std::string
提供了replace
函數(shù),用于替換字符串中的一部分內(nèi)容。
示例代碼
std::string str = "Hello, World!"; str.replace(7, 5, "C++"); // 從索引7開始,替換5個(gè)字符為"C++" std::cout << str << std::endl; // 輸出:Hello, C++!
參數(shù)說(shuō)明
- 第一個(gè)參數(shù)是替換的起始位置(索引)。
- 第二個(gè)參數(shù)是替換的字符數(shù)。
- 第三個(gè)參數(shù)是新的內(nèi)容。
注意事項(xiàng)
- 替換操作會(huì)改變字符串的
size
,但不會(huì)改變capacity
。 - 如果替換的起始位置超出字符串范圍,行為是未定義的。
追加操作
std::string
提供了多種追加操作,允許你在字符串的末尾添加字符、字符串或字符數(shù)組。
1. 追加單個(gè)字符
std::string str = "Hello"; str.push_back(' '); // 追加一個(gè)空格 str += 'W'; // 追加字符'W' std::cout << str << std::endl; // 輸出:Hello W
2. 追加字符串
std::string str = "Hello "; str += "World"; // 追加字符串"World" std::cout << str << std::endl; // 輸出:Hello World
3. 追加字符數(shù)組
std::string str = "Hello "; char arr[] = "C++"; str.append(arr); // 追加字符數(shù)組"C++" std::cout << str << std::endl; // 輸出:Hello C++
注意事項(xiàng)
- 追加操作會(huì)改變字符串的
size
,但不會(huì)改變capacity
。 - 如果
capacity
不足,std::string
會(huì)自動(dòng)分配更大的內(nèi)存。
清空字符串
std::string
提供了clear
函數(shù),用于清空字符串的內(nèi)容,但不會(huì)釋放內(nèi)存。
示例代碼
std::string str = "Hello, World!"; str.clear(); std::cout << "Size: " << str.size() << std::endl; // 輸出:Size: 0 std::cout << "Capacity: " << str.capacity() << std::endl; // 輸出:Capacity: 15(具體值可能因?qū)崿F(xiàn)而異)
注意事項(xiàng)
clear
函數(shù)只會(huì)清空字符串的內(nèi)容,不會(huì)釋放內(nèi)存。- 如果需要釋放內(nèi)存,可以結(jié)合
shrink_to_fit
使用。
使用std::stringstream進(jìn)行復(fù)雜修改
對(duì)于復(fù)雜的字符串修改操作,可以使用std::stringstream
。
std::stringstream
是一個(gè)非常靈活的工具,可以方便地進(jìn)行字符串的拼接、格式化和提取。
示例代碼
#include <sstream> std::string str = "Hello, World!"; std::stringstream ss(str); std::string word; ss >> word; // 提取第一個(gè)單詞 ss << "C++"; // 替換為"C++" ss >> word; // 提取第二個(gè)單詞 ss << "Programming"; // 替換為"Programming" str = ss.str(); // 將修改后的內(nèi)容賦值回str std::cout << str << std::endl; // 輸出:Hello, C++Programming
六.string類非成員函數(shù)
什么是std::string的非成員函數(shù)?
std::string
的非成員函數(shù)是指那些不屬于std::string
類的成員函數(shù),但專門用于操作std::string
對(duì)象的函數(shù)。
這些函數(shù)通常定義在<string>
頭文件中,或者通過(guò)標(biāo)準(zhǔn)庫(kù)的其他部分提供。
非成員函數(shù)的優(yōu)勢(shì)在于它們可以提供更通用的操作方式,同時(shí)避免了對(duì)std::string
類本身的過(guò)度擴(kuò)展。
常見的std::string非成員函數(shù)
1. std::swap
std::swap
用于交換兩個(gè)std::string
對(duì)象的內(nèi)容。
它是一個(gè)非成員函數(shù),可以高效地交換兩個(gè)字符串的內(nèi)容,而不需要逐個(gè)字符復(fù)制。
示例代碼
#include <iostream> #include <string> #include <algorithm> // 包含std::swap int main() { std::string str1 = "Hello"; std::string str2 = "World"; std::swap(str1, str2); std::cout << "str1: " << str1 << std::endl; // 輸出:str1: World std::cout << "str2: " << str2 << std::endl; // 輸出:str2: Hello }
2. std::to_string
std::to_string
是一個(gè)非常有用的非成員函數(shù),用于將數(shù)值類型(如int
、float
、double
等)轉(zhuǎn)換為std::string
。
它提供了一種簡(jiǎn)單且類型安全的方式來(lái)實(shí)現(xiàn)數(shù)值與字符串之間的轉(zhuǎn)換。
示例代碼
#include <iostream> #include <string> int main() { int num = 42; double pi = 3.14159; std::string numStr = std::to_string(num); std::string piStr = std::to_string(pi); std::cout << "Number as string: " << numStr << std::endl; // 輸出:Number as string: 42 std::cout << "Pi as string: " << piStr << std::endl; // 輸出:Pi as string: 3.141590 }
3. std::stoi、std::stod、std::stof等
這些函數(shù)用于將std::string
對(duì)象轉(zhuǎn)換為數(shù)值類型。
std::stoi
將字符串轉(zhuǎn)換為int
,std::stod
將字符串轉(zhuǎn)換為double
,std::stof
將字符串轉(zhuǎn)換為float
等。
這些函數(shù)提供了一種簡(jiǎn)單且安全的方式來(lái)解析字符串中的數(shù)值。
示例代碼
#include <iostream> #include <string> int main() { std::string numStr = "42"; std::string piStr = "3.14159"; int num = std::stoi(numStr); double pi = std::stod(piStr); std::cout << "Number from string: " << num << std::endl; // 輸出:Number from string: 42 std::cout << "Pi from string: " << pi << std::endl; // 輸出:Pi from string: 3.14159 }
4. std::getline
std::getline
是一個(gè)非成員函數(shù),用于從輸入流(如std::cin
或std::ifstream
)中讀取一行內(nèi)容并存儲(chǔ)到std::string
對(duì)象中。它支持按分隔符讀取,例如按逗號(hào)、空格等分隔。
示例代碼
#include <iostream> #include <string> #include <sstream> int main() { std::string line = "Hello, World!"; std::istringstream ss(line); std::string word; while (std::getline(ss, word, ',')) { std::cout << word << std::endl; // 輸出:Hello 和 World! } }
5. std::operator<< 和 std::operator>>
這些操作符重載允許你直接使用std::cin
和std::cout
來(lái)輸入和輸出std::string
對(duì)象。
它們是C++標(biāo)準(zhǔn)庫(kù)提供的非成員函數(shù),使得字符串的輸入輸出變得非常方便。
示例代碼
#include <iostream> #include <string> int main() { std::string str; std::cout << "Enter a string: "; std::cin >> str; std::cout << "You entered: " << str << std::endl; }
6. std::operator+ 和 std::operator+=
雖然這些操作符是std::string
的成員函數(shù),但它們也可以作為非成員函數(shù)使用。
std::operator+
用于拼接兩個(gè)字符串,而std::operator+=
用于將一個(gè)字符串追加到另一個(gè)字符串的末尾。
這些操作符使得字符串拼接變得非常直觀。
示例代碼
#include <iostream> #include <string> int main() { std::string str1 = "Hello"; std::string str2 = "World"; std::string result = str1 + " " + str2; // 使用std::operator+ str1 += " "; // 使用std::operator+= str1 += str2; std::cout << "Result: " << result << std::endl; // 輸出:Result: Hello World std::cout << "Modified str1: " << str1 << std::endl; // 輸出:Modified str1: Hello World }
7. std::operator==、std::operator!=、std::operator<等
這些操作符重載允許你直接比較兩個(gè)std::string
對(duì)象。它們按照字典序進(jìn)行比較,使得字符串的比較變得非常方便。
示例代碼
#include <iostream> #include <string> int main() { std::string str1 = "Hello"; std::string str2 = "World"; if (str1 == str2) { std::cout << "Strings are equal." << std::endl; } else { std::cout << "Strings are not equal." << std::endl; // 輸出:Strings are not equal. } if (str1 < str2) { std::cout << "str1 is less than str2." << std::endl; // 輸出:str1 is less than str2. } }
總結(jié)
std::string
是 C++ STL 中一個(gè)非常強(qiáng)大且靈活的工具,它提供了豐富的功能來(lái)處理字符串,同時(shí)避免了許多傳統(tǒng)字符串操作的常見問(wèn)題。
通過(guò)掌握 std::string
的構(gòu)造、操作、性能優(yōu)化以及高級(jí)用法,你可以更高效地編寫字符串處理相關(guān)的代碼。
在實(shí)際開發(fā)中,合理使用 std::string
能夠大大提高代碼的可讀性和安全性。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C++使用GDAL庫(kù)實(shí)現(xiàn)Tiff文件的讀取
這篇文章主要為大家詳細(xì)介紹了C++使用GDAL庫(kù)實(shí)現(xiàn)Tiff文件的讀取的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-03-03C語(yǔ)言所有經(jīng)典排序方法的實(shí)現(xiàn)代碼
這篇文章給大家分享C語(yǔ)言所有經(jīng)典排序方法,文章給大家提供完整的實(shí)例代碼幫助大家快速學(xué)習(xí)掌握C語(yǔ)言排序方法,感興趣的朋友一起看看吧2021-06-06Qt使用QCustomPlot的實(shí)現(xiàn)示例
QCustomPlot是一個(gè)基于Qt C++的圖形庫(kù),用于繪制和數(shù)據(jù)可視化,并為實(shí)時(shí)可視化應(yīng)用程序提供高性能服務(wù),本文主要介紹了Qt使用QCustomPlot的實(shí)現(xiàn)示例,感興趣的可以了解一下2024-01-01C語(yǔ)言字符串替換:字符,字符串,字符數(shù)組詳解
這篇文章主要介紹了C++字符串替換的字符,字符串,字符數(shù)組,需要考慮的情況比較全面,有不錯(cuò)的借鑒價(jià)值,需要的朋友可以參考下2021-09-09