文章目錄
- 一、string介紹
- 二、string類對象的創建(常見構造)
- 三、string類對象的容量操作
- 1.size()和length()
- 2.capacity()
- 3.empty()
- 4.clear()
- 5.reserve()
- 6.resize()
- 四、string類對象的遍歷與訪問
- 1.operator[ ]
- 2.正向迭代器begin()和end()
- 3.反向迭代器rbegin()和rend()
- 4.const正向和反向迭代器
- 5.范圍for
- 6.at()
- 五、string類對象的查找與修改
- 字符串查找
- 1.find()與npos
- 2.rfind()
- 3.find_first_of()和find_last_of()
- 4.substr()
- 字符串修改
- 1.operator+=
- 2.push_back()與pop_back()
- 3.append()
- 4.insert()
- 5.erase()
- 6.replace()
- 六、string類非成員函數
- operator+
- 輸入getline
一、string介紹
string是表示字符串的字符串類。它提供了一系列成員函數和操作符,使得字符串的操作更加方便和靈活。它位于標準命名空間
std
下,因此通常需要使用using namespace std;
語句或者前綴std::
來引用。
string是C++的STL(standard template libaray-標準模板庫)的容器之一。本篇,我們主要介紹string的基本用法。所有接口用法都可以在cplusplus參考手冊中查閱。下面我們主要介紹string的一些常用接口。
string底層實際是basic_string類模板的實例化,是表示字符串類型的模板類。
二、string類對象的創建(常見構造)
string重載了很多構造和拷貝構造函數,其實常用的也就4種。
//常用構造方式
string s1;//無參構造
string s2("interesting");//構造
string s3(s2);//拷貝構造
string s4 = "hello world";//構造
不常用的初始化方式
//函數原型 string (size_t n, char c);
string s5(10, 'x');//10個字符x
//函數原型 string (const string& str, size_t pos, size_t len = npos);
string s6(s2, 8, 3);//打印ing 第8個位置開始拷貝3個字符
string s7(s2, 8);//打印ing 第8個位置開始拷貝后面所有字符
三、string類對象的容量操作
1.size()和length()
計算有效字符串長度,不包括
\0
。 size()與length()的底層實現原理完全相同,引入size()的原因是為了與其他容器的接口保持一致,一般情況下基本都是用size()。
int main()
{string s("abcde");cout << s.size() << endl;//5cout << s.length() << endl;//5return 0;
}
2.capacity()
返回string類對象的空間容量大小。同樣的一個字符串在不同編譯器下的容量可能不一樣。
string s("abcde");
cout << s.capacity() << endl;//vs2019:15
3.empty()
字符串為空返回1,非空則返回0。
一般也很少用到。我們也可以用str == ""
判斷是否為空。
4.clear()
clear()只是將string中有效字符清空,不改變底層空間大小。 即有效數據size()清零,容量capacity()不變。
string s("abcde");
s.clear();
5.reserve()
提前申請空間,可以避免頻繁擴容。有效數據size不變,容量capacity增大。 且只比指定容量要大,不會小。
在Windows環境下(如上圖),reserve實際申請空間一般比我們指定的參數要大;而Linux的擴容空間與指定參數一樣。
不同環境下,string擴容的規律也不同:Windows環境下(PJ版本STL),容量capacity每次以1.5倍的速度擴容;Linux環境下(SGI版本STL),每次以2倍速度擴容;所以頻繁擴容的成本較高。reserve可以提前申請好空間,避免頻繁擴容。
reserve可以縮容嗎?
可以,但是如果原始空間有數據,則縮容無效;用clear清空有效數據,即可縮容到指定參數大小的空間。所以,想用reserve縮小空間
6.resize()
調整string容器大小,即有效數據個數size()。
string s("abcde");
s.resize(3);//abc size=3;
s.resize(5, 'x');//abcxx size=5
n < size相當于尾刪,size()減小到n,底層空間capacity()不變。
n > size則size增加到n,多出的空間用第二個字符參數填充,無參則默認填充’\0’。
四、string類對象的遍歷與訪問
1.operator[ ]
int main()
{string s("interesting");for (size_t i = 0; i < s.size(); i++){cout << s[i];s[i]++;}return 0;
}
2.正向迭代器begin()和end()
begin()返回指向字符串第一個字符的迭代器,end()返回指向字符串末尾字符’\0’的迭代器。
迭代器提供了一種遍歷容器中元素的方法,迭代器是像指針一樣的類型,但可能是指針,也可能不是指針,用法與指針類似。
任何容器都支持迭代器,并且用法是類似的。 迭代器是屬于類域的,所以要加域作用限定符。并且對于迭代器的使用,搭配關鍵字auto使用更簡單。
int main()
{string s("interesting");//auto it = s.begin();//自動識別類型string::iterator it = s.begin();//打印interestingwhile (it != s.end()){cout << *it;it++;}return 0;
}
3.反向迭代器rbegin()和rend()
反向迭代器與正向迭代器用法一樣,可以實現逆序遍歷。注意正向和反向迭代器名字不一樣。
int main()
{string s("interesting");//auto it = s.rbegin();//自動識別類型string::reverse_iterator rit = s.rbegin();//打印gnitseretniwhile (rit != s.rend()){cout << *rit;rit++;}return 0;
}
4.const正向和反向迭代器
對于const修飾的string類對象,就只能用const迭代器,否則會發生權限的放大。
使用auto更方便省事。
const string s("interesting");
//正向
string::const_iterator it = s.begin();
auto it = s.begin();
//反向
string::const_reverse_iterator rit = s.rbegin();
auto it = s.rbegin();
5.范圍for
C++11支持更簡潔的范圍for的新遍歷方式。范圍for的底層就是迭代器,不支持迭代器就不支持范圍for。
int main()
{string s("interesting");for (auto& ch : s)//可讀 加上引用可寫{ch++;cout << ch;}return 0;
}
6.at()
使用與operator[ ]一樣,但一般很少用at()來訪問string。
at()與[ ]的區別是對越界的檢查不一樣:[ ]越界會斷言,比較暴力;at()越界會拋異常,比較溫和。
int main()
{string s("interesting");for (size_t i = 0; i < s.size(); i++){cout << s.at(i);s.at(i)++;}return 0;
}
五、string類對象的查找與修改
字符串查找
1.find()與npos
find是查找字符或字符串函數,返回與字符參數匹配到的第一個字符位置下標,如果找不到則返回npos。
npos是string類的靜態成員變量,值為-1(-1的補碼全是1),因為是size_t即無符號整型,所以npos表示的大小為232-1,即整型的最大范圍。
2.rfind()
與find()一樣,只不過rfind()是從右往左查找。
3.find_first_of()和find_last_of()
find_first_of():只要字符串中找到字符參數中任意一個字符,則返回第一個找到的下標。
例如,下面這段代碼將字符串中的aeiou全部替換成*
find_last_of()同理,只不過是從右往左查找。
4.substr()
返回獲取到的子串
int main()
{string s1("hello world");//第一種也是最常用的string s2 = s1.substr(2, 3);//截取從下標2開始的3個字符cout << s2 << endl;//llos2 = s1.substr(6);//截取從下標6開始后面的所有字符cout << s2 << endl;//worlds2 = s1.substr();//截取整個字符串cout << s2 << endl;//hello worldreturn 0;
}
字符串修改
1.operator+=
+= 可以尾插字符或者字符串,這個比較常用。+=操作不僅可以連接單個字符,還可以連接字符串。
int main()
{string s("hello ");s += "world";s += '!';cout << s << endl;return 0;
}
2.push_back()與pop_back()
尾插和尾刪單個字符
string s("abcd");
s.pop_back();//abc
s.push_back('x');//abcx
3.append()
尾插n個字符或者尾插指定區間的字符串
string s("hello ");
s.append(10, 'x');//尾插10個x
s.append("world", 3);//尾插字符串world的前3個字符
s.append("world", 1, 3);//尾插從下標1開始往后的3字符即orl
tip:一般push_back()和append()尾插不常用,用+=更方便省事。
4.insert()
在指定位置插入字符或者字符串
5.erase()
刪除指定位置的字符或字符串
6.replace()
用新的字符或者字符串替換原字符串部分字符
六、string類非成員函數
operator+
盡量少用,因為傳值返回,導致深拷貝效率低。
int main()
{string s1("hello");string s2("world");s1 = s1 + " " + s2;cout << s1 << endl;return 0;
}
operator>>和operator<<運算符重載也是string的非成員函數。
輸入getline
cin無法讀取空格和換行,getline可以彌補這個缺陷。需要包含頭文件
<string>
不指定分隔符,默認以回車結束,可以讀取空格,常用來讀取一行。
#include <iostream>
#include <string>
using namespace std;
int main()
{string s;getline(cin, s);cout << s;return 0;
}
第三個參數可以指定分隔符,例如指定’\r’可以讀取回車,結束需按下:Ctrl+z 然后再回車
#include <iostream>
#include <string>
using namespace std;
int main()
{string s;getline(cin, s, '\r');cout << s;return 0;
}