C++ string類詳解(STL簡介, string類,訪問修改字符)
1. STL簡介
1.1 什么是STL
STL(Standard Template Library , 標準模板庫)是C++標準庫的重要組成部分 , 它基于模板技術 , 提供了一系列通用的數據結構(容器)和算法 , 旨在提高代碼的復用性 , 效率和標準化。
1.2 STL的發(fā)展
- 起源 : 20世紀80年代末 , 由Alexander Stepanov(亞歷山大·斯特潘諾夫)等人提出 , 最初并非C++標準 , 后因實用性被納入C++標準。
- 標準化 : 1998年 , STL正式成為C++98標準的一部分 , 后續(xù)在C++11 , C++14等版本中不斷擴展(如增加無序容器 , 移動語義支持等)。
- 目標 : 通過模板實現“泛型編程” , 讓數據結構和算法脫離具體數據類型 , 實現跨類型復用。
- 原始版本 : Alexander Stepanov、Meng Lee 在惠普實驗室完成的原始版本 , 本著開源精神 , 他們聲明允許任何人任意運用 , 拷貝 , 修改 , 傳播 , 商業(yè)使用這些代碼 , 無需付費。唯一的條件就是也需要向原始版本一樣做開源使用。HP版本 - 所有STL實現版本的始祖。
- P.J.版本 : 由P.J. Plauger開發(fā) , 繼承自HP版本 , 被Windows Visual C++采用 , 不能公開或修改 , 缺陷 : 可讀性比較低 , 符號命名比較怪異。
- RW版本 : 由Rouge Wage公司開發(fā) , 繼承自HP版本 , 被C++ Builder 采用 , 不能公開或修改 , 可讀性一般。
- SGI版本 : 由Silicon Graphics Computer Systems, Inc公司開發(fā) , 繼承自HP版本。被GCC(Linux)采用 , 可移植性好 , 可公開 , 修改甚至販賣 , 從命名風格和編程風格上看 , 閱讀性非常高。我們后面學習STL要閱讀部分源代碼 , 主要參考的就是這個版本。
1.3 STL的六大組件

1.4 STL的重要性
- 提高開發(fā)效率 : 無需重復實現常見數據結構(如鏈表、哈希表)和算法(如排序) , 直接調用STL組件 , 減少代碼量。
- 保證性能 : STL由專家優(yōu)化 , 底層實現高效(如 vector 的連續(xù)內存 , map 的紅黑樹平衡操作)。
- 標準化 : 統(tǒng)一接口讓代碼更易讀 , 易維護 , 不同開發(fā)者可基于STL達成共識。
- 泛型編程典范 : 展示了模板技術的強大 , 為C++后續(xù)發(fā)展奠定基礎。
1.5 如何學習STL
- 1. 基礎入門
- 先掌握C++模板語法(類模板 , 函數模板) , 理解STL的實現基礎。
- 逐個學習核心容器 : vector (最常用)→ list → map / set → 無序容器 , 掌握其初始化 , 增刪改查 , 迭代器使用。
- 2. 算法實踐
- 熟悉 <algorithm> 頭文件中的常用算法 : sort , find , count , reverse 等 , 結合容器練習。
- 理解算法的時間復雜度(如sort 是O(n log n) , find 是O(n))。
- 3. 深入原理
- 了解容器底層實現(如 vector 動態(tài)擴容機制 , map 紅黑樹結構) , 解釋為何某些操作高效/低效。
- 學習迭代器失效場景(如 vector 插入元素可能導致迭代器失效)。
- 4. 實戰(zhàn)應用
- 在編程題 , 項目中主動使用STL , 例如用 unordered_map 做哈希映射 , vector 存儲動態(tài)數組。
- 對比不同容器的適用場景(如需要隨機訪問用 vector , 頻繁插入刪除用 list)。
2. string類
2.1 string類的概念
簡單說 , std::string 是標準庫中獨立的字符串工具 , 但因適配 STL 的迭代器和算法 , 常被視為“準 STL 組件” , 在實際開發(fā)中與 STL 容器(如 vector<string> )配合頻繁。
2.2 string類與STL的關系:
std::string 不屬于 STL 的核心組成部分 , 但它與 STL 關系密切 , 且常被一起使用。
具體來說:
- 歸屬上 : std::string 是 C++ 標準庫中專門用于處理字符串的類 , 定義在 <string> 頭文件中 , 其設計早于 STL 標準化 , 核心目標是封裝字符串操作(如拼接、比較、長度計算等) , 并非 STL 最初定義的“容器、算法、迭代器”體系的核心成員。
- 關聯(lián)上 : std::string 支持 STL 的迭代器(可通過 begin() / end() 獲取) , 能直接使用 STL 算法(如 std::sort 對字符串字符排序 , std::find 查找字符) , 且其內部實現也依賴模板技術 , 與 STL 的泛型思想一致。
2.3 為什么要學習string類
- C語言中 , 字符串是以 \0 結尾的一些字符的集合 , 為了操作方便 , C標準庫中提供了一些str系列的庫函數 , 但是這些庫函數與字符串是分離開的 , 不太符合OOP的思想 , 而且底層空間需要用戶自己管理 , 稍不留神可能還會越界訪問。
- 在OJ中 , 有關字符串的題目基本以string類的形式出現 , 而且在常規(guī)工作中 , 為了簡單、方便、快捷 , 基本都使用string類 , 很少有人去使用C庫中的字符串操作函數。
3. 標準庫中的string類
3.1 string類
std::string 是 C++ 標準庫中用于處理字符串的類 , 定義在 <string> 頭文件中 , 屬于 std 命名空間。使用 string 類時 , 需包含頭文件 <string> , 并通常通過 using namespace std; (或指定 std::string) 來使用。它封裝了字符串的存儲與操作 , 無需像 C 語言字符數組那樣手動管理內存(如擴容 , 越界等問題)。
3.2 基本語法
1. 包含頭文件與命名空間
要使用 string 類 , 需包含頭文件 <string> , 且通常使用 std 命名空間(也可通過 std::string 顯式指定):
#include <string> using namespace std; // 或使用 std::string
2. 字符串的初始化
- 默認初始化:創(chuàng)建空字符串。
string str1;
- 用字符串字面量初始化:
string str2 = "hello";
string str3("world");- 用部分字符初始化 : string(const char* s, size_t n) , 從字符串 s 的開頭取 n 個字符初始化。
string str4("abcdef", 3); // str4 為 "abc"- 用重復字符初始化 : string(size_t n, char c) , 創(chuàng)建包含 n 個字符 c 的字符串。
string str5(5, 'a'); // str5 為 "aaaaa"
- 拷貝初始化 : 用另一個 string 對象初始化。
string str6 = str2; // str6 為 "hello"
3. 字符串的基本操作
(1) 長度與容量
- size() / length() : 獲取字符串長度(字符個數) , 二者功能一致。
string str = "hello"; cout << str.size() << endl; // 輸出 5 cout << str.length() << endl; // 輸出 5
- capacity() :獲取字符串當前已分配的內存能容納的字符數(不包含結尾 \0 )。
cout << str.capacity() << endl;
- empty() :判斷字符串是否為空 , 空返回 true , 否則返回 false。
if (str.empty())
{
cout << "字符串為空" << endl;
} else
{
cout << "字符串不為空" << endl;
}- resize(size_t n, char c = '\0') :調整字符串長度為 n , 若 n 大于原長度 , 新增字符用 c 填充 , 若 n 小于原長度 , 截斷字符串。
str.resize(8, 'x'); // str 變?yōu)?"helloxxx" str.resize(3); // str 變?yōu)?"hel"
(2) 訪問字符
- 下標訪問( [] ):通過索引訪問字符 , 類似數組 , 索引從 0 開始。
string str = "hello"; cout << str[0] << endl; // 輸出 'h' str[1] = 'E'; // str 變?yōu)?"hEllo"
- 迭代器訪問:string 支持迭代器 , 可用于遍歷等操作。
for (string::iterator it = str.begin(); it != str.end(); ++it)
{
cout << *it << " ";
}- 也可結合 auto 簡化
for (auto it = str.begin(); it != str.end(); ++it)
{
cout << *it << " ";
}- 范圍 for 循環(huán)(C++11+) : 更簡潔地遍歷每個字符。
for (char c : str)
{
cout << c << " ";
}(3) 字符串拼接
- + 運算符:用于字符串與字符串 , 字符串與字符的拼接。
string str1 = "hello"; string str2 = " world"; string str3 = str1 + str2; // str3 為 "hello world" string str4 = str1 + '!'; // str4 為 "hello!"
- += 運算符:在原字符串后追加內容。
string str = "hello"; str += " world"; // str 為 "hello world" str += '!'; // str 為 "hello world!"
- append() 方法:功能類似 += , 也可追加部分字符。
str.append("test"); // 追加字符串 "test"
str.append("abcdef", 3); // 追加 "abcdef" 的前 3 個字符 "abc"(4) 字符串查找
- find(const string& str, size_t pos = 0) : 從位置 pos 開始查找子串 str , 返回第一次出現的起始索引 , 若未找到返回 string::npos (一個很大的無符號整數)。
string str = "hello world hello";
size_t pos = str.find("hello"); // 找到,返回 0
pos = str.find("hello", 1); // 從索引 1 開始找,返回 12
if (str.find("test") == string::npos)
{
cout << "未找到子串" << endl;
}- rfind(const string& str, size_t pos = npos) : 從位置 pos 開始反向查找子串 str ,回最后一次出現的起始索引。
size_t pos = str.rfind("hello"); // 返回 12- find_first_of(const string& str, size_t pos = 0) : 從位置 pos 開始 , 查找 str 中任意一個字符第一次出現的索引。
string str = "hello world";
size_t pos = str.find_first_of("aeiou"); // 找元音字母,返回 1('e' 的索引)- find_last_of(const string& str, size_t pos = npos) :從位置 pos 開始 , 查找 str 中任意一個字符最后一次出現的索引。
size_t pos = str.find_last_of("aeiou"); // 返回 7('o' 的索引)(5) 字符串截取與替換
- substr(size_t pos = 0, size_t len = npos) :從位置 pos 開始 , 截取長度為 len 的子串 , 若 len 為 npos 則截取到字符串末尾。
string str = "hello world"; string sub = str.substr(6, 5); // sub 為 "world" sub = str.substr(0, 5); // sub 為 "hello" sub = str.substr(6); // sub 為 "world"
- replace(size_t pos, size_t len, const string& str) :從位置 pos 開始 , 替換長度為 len 的子串為 str。
string str = "hello world"; str.replace(6, 5, "C++"); // str 變?yōu)?"hello C++"
(6) 字符串比較
- 關系運算符( == 、 != 、 < 、 > 、 <= 、 >= ):按字典序比較兩個字符串。
string str1 = "abc";
string str2 = "abd";
if (str1 < str2)
{
cout << "str1 小于 str2" << endl;
}- compare(const string& str) :比較當前字符串與 str , 返回值:
- 小于 0:當前字符串小于 str;
- 等于 0:兩者相等;
- 大于 0:當前字符串大于 str。
int res = str1.compare(str2);
if (res < 0)
{
cout << "str1 < str2" << endl;
}(7) 字符串的插入與刪除
- insert(size_t pos, const string& str) :在位置 pos 插入字符串 str。
string str = "hello"; str.insert(5, " world"); // str 變?yōu)?"hello world"
- erase(size_t pos = 0, size_t len = npos) :從位置 pos 開始 , 刪除長度為 len 的子串 , 若 len 為 npos 則刪除到字符串末尾。
string str = "hello world"; str.erase(5, 6); // 刪除從索引 5 開始的 6 個字符,str 變?yōu)?"hello" str.erase(2); // 刪除從索引 2 開始到末尾的字符,str 變?yōu)?"he"
4. 其他常用操作
- 清空字符串: clear() , 將字符串變?yōu)榭铡?/p>
string str = "hello"; str.clear();
- 交換字符串: swap(string& str) , 交換兩個字符串的內容。
string str1 = "hello"; string str2 = "world"; str1.swap(str2); // str1 變?yōu)?"world",str2 變?yōu)?"hello"
掌握這些 string 類的語法和操作 , 能滿足大部分字符串處理的需求 , 讓 C++ 中的字符串操作更加高效和簡潔。
3.3 訪問和修改字符
在 C++ 中 , 訪問 std::string 字符主要有下標訪問、迭代器訪問、范圍 for 循環(huán)、結合 auto 的遍歷這幾種方式 , 下面分別詳細講解:
1. 下標訪問( [] 運算符)
std::string 重載了 [] 運算符,支持像數組一樣通過索引訪問單個字符,索引從 0 開始,到 size() - 1 結束。
語法形式:
char& string::operator[](size_t pos); // 非 const 版本,可修改字符 const char& string::operator[](size_t pos) const; // const 版本,僅讀取
特點與使用場景:
- - 優(yōu)點 : 語法簡潔 , 像操作數組一樣直觀 , 訪問效率高(直接通過索引定位內存)。
- - 缺點:
- - 不做范圍檢查 , 若 pos 超出 [0, size()-1] , 會導致未定義行為(如程序崩潰、亂碼等)。
- - 只能訪問單個字符 , 遍歷所有字符時需手動控制索引。
示例:
#include <string>
#include <iostream>
using namespace std;
int main()
{
string str = "hello";
// 訪問單個字符
cout << str[0] << endl; // 輸出 'h'
// 修改字符
str[1] = 'E';
cout << str << endl; // 輸出 "hEllo"
// 遍歷所有字符(需手動控制索引)
for (size_t i = 0; i < str.size(); ++i)
{
cout << str[i] << " ";
}
// 輸出:h E l l o
return 0;
}2. 迭代器訪問
迭代器是 STL 中連接容器和算法的“橋梁” , std::string 提供了迭代器來遍歷字符 , 支持多種迭代器類型(如正向迭代器、反向迭代器、const 迭代器等)。
迭代器類型:
- string::iterator :正向迭代器,支持讀寫操作。 - string::const_iterator :const 正向迭代器,僅支持讀操作(用于 const string )。 - string::reverse_iterator :反向迭代器,從后往前遍歷。 - string::const_reverse_iterator :const 反向迭代器。
常用迭代器方法
- begin()/cbegin() :返回指向字符串首字符的迭代器(cbegin() 返回 const_iterator )。 - end()/cend() :返回指向字符串**末尾(最后一個字符的下一個位置)**的迭代器。 - rbegin()/crbegin() :返回指向字符串最后一個字符的反向迭代器。 - rend()/crend() :返回指向字符串首字符前一個位置的反向迭代器。
特點與使用場景:
- - 優(yōu)點:
- - 通用:符合 STL 迭代器規(guī)范 , 可與 STL 算法(如 std::sort , std::find )無縫配合。
- - 安全:遍歷邏輯由迭代器封裝 , 不易因索引錯誤導致越界。
- - 靈活:支持正向、反向等多種遍歷方式。
- - 缺點:語法比下標訪問復雜 , 新手可能需要適應。
示例
#include <string>
#include <iostream>
using namespace std;
int main()
{
string str = "hello";
// 正向迭代器(讀寫)
for (string::iterator it = str.begin(); it != str.end(); ++it)
{
*it = toupper(*it); // 轉大寫
}
cout << str << endl; // 輸出 "HELLO"
// const 正向迭代器(只讀,用于 const string)
const string constStr = "world";
for (string::const_iterator cit = constStr.cbegin(); cit != constStr.cend(); ++cit)
{
cout << *cit << " ";
}
// 輸出:w o r l d
// 反向迭代器
for (string::reverse_iterator rit = str.rbegin(); rit != str.rend(); ++rit)
{
cout << *rit << " ";
}
// 輸出:O L L E H
return 0;
}3. 范圍for循環(huán)(C++11及以上)
范圍 for 是 C++11 引入的語法糖 , 專門用于遍歷容器(如 std::string , STL 容器)或數組的所有元素,語法非常簡潔。
語法形式:
for (元素類型 變量名 : 容器/數組)
{
// 操作變量名
}特點與使用場景:
- - 優(yōu)點:
- - 語法極簡:無需手動控制索引或迭代器, 直接遍歷所有元素。
- - 安全:由編譯器保證遍歷范圍的正確性 , 不會越界。
- - 缺點:
- - 僅支持順序遍歷 , 無法靈活控制遍歷方向(如反向)。
- - 若需要修改字符 , 需注意是否用引用(否則是值拷貝 , 修改不影響原字符串)。
示例:
#include <string>
#include <iostream>
using namespace std;
int main()
{
string str = "hello";
// 只讀遍歷(值拷貝)
for (char c : str)
{
cout << c << " ";
}
// 輸出:h e l l o
// 讀寫遍歷(引用)
for (char& c : str)
{
c = toupper(c); // 轉大寫,修改原字符串
}
cout << str << endl; // 輸出 "HELLO"
// const 字符串的只讀遍歷
const string constStr = "world";
for (char c : constStr)
{
cout << c << " ";
}
// 輸出:w o r l d
return 0;
}4. 結合 auto 的遍歷
auto 是 C++11 引入的類型推導關鍵字 , 可讓編譯器自動推導變量類型。結合迭代器或范圍 for 時 , 能進一步簡化代碼。
與迭代器結合 : 利用 auto 推導迭代器類型 , 避免寫冗長的 string::iterator 等類型名。
示例:
#include <string>
#include <iostream>
using namespace std;
int main()
{
string str = "hello";
// 正向迭代器(auto 推導類型)
for (auto it = str.begin(); it != str.end(); ++it)
{
*it = toupper(*it);
}
cout << str << endl; // 輸出 "HELLO"
// 反向迭代器(auto 推導類型)
for (auto rit = str.rbegin(); rit != str.rend(); ++rit)
{
cout << *rit << " ";
}
// 輸出:O L L E H
return 0;
}與范圍 for 結合 : 用 auto 推導范圍 for 中元素的類型,進一步簡化代碼。
示例:
#include <string>
#include <iostream>
using namespace std;
int main()
{
string str = "hello";
// 只讀遍歷(auto 推導為 char)
for (auto c : str)
{
cout << c << " ";
}
// 輸出:h e l l o
// 讀寫遍歷(auto& 推導為 char&)
for (auto& c : str)
{
c = toupper(c);
}
cout << str << endl; // 輸出 "HELLO"
// const 字符串的只讀遍歷(auto 推導為 char)
const string constStr = "world";
for (auto c : constStr)
{
cout << c << " ";
}
// 輸出:w o r l d
return 0;
}總結:四種方式的對比與選擇
實際開發(fā)中 , 建議優(yōu)先使用范圍 for + auto(簡潔且安全);若需復雜遍歷(如反向、與 STL 算法配合) , 則用迭代器 + auto;僅需隨機訪問單個字符時 , 再考慮下標訪問。
4. 總結:
STL(標準模板庫)是C++標準庫的重要組成部分 , 提供通用數據結構和算法 , 基于模板技術實現泛型編程。STL包含六大組件, , 如容器、算法、迭代器等 , 能提高開發(fā)效率、保證性能并促進代碼標準化。string類雖不屬于STL核心 , 但常與STL配合使用 , 提供強大的字符串操作功能 , 包括初始化、訪問、修改、查找、拼接等。學習STL和string類需掌握模板語法、核心容器使用、算法實踐及底層原理 , 建議通過實際項目應用加深理解。
到此這篇關于C++ string類詳解(STL簡介, string類,訪問修改字符)的文章就介紹到這了,更多相關C++ string類內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
2022最新使用VSCode編譯運行C++的過程及會遇到的兩個問題
這篇文章主要介紹了2022最新使用VSCode編譯運行C++的過程及會遇到的兩個問題,這里需要注意把剛才解壓的地址加上\bin添加進去,比如我的:D:\aaakkk\cpp\mingw64\bin,然后點確定,注意一定要確保它被保存了,感興趣的朋友跟隨小編一起看看吧2022-09-09

