?
?
🔥個人主頁:guoguoqiang. 🔥專欄:我與C++的愛戀
朋友們大家好啊,本節我們來到STL內容的第一部分:string類接口函數的介紹
?
?
1.string類的認識
給大家分享一個c++文檔
https://legacy.cplusplus.com/
- 字符串 string 是表示字符序列的類
- 標準的字符串類提供了對此類對象的支持,其接口類似于標準字符容器的接口,但添加了專門用于操作
單字節字符字符串的設計特性。 - string類是使用char(即作為它的字符類型,使用它的默認char_traits和分配器類型(關于模板的更多信
息,請參閱basic_string)。 - string類是basic_string模板類的一個實例,它使用char來實例化basic_string模板類,并用char_traits
和allocator作為basic_string的默認參數(根于更多的模板信息請參考basic_string)。 - 注意,這個類獨立于所使用的編碼來處理字節:如果用來處理多字節或變長字符(如UTF-8)的序列,這個
類的所有成員(如長度或大小)以及它的迭代器,將仍然按照字節(而不是實際編碼的字符)來操作。
總結: - string是表示字符串的字符串類
- 該類的接口與常規容器的接口基本相同,再添加了一些專門用來操作string的常規操作。
- string在底層實際是:basic_string模板類的別名,typedef basic_string<char, char_traits, allocator>string;
- 不能操作多字節或者變長字符的序列。
在使用string類時,必須包含#include頭文件以及using namespace std;
2.常見接口講解
2.1 string類對象的常見構造
string() 這個函數的功能是構建一個空字符串,也是默認構造。
string(const char*s) 用c—str來構造string類對象
用法:string s1("hello world");
string(const string&s) 拷貝構造函數
用法:
string s1("hello world"); string s2(s1);
`
string (const string& str, size_t pos, size_t len= npos);
拷貝從pos位置開始,向后len長度,如果超過剩余長度,則遍歷到字符串的末尾
注意,這里有個npos的缺省值,如果不給值,默認給npos,會遍歷到字符串末尾。
了解一下npos
npos是一個無符號常量整數-1,無符號整數-1即為整形的最大值2^32-1
用法:
string s1("hello world");
string s3(s1, 5, 3);
string s4(s1, 5, 10);
string s5(s1, 5);
cout << s1 << endl;
cout << s3 << endl;
cout << s4 << endl;
cout << s5 << endl;
輸出結果:
hello worldwoworldworld
string(const char*s,size_t n);
函數的功能是拷貝字符串的前n個字符
string(size_t n,char c);
這個函數的功能就是用n個字符c來構造字符串,用法:
2.2 對string對象的遍歷和修改
對于string遍歷使用[]遍歷最為方便
函數的功能是返回pos位置的字符
int main() {string s1("hello world");for (int i = 0; i < s1.size(); i++) {cout << s1[i] << " ";}cout << endl;return 0;
}
字符串長度通過s.size()來表示。
operator[]是一個重載的操作符,用于直接訪問和修改字符串中特定索引位置的字符
char& operator[] (size_t pos);
返回的為引用,意味著我們還可以對這個位置進行修改。
例如:
int main() {string s1("hello world");for (int i = 0; i < s1.size(); i++) {s1[i]++;cout << s1[i] << " ";}cout << endl;return 0;
}
這里我們發現還有第二種重載方式:
const char& operator[] (size_t pos) const;
const定義的對象是只讀的,不能對其進行修改
迭代器iterators
迭代器的作用是用來訪問容器(用來保存元素的數據結構)中的元素,所以使用迭代器,我們就可以訪問容器中里面的元素。這和訪問數組這個序列的指針一樣,因為數組范圍內的指針就是迭代器的一種。
int main() {string s1("hello world");string::iterator it1 = s1.begin();while (it1 != s1.end()) {cout << *it1 << " ";++it1;}cout << endl;return 0;
}
begin作用是返回第一個有效位置的迭代器,end是返回最后一個元素的下一個位置,也就是/0的位置。
雖然我們習慣使用下標來訪問,但是有時候只能只能使用迭代器來訪問(迭代器的訪問范圍更廣泛),比如后面的list部分。所以迭代器才是最重要的方式。
反向迭代器
它返回的是字符串末尾的迭代器,我們用這一組迭代器可以實現逆序遍歷
int main() {string s1("hello world");string::reverse_iterator it1 = s1.rbegin();while (it1 != s1.rend()) {cout << *it1 << " ";++it1;}cout << endl;return 0;
}
還有const版本
const_iterator begin() const;
int main() {string s1("hello world");string::const_iterator it1 = s1.begin();while (it1 != s1.end()) {//(*it1)++; //如果修改會編譯報錯cout << *it1 << " ";++it1;}cout<<endl;return 0;
}
對const字符串進行遍歷,const_iterator是只讀的,不可寫
范圍for
string s1("hello world");
for (auto e : s1)
{cout << e << " ";
}
cout << endl;
范圍for本質就是迭代器
2.3 string類對象的容量操作
size
size的功能是返回字符串長度
capacity
void func2()
{string s;size_t sz = s.capacity();cout << sz << endl;for (int i = 0; i < 100; i++){s.push_back('a');if (sz != s.capacity()){sz = s.capacity();cout << "容量:" << sz << endl;}}
}
通過上述函數來看一下它的擴容機制
我們發現第一次是以2倍擴容,后面都是1.5倍擴容。
clear
clear作用是清空有效字符,但它對capacity沒有影響
void func3() {string s("hello world");size_t sz = s.capacity();cout << s << endl;cout << sz << endl;s.clear();cout << s << endl;cout << s.capacity() << endl;}
empty
檢測字符串釋放為空串,是返回true,否則返回false
reserve
reserve(size_t res_arg=0):為string預留空間,不改變有效元素個數,當reserve的參數小于string的底層空間總大小時,reserver不會改變容量大小。
當你知道將要在字符串中存儲具體數量的字符時,使用reserve可以減少因反復增加字符串大小而導致的多次內存分配和數據復制,從而提高性能。(提前開好,減少擴容,提高效率)
擴容可能會開辟新的空間,使用reserve我們就可以減少擴容
string s;
s.reserve(100);
cout << s.capacity() << endl;
reserve的調用是一個請求,所以他申請的空間可能大于你要的空間,但不會小于。(g++中是剛好等于你要的空間)
reserve不會進行縮容,比當前capacity大才會進行擴容
resize
resize(size_t n) 與 resize(size_t n, char c)都是將字符串中有效字符個數改變到n個,不同的是當字符個數增多時:resize(n)用0來填充多出的元素空間,resize(size_t n, char c)用字符c來填充多出的元素空間。
注意:resize在改變元素個數時,如果是將元素個數增多,可能會改變底層容量的大小,如果是將元素個數減少,底層空間總大小不變。
如果個數不變,resize不會對字符串進行任何修改。
void func5() {string str("hello");str.resize(10, 'x');//結果 helloxxxxxstr.resize(2); //結果 hestr.resize(5); //結果 hellocout << str << endl;
}
resize直接修改字符串本身,如果你增長字符串并且不指定填充字符則填充空字符’\0’ ,如果減小字符串長度,被移除的字符就被丟棄,而且無法恢復。
2.4 string類對象的修改操作
push_back
在字符串后面尾插字符
string s("abcdef");
s.push_back('e');
cout<<s<<endl;//abcdefe
append
在字符串后追加一個字符串
void test_string10() {string s("hell");s.push_back('o');cout << s << endl;s.append("world");cout << s << endl;
}
append也可以插入string,或者插入string的部分。還可以插入n個字符
void test_string11() {string s("hell");string s1("o world!");s.append(s1);cout << s << endl;
}
void test_string11() {string s("hell");string s1("o world!");s.append(s1,0,2);cout << s << endl;//hello
}
還可以插入字符串的迭代區間
void test_string12() {string s("hell");string s1("o world!");s.append(s1.begin(),s1.end());cout << s << endl;
}
如果在這里我們不想要感嘆號可以這樣追加:
void test_string12() {string s("hell");string s1("o world!");s.append(s1.begin(),--s1.end());cout << s << endl;
}
operator+=
operator+=十分方便,我們可以直接追加一個string對象,或者一個字符串,或者一個字符。
insert和erase
insert可以在指定位置插入數據。
void test_string13() {string s("hello");s.insert(0, "xxx");cout << s << endl;
}
erase
從pos位置開始刪除,這里pos給的缺省值,如果不傳參,則全部刪除,len的缺省值為npos,如果len大于剩余字符長度(_size-pos),也會全部刪除掉
replace
對string對象內容進行替換
void test_string14() {string s("hello ");s.replace(6,1, "world");//把下標為6的那個字符修改為world字符串cout << s << endl;
}
find
find用于搜索字符串中第一次出現的指定子字符串或字符的位置。如果找到了指定的子字符串或字符,find會返回它開始的位置的索引;如果沒有找到,它會返回一個特殊的常量std::string::npos(這個是無效的位置),表示未找到任何匹配。
find函數的常見用法:
- 搜索字符
string str = "Hello, world!";
size_t pos = str.find('w');
if (pos != string::npos) {cout << pos << endl;// 找到了字符 'W'
}
- 搜索子字符串
string str = "Hello, world!";
size_t pos = str.find("world");
if (pos != string::npos) {printf("找到了子字符串 \"world\"");
}
- 從指定位置開始搜索
string str = "Hello, world! world!";
size_t pos = str.find("world", 8); // 從索引8開始搜索
if (pos != string::npos) {printf("找到了第二個 \"world\"");
}
find函數可以搜索字符串中的內容,是處理字符串時常用的功能之一
本節內容到此結束!感謝大家閱讀!!