為什么我們要學(xué)string類呢?那是必須是為了方便??!在C語言中,我們創(chuàng)建一個字符串,有很多操作或者必須要注意的細節(jié)會把控不住,所以C++中出現(xiàn)了string類,讓我們應(yīng)對字符串等oj題也方便快捷了許多!
創(chuàng)新互聯(lián)提供高防服務(wù)器、云服務(wù)器、香港服務(wù)器、達州電信機房等目錄
一、STL的介紹
二、標(biāo)準(zhǔn)庫中的string類
1、簡介string?編輯
2、庫中的string類的常用接口說明?編輯
1.構(gòu)造函數(shù)
?2.npos?
?3.遍歷?
3.capacity
1.size,lenth,max_size,capacity
2.shrink_to_fit
3.reserve、resize(重點)
4.operator[],at
5、Modifiers
1.push_back, append, operator+=
2.insert,erase
???3.assign,replace(不重要)
4.find,c_str,substr
總結(jié)?
string是一個模板,是因為編碼不同,導(dǎo)致char的字節(jié)數(shù)不同,所以需要模板來適應(yīng)不同的編碼類型,原型差不多就是這樣的:
我們接下來研究的:utf-8,char為一個字節(jié)的string類
?2、庫中的string類的常用接口說明1.構(gòu)造函數(shù)在學(xué)習(xí)任何類之前,當(dāng)然要先看它的構(gòu)造函數(shù)了?。ㄎ覀冎涣私庵匾页S玫模?/p>
構(gòu)造函數(shù):直接上例子:
可以看得出,s1為默認的構(gòu)造函數(shù)
s2是帶參的構(gòu)造函數(shù)(理解:會開辟一段空間,將內(nèi)容存起來)
s3的構(gòu)造方式,會發(fā)生隱式類型轉(zhuǎn)換,會產(chǎn)生臨時變量,先構(gòu)造,再拷貝構(gòu)造,優(yōu)化后就是構(gòu)造
s4構(gòu)造是用n個char c 字符去初始化
拷貝構(gòu)造:自定義類型拷貝會發(fā)生深拷貝,所以形參一般要用引用減少拷貝,提高效率
s5,s6都是拷貝構(gòu)造
npos是一個靜態(tài)成員變量,無符號整型,是一個極大的數(shù)。
對于這個構(gòu)造函數(shù),是在str的pos位置開始向后len的長度,這段字符串進行初始化。
那默認不傳len,len的值就是npos,是一個非常大的數(shù),當(dāng)len大于str的長度時,默認到了str的最后一位。
3.遍歷?共有三種遍歷方式:
void test2() { string s1("12345678"); // 1、下標(biāo) [] for (size_t i = 0; i< s1.size(); ++i) { s1[i]++; } cout<< s1<< endl; // 2、范圍for for (auto& ch : s1) { ch--; } cout<< s1<< endl; // 3、迭代器 -- 通用的訪問形式 string::iterator it1 = s1.begin(); while (it1 != s1.end()) { *it1 += 1; ++it1; // 把string里的內(nèi)容每一個都加了一 } it1 = s1.begin(); while (it1 != s1.end()) { cout<< *it1<< " "; //打印每一個內(nèi)容 ++it1; } cout<< endl; }
可以看的出:operator[]有兩個接口,一個是有const,一個沒有const
operator[],是一個可讀且可寫的接口。
當(dāng)const只讀對象調(diào)用時,就會調(diào)用const接口
當(dāng)只寫對象調(diào)用時,就會調(diào)用非const,
所以對于即可寫又可讀的接口函數(shù)來說,就有兩個版本,const和非const
還有一點:operator[]內(nèi)部有防止越界訪問的功能:assert(pos<=size);
迭代器的遍歷方法:
這里的迭代器是string類的自定義的一種類型,需要string::
迭代器我們現(xiàn)在可以看作是 和指針相差不多的東西(行為像指針),但他又不是指針,具體的底層我們后面會見面。
begin()就是指向第一個位置,end()指向最后一個有效字符的下一個位置
迭代器要注意的地方:
我們可以看到:迭代器也分為const和非const,那什么時候分別用哪個呢?
const_iterator:只能在const對象下使用,并且const迭代器可以改變迭代器本身,但不能改變迭代器所指向的內(nèi)容?
迭代器有正向迭代器和反向迭代器:
void Print(const string& s) { // 只讀不寫,可以遍歷改變it,但不能改變他指向內(nèi)容 string::const_iterator it = s.begin(); //正向迭代器 while (it != s.end()) { // *it += 1; 錯誤! cout<< *it<< " "; ++it; //正向迭代器就是正著迭代++ } } cout<< endl; //string::const_reverse_iterator rit = s.rbegin(); auto rit = s.rbegin(); //反向迭代器 while (rit != s.rend()) { cout<< *rit<< " "; ++rit; //都是++,這里不可以類比指針反向迭代器就是反著迭代++ } cout<< endl; }
學(xué)會了嗎?
在string中,我們會怎么描述字符串長度??length是不是更貼合,那為什么又有size呢??
因為string是早于stl的,在它之后size更普遍適用,為了普遍化,那只能添加一個size了
size==length,就是求長度或者字符個數(shù)。(length淘汰!?。?/p>
只讀接口,加const
capacity:string的容量,和size可不相同。
clear:因為stl只是規(guī)范了每個接口名字或者參數(shù),但并沒有將每一個容器函數(shù)的細節(jié)拿捏死,所以對于clear,我們并不知道他清空數(shù)據(jù)以后,是否還要回收空間。得需要驗證!
void test4()
{
string s("hello world");
cout<< s.size()<< endl;
cout<< s.length()<< endl;
cout<< s.capacity()<< endl;
s.clear();
cout<< s<< endl;
cout<< s.capacity()<< endl;
}
可以發(fā)現(xiàn),clear之后并沒有回收空間,也不會縮容
empty(),就是來判空的
當(dāng)capacity大于size時,將size和capacity保持一致,會縮容,但縮容代價還是挺大的,一般也不這么搞。
只改變capacity
在我們知道需要多少空間時,插入數(shù)據(jù),為了防止反復(fù)擴容(擴容代價大),我們可以提前預(yù)留空間,開辟好。
那到底是怎么擴的呢??一次擴多少?
我們在vs和g++上分別測試得出:vs上面會1.5倍擴容,但是存在內(nèi)存對齊問題,會有些許偏差,但空間還是大于我們要開辟的。g++就是2倍擴容,要多少擴多少,不會有偏差。
第一次預(yù)留500,第一次擴容到766,第二次擴容1149,差不多就是1.5倍
?4.operator[],atresize:它改變的是?size
當(dāng)n不同,resize會分為三種情況:(n為size改變后的值)
舉例說明:
void test6() { //當(dāng)n
capacity, (擴容+插入數(shù)據(jù)) string s3("hello world"); s3.resize(20, '#'); cout<< s3.size()<< endl; cout<< s3.capacity()<< endl; cout<< s3<< endl<< endl; } 所以resize功能還是比較完善健全的。
他們是一樣的,都是讀寫到string中的某個值,進行操作。
但是區(qū)別在于:當(dāng)發(fā)生越界時,operator[]會直接assert()報警告;而at則會拋異常(后面我們會詳細了解)
5、Modifiers 1.push_back, append, operator+=2.insert,erase插入:
push_back :尾插
下面通過舉例來觀察:?
void test7() { //push_back string s1("hello world"); s1.push_back('x'); s1.push_back('y'); cout<< s1<< endl; //append string s2("1111111111"); s2.append(s1); cout<< s2<< endl; //operator+= string s3("666"); s3 += ' '; s3 += "hello world"; s3 += s2; cout<< s3<< endl; }
適用于頭插,頭刪,中間插入和刪除
但這兩種函數(shù)我們都不建議經(jīng)常使用,因為它的效率很低,在刪除或者插入時,就會有數(shù)據(jù)挪動,效率很低。
?3.assign,replace(不重要)void test8() { string s("hello world"); s.insert(0, "bit"); cout<< s<< endl; s.erase(0, 3); cout<< s<< endl; s.insert(5, "bit"); cout<< s<< endl; s.erase(5,3); cout<< s<< endl; s.erase(5); //第二個參數(shù)不提供,默認是npos,直接從pos刪到最后一個。 cout<< s<< endl; }
4.find,c_str,substrassign(功能):先clear,再賦值?
replace:替換內(nèi)容
void test9() { string s("3456789"); s.assign("1234"); cout<< s<< endl; string s1("hello world"); s1.replace(6, 10, "666"); cout<< s1; }
find:也有缺省值,默認不提供,直接找到最后一個
c_str:取出C形式字符串(底層指針)
substr:取出str的一部分,再將其構(gòu)建成新對象返回
getline:輸入可以中間帶空格的字符串
這就是我們經(jīng)常要用到的函數(shù)接口,更底層的內(nèi)容,需要我們在模擬實現(xiàn)的時候,去好好感悟,下期再見!
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧