百度做網(wǎng)站一鍵優(yōu)化清理加速
🔥博客主頁(yè):小王又困了
📚系列專欄:C++
🌟人之為學(xué),不日近則日退
??感謝大家點(diǎn)贊👍收藏?評(píng)論??
目錄
一、string類介紹
二、string類的常用接口說明
📒2.1string類對(duì)象的常見構(gòu)造
📒2.2string類對(duì)象的容量操作
📒2.3string類對(duì)象的訪問及遍歷操作
📒2.4string類對(duì)象的修改操作
?編輯
📒2.5string類對(duì)象的查找接口
📒2.6string類非成員函數(shù)
🗒?前言:
C語(yǔ)言中,字符串是以'\0'結(jié)尾的一些字符的集合,為了操作方便,C標(biāo)準(zhǔn)庫(kù)中提供了一些str系列的庫(kù)函數(shù), 但是這些庫(kù)函數(shù)與字符串是分離開的,不太符合OOP的思想,而且底層空間需要用戶自己管理,稍不留神可能還會(huì)越界訪問。C++中引入了string類,給我們提供了便利。
一、string類介紹
- string是表示字符串的字符串類
- string類的接口與常規(guī)容器的接口基本相同,再添加了一些專門用來操作string的常規(guī)操作。
- string在底層實(shí)際是:basic_string模板類的別名,typedef basic_string string;。
- 不能操作多字節(jié)或者變長(zhǎng)字符的序列。
小Tips:在使用string類時(shí),必須包含#include頭文件以及using namespace std;。
二、string類的常用接口說明
📒2.1string類對(duì)象的常見構(gòu)造
🎀string()
? ? 構(gòu)造空的string類對(duì)象,即空字符串。
int main() {string s1;cout << s1 << endl;return 0; }
🎀string(const char* s)
? ??用一個(gè)C的字符串(或字符數(shù)組)來構(gòu)造一個(gè)string類的對(duì)象。
int main() {string s1("hellow world");cout << s1 << endl;return 0; }
🎀string(size_t n, char c)
? ??用?n?個(gè)字符來構(gòu)建string類對(duì)象。
int main() {string s1(5, 'x');cout << s1 << endl;return 0; }
🎀string(const string&s)
? ? ?string類的拷貝構(gòu)造,用于構(gòu)建一個(gè)和存在的s1一模一樣的對(duì)象。
int main() {string s1(5, 'x');string s2(s1);cout << s2 << endl;return 0; }
🎀string(const string& str,size_t pos,size_t len=npos)
? ? 復(fù)制str從pos位置開始len個(gè)字符的部分,使用一個(gè)已存在的string類對(duì)象的一部分來創(chuàng)建一個(gè)新的string類對(duì)象。
小Tips:nops是string類里面的一個(gè)靜態(tài)成員變量,它是size_t類型,初始化為-1,即表示整型的最大值。
int main() {string s1("hellow world");string s2(s1, 7, 5);cout << s2 << endl;return 0; }
🎀string(const char* s,size_t n)
? ? 用 s 所指向字符串(或字符數(shù)組)的前 n 個(gè)字符來初始化創(chuàng)建一個(gè)string類對(duì)象。
int main() {char s[] = "hellow ,world";string s1(s, 6);cout << s1 << endl;return 0; }
📒2.2string類對(duì)象的容量操作
🎀size()
? ??返回字符串有效字符長(zhǎng)度
int main() {string s1("hellow world");string s2("hellow C++");cout << s1.size() << endl;cout << s2.size() << endl;return 0; }
🎀length()
? ??返回字符串有效字符長(zhǎng)度
int main() {string s1("hellow world");string s2("hellow C++");cout << s1.length() << endl;cout << s2.length() << endl;return 0; }
小Tips:size()與length()方法底層實(shí)現(xiàn)原理完全相同,引入size()的原因是為了與其他容器的接口保持一致,一般情況下基本都是用size()。
🎀capacity()
? ? 返回string對(duì)象空間的總大小。
int main() {string s1("hellow world");string s2("hellow world xxxxxxx");cout << s1.capacity() << endl;cout << s2.capacity() << endl;return 0; }
小Tips:capacity()會(huì)返回對(duì)象空間的總大小,這個(gè)空間是存儲(chǔ)有效字符的空間,實(shí)際上會(huì)多開辟一個(gè)空間,存儲(chǔ)‘\0’。同一個(gè)對(duì)象在不同的環(huán)境開辟的空間不同,在不同環(huán)境下擴(kuò)容機(jī)制也不同。
📖VS下的擴(kuò)容機(jī)制
int main() {string s1("hellow world");size_t old = s1.capacity();cout << old << endl;for (size_t i = 0; i < 100; i++){s1.push_back('x');if (old != s1.capacity()){cout << s1.capacity() << endl;old = s1.capacity();}}return 0; }
VS下默認(rèn)開辟15個(gè)空間用來存儲(chǔ)數(shù)據(jù)(本質(zhì)上是開16個(gè)空間,因?yàn)檫€要存‘/0’),第一次擴(kuò)容是2倍,后面都是以1.5倍的大小去擴(kuò)容。?
📖Linux下的擴(kuò)容機(jī)制
在Linux環(huán)境下最初對(duì)象需要多少空間就開多少,后面一次按照2倍的大小進(jìn)行擴(kuò)容。
🎀reserve(size_t n = 0)
? ??為字符串預(yù)留空間。直接一次開辟n個(gè)空間,可以用來存儲(chǔ)n個(gè)有效字符,可以避免每次都要去擴(kuò)容。
int main() {string s1("hellow world");s1.reserve(100);size_t old = s1.capacity();cout << s1.capacity() << endl;for (size_t i = 0; i < 100; i++){s1.push_back('x');if (old != s1.capacity()){cout << s1.capacity() << endl;old = s1.capacity();}}return 0; }
小Tips:當(dāng)我們確定需要多少空間,就可以使用reserve()提前開辟好空間即可,可以減少擴(kuò)容次數(shù),?大部分的擴(kuò)容都是異地?cái)U(kuò)容,擴(kuò)容次數(shù)過多會(huì)影響效率。
🎀resize(size_t n = 0, char c)
? ??resize(size_t n)與resize(size_t n, char c)都是將字符串中有效字符個(gè)數(shù)改變到n個(gè),當(dāng)n小于當(dāng)前字符串的長(zhǎng)度size(),會(huì)保留前n個(gè)字符,將第n個(gè)字符后面的所以字符刪除;當(dāng)n大于當(dāng)前字符串的長(zhǎng)度size(),先會(huì)進(jìn)行擴(kuò)容,不同的是當(dāng)字符個(gè)數(shù)增多時(shí):resize(size_t n)用‘\0’來填充多出的元素空間,resize(size_t n, char c)用字符c來填充多出的元素空間。
int main() {string s1("hellow world");cout << s1 << endl;cout << s1.size() << endl;cout << s1.capacity() << endl;s1.resize(100,'x');cout << s1 << endl;cout << s1.size() << endl;cout << s1.capacity() << endl;return 0; }
小Tips:resize在改變?cè)貍€(gè)數(shù)時(shí),如果是將元素個(gè)數(shù)增多,可能會(huì)改變底層容量的大小,如果是將元素個(gè)數(shù)減少,底層空間總大小不變。 reserve只會(huì)影響容量,不改變有效元素個(gè)數(shù),當(dāng)reserve的參數(shù)小于string的底層空間總大小時(shí),reserver不會(huì)改變?nèi)萘看笮?即不會(huì)縮容。
- reserve只影響容量,不影響數(shù)據(jù)
- resize既影響容量,也影響數(shù)據(jù)
🎀clean()
? ? 清理有效字符,不改變?nèi)萘看笮?/span>
int main() {string s1("Hello C++!");cout << "清空之前的size:" << s1.size() << endl;cout << "清空之前的capacity:" << s1.capacity() << endl;s1.clear();cout << "清空之后的size:" << s1.size() << endl;cout << "清空之后的capacity:" << s1.capacity() << endl;return 0; }
小Tips:clear()只是將string中有效字符清空,不改變底層空間大小。
📒2.3string類對(duì)象的訪問及遍歷操作
🎀operator()
? ??返回pos位置的字符
int main() {string s1 = "hellow world";for (size_t i = 0; i < s1.size(); i++){cout << s1[i];}cout << endl;return 0; }
小Tips:如果字符串是const限定的,則該函數(shù)返回const char&。否則,它將返回char&。at借口與operator[]借口功能類型,operator[]接口發(fā)生越界訪問,程序會(huì)直接報(bào)錯(cuò);at接口發(fā)生越界訪問的時(shí)候會(huì)拋出異常。
🎀begin、end/rebegin、rend
? ??begin獲取對(duì)象第一個(gè)字符的迭代器,end獲取對(duì)象最后一個(gè)字符下一個(gè)位置的迭代器
int main() {string s1 = "hellow world";string::iterator it = s1.begin();while (it != s1.end()){cout << *it;it++;}cout << endl;string::reverse_iterator it = s1.rbegin();//反向迭代器while (it != s1.rend()){cout << *it;it++;}cout << endl;return 0; }
如上代碼我們看到迭代器和指針的使用方法類似,都可以解引用和++,對(duì)象也可以修改。但迭代器的這些操作都是通過運(yùn)算符重載來實(shí)現(xiàn)的。
小Tips:迭代器區(qū)間永遠(yuǎn)都是左閉右開,迭代器類型作為類的內(nèi)置類型可以通過類名
::
itertator直接訪問,例如:string::
itertator就表示string類里面的迭代器類型。普通迭代器可讀可寫,const迭代器限制的是其指向的內(nèi)容,只能讀不能寫,而const迭代器本身可以修改。
🎀范圍for
int main() {string s1("Hello world");for (auto it : s1){cout << it;}cout << endl;return 0; }
?小Tips:范圍for就是基于迭代器實(shí)現(xiàn)的,在底層范圍for會(huì)轉(zhuǎn)化成正向迭代器。
📒2.4string類對(duì)象的修改操作
🎀push back
? ??在字符串后尾插字符c
int main() {string s1("Hello world");cout << "追加前:" << s1 << endl;s1.push_back('x');cout << "追加后:" << s1 << endl;return 0; }
🎀append
? ??在字符串后追加一個(gè)字符串,它有六種重載形式,如下圖所示:
int main() {string s1("Hello world");cout << "追加前:" << s1 << endl;s1.append("xxxxxxx");cout << "追加后:" << s1 << endl;string s2 = "abcdefg";cout << "追加前:" << s1 << endl;s1.append(s2, 2, 4);cout << "追加后:" << s1 << endl;return 0; }
🎀operator+=
? ??通過重載運(yùn)算符+=實(shí)現(xiàn)追加,該運(yùn)算符重載有三種重載實(shí)現(xiàn)形式,如下圖所示:
int main() {string s1("Hello world");cout << "追加前:" << s1 << endl;s1 += "xxxxxx";cout << "追加后:" << s1 << endl;string s3 = "abcdefg";string s2("Hello world");cout << "追加前:" << s2 << endl;s2 += s3;cout << "追加后:" << s2 << endl;return 0; }
小Tips:在string尾部追加字符的三種方式中,+=操作用的比較多,+=操作不僅可以連接單個(gè)字符,還可以連接字符串。
📒2.5string類對(duì)象的查找接口
🎀find
? ??從字符串的pos位置開始往后查找字符或字符串,返回其在當(dāng)前字符串中的位置。
int main() {string s1 = "hellow world";string s2 = "world";size_t pos = s1.find(s2);cout << pos << endl;return 0; }
?🎀substr
? ? ?在str中從pos位置開始,截取n個(gè)字符,然后將其返回
int main() {string s1 = "test.txt.cpp";size_t pos = s1.rfind('.');if (pos != string::npos){string s2 = s1.substr(pos);cout << s2 << endl;}return 0; }
📒2.6string類非成員函數(shù)
函數(shù)名稱 | 功能說明 |
operator+ | 盡量少用,因?yàn)閭髦捣祷?#xff0c;導(dǎo)致深拷貝效率低 |
operator>> | 輸入運(yùn)算符重載 |
operator<< | 輸出運(yùn)算符重載 |
getline | 獲取一行字符串 |
relational?operators | 大小比較 |
小Tips:operator>>和getline的區(qū)別在于,前者遇到空格‘? ’和換行‘\n’會(huì)截止,而后者默認(rèn)只有遇到換行‘\n’才截止,因此當(dāng)我們需要從鍵盤讀取一個(gè)含有空格的字符串是,只能用getline。
🎁結(jié)語(yǔ):?
? ? ?本次的內(nèi)容到這里就結(jié)束啦。希望大家閱讀完可以有所收獲,同時(shí)也感謝各位讀者三連支持。文章有問題可以在評(píng)論區(qū)留言,博主一定認(rèn)真認(rèn)真修改,以后寫出更好的文章。你們的支持就是博主最大的動(dòng)力。