目錄
一、成員訪問(wèn)
1、operator[ ]&at
2、front( )&back( )
二、插入元素 insert( )
三、刪除元素 erase( )
四、替換元素 replace( )
五、查找元素 find( )
六、交換字符串 swap( )
七、C風(fēng)格?c_str
八、rfind&substr
一、成員訪問(wèn)
1、operator[ ]&at
雖然二者功能一樣,但[ ]比較常用。
int main()
{
string s1("hello world");
cout << s1[4] << endl;
cout << s1.at(4) << endl;
return 0;
}
訪問(wèn)越界[ ]會(huì)直接報(bào)錯(cuò),.at( )會(huì)拋異常。
int main()
{
string s1("hello world");
try {
s1.at(100);
}
catch (const exception& e) {
cout << e.what() << endl;
}
return 0;
}
2、front( )&back( )
int main()
{
string s1("hello world");
cout << s1.back() << endl;
cout << s1.front() << endl;
return 0;
}
二、插入元素 insert( )
insert/erase不推薦經(jīng)常使用,能少用就少用,因?yàn)樗麄兛赡芏即嬖谝矂?dòng)數(shù)據(jù),效率低下。
指定位置插入字符串。
int main()
{
string s1("world");
s1.insert(0, "hello");
cout << s1 << endl;
return 0;
}
指定位置插入單個(gè)字符?
s1.insert(0, "w");
?
?兩種方式指定位置插入空字符
使用單引號(hào)需要加上插入字符個(gè)數(shù)(第二個(gè)參數(shù)),使用雙引號(hào)不需要。
int main()
{
string s1("world");
s1.insert(2, 1, ' ');
s1.insert(3, " ");
cout << s1 << endl;
return 0;
}
?
?插入可以借助迭代器的begin()和end()獲取位置。
s1.insert(s1.begin()+2, ' ');
s1.insert(s1.end() - 1, ' ');
?
三、刪除元素 erase( )
?insert/erase不推薦經(jīng)常使用,能少用就少用,因?yàn)樗麄兛赡芏即嬖谝矂?dòng)數(shù)據(jù),效率低下。?
刪除指定位置指定長(zhǎng)度字符。?
int main()
{
string s2("hello world");
s2.erase(5, 1);
cout << s2 << endl;
return 0;
}
也可以使用迭代器。?
s2.erase(s2.begin() + 5);
?
?如果長(zhǎng)度大于字符串長(zhǎng)度或者缺省,則刪除指定位置開(kāi)始一直到最后的字符。
s2.erase(5, 30);
s2.erase(5);
?
四、替換元素 replace( )
replace()
函數(shù)的第一個(gè)參數(shù)是替換的起始位置,第二個(gè)參數(shù)是要替換的字符數(shù),第三個(gè)參數(shù)是替換的字符串。?
int main()
{
string s1("hello world");
s1.replace(5, 1, "&&&&");
cout << s1 << endl;
return 0;
}
- 首先,代碼中的第一行是被注釋掉的,表示字符串
s1
被初始化為"hello world"。這是一個(gè)注釋行,不會(huì)被執(zhí)行。 - 然后,使用
s1.replace(5, 1, "&&&&")
函數(shù)調(diào)用來(lái)替換字符串s1
中從索引位置5開(kāi)始的1個(gè)字符,將其替換為"&&&&"。 - 接下來(lái),使用
cout
對(duì)象和<<
運(yùn)算符將修改后的字符串s1
輸出到標(biāo)準(zhǔn)輸出流。
使用replace時(shí),空間不夠擴(kuò)容,還要移動(dòng)數(shù)據(jù)。?
五、查找元素 find( )
find()
用于在字符串中查找指定子串的第一個(gè)出現(xiàn)位置。
find()
函數(shù)有多個(gè)重載版本,其中最常用的版本接受一個(gè)參數(shù),即要查找的子串。它返回一個(gè)整數(shù)值,表示子串在字符串中的位置索引。如果找到了子串,則返回第一個(gè)匹配的位置索引;如果未找到子串,則返回一個(gè)特殊的值std::string::npos
。
int main()
{
string s1("hello world I love you");
size_t pos = s1.find(' ');
while (pos != string::npos) {
s1.replace(pos, 1, "***");
pos = s1.find(' ');
}
cout << s1 << endl;
return 0;
}
我們可以對(duì)上述程序進(jìn)行優(yōu)化。
int main()
{
string s1("hello world I love you");
size_t num = 0;
for (auto ch : s1) {
if (ch == ' ')
++num;
}
s1.reserve(s1.size() + 2 * num);
size_t pos = s1.find(' ');
while (pos != string::npos) {
s1.replace(pos, 1, "***");
pos = s1.find(' ',pos+3);
}
cout << s1 << endl;
return 0;
}
- 首先,在代碼中創(chuàng)建了一個(gè)名為
s1
的字符串對(duì)象,并將其初始化為"hello world I love you"。 - 然后,使用一個(gè)循環(huán)遍歷字符串
s1
中的每個(gè)字符。在循環(huán)中,如果當(dāng)前字符是空格,則將計(jì)數(shù)器num
加1。 - 接下來(lái),使用
s1.reserve(s1.size() + 2 * num)
函數(shù)調(diào)整字符串s1
的容量,以便能夠容納替換后的字符串。這樣做是為了避免在替換過(guò)程中頻繁地重新分配內(nèi)存,提高性能。 - 然后,使用
s1.find(' ', pos)
函數(shù)來(lái)查找字符串s1
中下一個(gè)空格的位置。如果找到了空格,將其位置存儲(chǔ)在變量pos
中。 - 接下來(lái),使用
s1.replace(pos, 1, "***")
函數(shù)將找到的空格替換為三個(gè)星號(hào)"***"。這樣做會(huì)修改字符串s1
中的內(nèi)容。 - 然后,使用
pos = s1.find(' ', pos + 3)
來(lái)查找下一個(gè)空格的位置,從上一個(gè)空格的位置加3開(kāi)始查找。這樣做是為了避免重復(fù)替換已經(jīng)被替換過(guò)的空格。 - 循環(huán)會(huì)一直執(zhí)行,直到?jīng)]有更多的空格被找到。
- 最后,使用
cout
對(duì)象和<<
運(yùn)算符將修改后的字符串s1
輸出到標(biāo)準(zhǔn)輸出流。
?還可以使用+=運(yùn)算符進(jìn)一步優(yōu)化。
int main()
{
string s1("hello world I love you");
string newStr;
size_t num = 0;
for (auto ch : s1) {
if (ch != ' ')
++num;
}
newStr.reserve(s1.size() + 2 * num);
for (auto ch : s1) {
if (ch != ' ')
newStr += ch;
else
newStr += "***";
}
s1 = newStr;
}
與之前的版本相比,這段程序是對(duì)第一段程序的改進(jìn)版本,具有以下特點(diǎn)和優(yōu)點(diǎn):?
-
更簡(jiǎn)潔:第二段程序使用了更簡(jiǎn)潔的方法來(lái)替換字符串中的空格,避免了使用循環(huán)和查找函數(shù)。
-
更高效:第二段程序只需遍歷一次原始字符串,而不是使用循環(huán)和查找函數(shù)多次遍歷。這樣可以減少時(shí)間復(fù)雜度,提高程序的執(zhí)行效率。
-
更易讀:第二段程序使用了更直觀的方式來(lái)替換空格,通過(guò)判斷字符是否為空格來(lái)決定添加字符還是添加"***"。這樣代碼更易讀懂,減少了冗余的操作。
-
更節(jié)省內(nèi)存:第二段程序使用了新的字符串
newStr
來(lái)存儲(chǔ)替換后的結(jié)果,避免了對(duì)原始字符串s1
進(jìn)行頻繁的修改。這樣可以減少內(nèi)存的使用,提高程序的效率。
六、交換字符串 swap( )
int main()
{
string s1("hello world");
string s2("xxxxx");
s1.swap(s2);
cout << s1 << endl;
cout << s2 << endl;
swap(s1, s2);
cout << s1 << endl;
cout << s2 << endl;
}
這段程序中的兩個(gè)swap
函數(shù)調(diào)用有以下區(qū)別:
-
std::string::swap
是std::string
類的成員函數(shù),它直接在兩個(gè)字符串對(duì)象之間交換數(shù)據(jù),通常是通過(guò)交換內(nèi)部指針來(lái)實(shí)現(xiàn)的,所以它的效率非常高,幾乎是常數(shù)時(shí)間復(fù)雜度。 -
std::swap
是標(biāo)準(zhǔn)庫(kù)提供的一個(gè)模板函數(shù),它可以用于交換任何類型的兩個(gè)對(duì)象。對(duì)于std::string
類型,std::swap
內(nèi)部實(shí)際上也是調(diào)用的std::string::swap
,所以效率也是很高的。
總的來(lái)說(shuō),這兩種方法在效率上是相當(dāng)?shù)?,你可以根?jù)實(shí)際情況和編程風(fēng)格來(lái)選擇使用哪一種。如果代碼只涉及到字符串交換,那么使用std::string::swap
可能會(huì)更直觀一些;如果代碼需要處理多種類型的交換,那么使用std::swap
可能會(huì)更通用一些。
七、C風(fēng)格?c_str
int main()
{
string s1("hello world");
cout << s1 << endl;
cout << s1.c_str() << endl;
return 0;
}
-
cout << s1 << endl;
:這行代碼將字符串對(duì)象s1
直接輸出到標(biāo)準(zhǔn)輸出流cout
中。它會(huì)輸出s1
的內(nèi)容,即字符串 "hello world"。 -
cout << s1.c_str() << endl;
:這行代碼使用了字符串對(duì)象s1
的c_str()
成員函數(shù)。c_str()
函數(shù)返回一個(gè)指向以空字符結(jié)尾的字符數(shù)組(C風(fēng)格字符串)的指針。然后,該指針被傳遞給cout
輸出流進(jìn)行輸出。它也會(huì)輸出s1
的內(nèi)容,即字符串 "hello world"。
區(qū)別在于輸出的方式不同。第一行直接輸出字符串對(duì)象s1
的內(nèi)容,而第二行使用了c_str()
函數(shù)將字符串對(duì)象轉(zhuǎn)換為C風(fēng)格字符串后輸出。通常情況下,直接輸出字符串對(duì)象更為簡(jiǎn)潔和方便。
int main()
{
string s1("hello world");
cout << s1 << endl;
cout << s1.c_str() << endl;
s1 += '\0';
s1 += '\0';
s1 += "xxxxx";
cout << s1 << endl;
cout << s1.c_str() << endl;
return 0;
}
可以看到,通過(guò)對(duì)s1
進(jìn)行修改操作后,輸出結(jié)果中的空字符('\0')在字符串對(duì)象s1
的輸出中仍然存在,但在c_str()
函數(shù)返回的C風(fēng)格字符串中被忽略了。這是因?yàn)?code>c_str()函數(shù)會(huì)將字符串以空字符結(jié)尾,而在輸出時(shí)遇到空字符就會(huì)停止輸出。?
我們逐步解釋為什么輸出結(jié)果會(huì)有所不同。
初始狀態(tài)下,s1
的值為"hello world"。
-
cout << s1 << endl;
:輸出s1
的內(nèi)容,即字符串 "hello world"。 -
cout << s1.c_str() << endl;
:輸出s1
的C風(fēng)格字符串表示,即 "hello world"。 -
s1 += '\0';
:在s1
末尾添加一個(gè)空字符('\0'),此時(shí)s1
的值變?yōu)?"hello world\0"。 -
s1 += '\0';
:再次在s1
末尾添加一個(gè)空字符('\0'),此時(shí)s1
的值變?yōu)?"hello world\0\0"。 -
s1 += "xxxxx";
:將字符串 "xxxxx" 追加到s1
的末尾,此時(shí)s1
的值變?yōu)?"hello world\0\0xxxxx"。 -
cout << s1 << endl;
:輸出s1
的內(nèi)容,即 "hello world\0\0xxxxx"。 -
cout << s1.c_str() << endl;
:輸出s1
的C風(fēng)格字符串表示,即 "hello world"。這里需要注意,c_str()
函數(shù)返回的是以空字符結(jié)尾的字符數(shù)組,輸出時(shí)遇到第一個(gè)空字符就會(huì)停止輸出。
八、rfind&substr
rfind
函數(shù)用于在一個(gè)字符串中從后往前搜索指定的子字符串,并返回子字符串的位置。
它的語(yǔ)法如下:
size_t rfind(const string& str, size_t pos = string::npos) const;
str
是要搜索的子字符串,pos
是搜索的起始位置,默認(rèn)為string::npos
,表示從字符串的末尾開(kāi)始搜索。
substr
函數(shù)用于從一個(gè)字符串中提取子字符串。它的語(yǔ)法如下:
string substr(size_t pos = 0, size_t len = string::npos) const;
其中,pos
是要提取的子字符串的起始位置,默認(rèn)為0,len
是要提取的子字符串的長(zhǎng)度,默認(rèn)為string::npos
,表示提取從起始位置到字符串末尾的所有字符。
接下來(lái)看下面代碼:
int main()
{
string file("string.cpp.tar.zip");
size_t pos = file.rfind('.');
if (pos != string::npos)
{
string suffix = file.substr(pos);
cout << suffix << endl;
}
return 0;
}
這段代碼的目的是提取文件名中的后綴名。
- 首先,定義了一個(gè)字符串
file
,其中包含了一個(gè)文件名string.cpp.tar.zip
。 - 然后,使用
rfind
函數(shù)從后往前搜索.
字符的位置,并將結(jié)果保存在變量pos
中。如果找到了.
字符,則pos
的值不等于string::npos
。 - 接下來(lái),通過(guò)判斷
pos
的值是否不等于string::npos
,來(lái)確定是否找到了.
字符。如果找到了,則使用substr
函數(shù)從pos
位置開(kāi)始提取子字符串,并將結(jié)果保存在變量suffix
中。 - 最后,將提取到的后綴名輸出到標(biāo)準(zhǔn)輸出流
cout
中,然后換行。
在這個(gè)例子中,輸出結(jié)果為.zip
,因?yàn)?code>.字符后面的部分就是文件的后綴名。
?從URL中提取主機(jī)地址:
int main()
{
string url("http://www.cplusplus.com/reference/string/string/find/");
cout << url << endl;
size_t start = url.find("://");
if (start == string::npos)
{
cout << "invalid url" << endl;
}
start += 3;
size_t finish = url.find('/', start);
string address = url.substr(start, finish - start);
cout << address << endl;
return 0;
}
使用find
函數(shù)搜索字符串url
中第一次出現(xiàn)的子字符串"://"
的位置,并將結(jié)果保存在變量start
中。如果找不到該子字符串,則start
的值等于string::npos
。
接下來(lái),通過(guò)判斷start
的值是否等于string::npos
,來(lái)確定是否找到了"://"
子字符串。如果沒(méi)有找到,則輸出"invalid url"
,表示URL無(wú)效。
如果找到了"://"
子字符串,則將start
的值增加3,以跳過(guò)"://"
部分,然后使用find
函數(shù)搜索從start
位置開(kāi)始的下一個(gè)'/'
字符的位置,并將結(jié)果保存在變量finish
中。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-753699.html
最后,使用substr
函數(shù)從start
位置開(kāi)始,提取從start
到finish
之間的子字符串,并將結(jié)果保存在變量address
中,將提取到的主機(jī)地址輸出到標(biāo)準(zhǔn)輸出流cout
中,然后換行。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-753699.html
到了這里,關(guān)于C++ string類(2)—成員訪問(wèn)、插入、刪除、替換、查找和交換操作的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!