📝個人主頁🌹:Eternity._
?收錄專欄?:C++ “ 登神長階 ”
🤡往期回顧🤡:C++模板入門
🌹🌹期待您的關注 🌹🌹
?STL之string
- 📒1. STL基本介紹
- 🎈STL的版本
- 🎩STL的缺陷
- 📒2. string類的基本概念
- 📒3. string類的常用操作
- 🌈string類對象的常見構造
- 🌞string類對象的容量操作
- 🌙string類對象的訪問及遍歷操作
- ?string類對象的修改操作
- 📒4. 總結拓展
- 🔥拓展:getline
- 💧總結
前言:STL(Standard Template Library,標準模板庫)是C++標準庫的重要組成部分,它提供了一系列通用的數據結構和算法。在STL中,string類是一個非常重要的容器,用于處理字符串數據。本文將詳細介紹STL中的string類,包括其基本概念、常用操作以及使用示例
STL的六大組件
📒1. STL基本介紹
🎈STL的版本
- 原始版本
Alexander Stepanov、Meng Lee 在惠普實驗室完成的原始版本,本著開源精神,他們聲明允許任何人任意運用、拷貝、修改、傳播、商業使用這些代碼,無需付費。唯一的條件就是也需要向原始版本一樣做開源使用。 HP 版本–所有STL實現版本的始祖。- P. J. 版本
由P. J. Plauger開發,繼承自HP版本,被Windows Visual C++采用,不能公開或修改,缺陷:可讀性比較低,符號命名比較怪異。- RW版本
由Rouge Wage公司開發,繼承自HP版本,被C+ + Builder 采用,不能公開或修改,可讀性一般。- SGI版本
由Silicon Graphics Computer Systems,Inc公司開發,繼承自HP版 本。被GCC(Linux)采用,可移植性好,可公開、修改甚至販賣,從命名風格和編程 風格上看,閱讀性非常高。我們后面學習STL要閱讀部分源代碼,主要參考的就是這個版本
🎩STL的缺陷
- STL庫的更新太慢了。這個得嚴重吐槽,上一版靠譜是C++98,中間的C++03基本一些修訂。C++11出來已經相隔了13年,STL才進一步更新。
- STL現在都沒有支持線程安全。并發環境下需要我們自己加鎖。且鎖的粒度是比較大的。
- STL極度的追求效率,導致內部比較復雜。比如類型萃取,迭代器萃取。
- STL的使用會有代碼膨脹的問題,比如使用vector/vector/vector這樣會生成多份代碼,當然這是模板語法本身導致的
📒2. string類的基本概念
string類是一個模板類,專門用于處理字符串數據。 在C++中,字符串是由一系列字符組成的序列,而string類則提供了對這些字符序列進行高效操作的功能。與傳統的C語言風格字符串(以\0結尾的字符數組)相比,string類更加安全和易用,因為它會自動管理內存,并提供了豐富的成員函數來操作字符串
string類成員函數:
class string
{
private:char* ——str;int _capacity;int _size;
};
📒3. string類的常用操作
🌈string類對象的常見構造
函數名稱 | 功能說明 |
---|---|
string() | 構造空的string類對象,即空字符串 |
string(const char* s) | 用const對象來構造string類對象 |
string(size_t n, char c) | string類對象中包含n個字符c |
string(s.begin(), s.end()) | 用迭代區間構造 |
string(const string&s) | 拷貝構造函數 |
int main()
{string s1(); // 空字符串string s2("hello world"); // const對象構造string類對象string s3(10, 'x'); // n個字符c構造string s4(s2.begin(), s2.end()); // 用迭代區間構造string s5 = s2; // 拷貝構造return 0;
}
注意:在這里迭代器類似于指針!
🌞string類對象的容量操作
函數名稱 | 功能說明 |
---|---|
size | 返回字符串有效字符長度 |
length | 返回字符串有效字符長度 |
capacity | 返回空間總大小 |
empty | 檢測字符串釋放為空串,是返回true,否則返回false |
clear | 清空有效字符 |
reserve | 為字符串預留空間 |
resize | 將有效字符的個數該成n個,多出的空間用字符c填充 |
int main()
{string s("hello world");// 返回字符串有效字符長度cout << s.size() << endl;cout << s.length() << endl;// 返回空間總大小cout << s.capacity() << endl;// 檢測字符串釋放為空串,是返回true,否則返回falsecout << s.empty() << endl;// 清空有效字符s.clear();cout << "clear after: " << s << endl;// 為字符串預留空間s.reserve(100); // 一般會多預留空間cout << "reserve(100)after: " << s.size() << endl;cout << "reserve(100)after: " << s.capacity() << endl;cout << endl;// 將有效字符的個數該成n個,多出的空間用字符c填充s.resize(100);cout << "resize(100)after: " << s.size() << endl;cout << "resize(100)after: " << s.capacity() << endl;return 0;
}
注意:
- size()與length()方法底層實現原理完全相同,引入size()的原因是為了與其他容器的接口保持一致,一般情況下基本都是用size()。
- clear()只是將string中有效字符清空,不改變釋放空間
- reserve()只會變大,如果是將元素個數減少,底層空間總大小不變
- resize在改變元素個數時,如果是將元素個數增多,可能會改變底層容量的大小,如果是將元素個數減少,底層空間總大小不變
🌙string類對象的訪問及遍歷操作
函數名稱 | 功能說明 |
---|---|
operator[ ] | 返回pos位置的字符,const string類對象調用 |
begin+ end begin | 獲取一個字符的迭代器 + end獲取最后一個字符下一個位置的迭代器 |
rbegin + rend begin | 獲取一個字符的迭代器 + end獲取最后一個字符下一個位置的迭器 |
范圍for | C++11支持更簡潔的范圍for的新遍歷方式 |
int main()
{string s("hello world");for (int i = 0; i < s.size(); i++){cout << s[i];}cout << endl;// 迭代器string::iterator it = s.begin();while (it != s.end()){cout << *it;it++;}cout << endl;// 范圍forfor (auto ch : s){cout << ch;}cout << endl;return 0;
}
關于迭代器
迭代器的用法像指針一樣能夠+–也可以解引用拿到指向的內容
?string類對象的修改操作
函數名稱 | 功能說明 |
---|---|
push_back | 在字符串后尾插字符c |
append | 在字符串后追加一個字符串 |
operator+= | 在字符串后追加字符串str |
c_str | 返回C格式字符串 |
find + npos | 從字符串pos位置開始往后找字符c,返回該字符在字符串中的位置 |
rfind | 從字符串pos位置開始往前找字符c,返回該字符在字符串中的位置 |
substr | 在str中從pos位置開始,截取n個字符,然后將其返回 |
注意:npos是無符號的整形,值為-1,npos是int的最大值
int main()
{string s1("h");// 插入字符s1.push_back('e');//插入字符串s1.append("llo ");s1 += "world";// 將s1變成 hello world//c_str函數返回字符串從\0結尾的字符串,但是c++中的字符串不一定s1 += '\0';s1 += "aaa";cout << s1 << endl; // hello worldaaacout << s1.c_str() << endl; // hello world// find 從pos位置開始查找字符并返回其位置// rfind 從pos位置開始往前查找字符并返回其位置int ret = s1.find('l',3);cout << s1[++ret] << endl; // o//substr 從ret位置開始截取pos個字符,如果pos不傳參數將會截取到最后string s2 = s1.substr(0);cout << s2 << endl; // hello worldaaareturn 0;
}
這里要注意的是:
c_str
,C格式字符串是以’\0’結尾的但是C++里面不一定substr
,當我們沒有結束位置時,它會遍歷完整個字符串- 關于修改操作其實還有
insert
和erase
,但是這兩個涉及挪動數據,效率不高,能不用就不用
string s1("hello world!!!");
// 頭插
s1.insert(0, 1, 'x');
// 刪除
s1.erase(0,5);
我們來查閱一下這三個函數
insert
可以在pos位置插入一個字符,一個字符串或者一個string類甚至還可以指定插入字符串的長度,insert接口有很多
erase
可以刪除從pos位置往后len個字符,如果pos不傳參數,則從0位置刪除npos個
📒4. 總結拓展
🔥拓展:getline
getline
是用于從輸入流中讀取一行字符串并保存到指定的字符串變量中的函數,直到遇到換行符或達到指定的最大字符數
代碼演示:
int main()
{string s;getline(cin, s);cout << s << endl;cout << endl;cin >> s;cout << s << endl;return 0;
}
💧總結
在深入學習和掌握了STL中string類的運用后,我們可以深刻感受到C++在處理字符串時的靈活性和高效性。通過合理利用string提供的各種成員函數和特性,實現更加高效且易于維護的代碼。對于學習后面的STL容器也有很大幫助!
謝謝大家支持本篇到這里就結束了,祝大家天天開心!