更多關於STL的文章:STL專欄
文章目錄
爲了防止學習的過程中出現學後忘的情況,我將接觸到的知識進行整理,作該筆記,由於本人水平有限,如果出現錯誤,還望賜正。
介紹
STL(Standard Template Library 標準模板庫) 中只有一個字符串類,即 basic_string類 。basic_string 實現管理以 \0 結尾的字符數組,字符類型由模板參數決定。通常,basic_string 被處理爲不透明的對象,靠獲得只讀指針來訪問緩衝區,寫操作是由 basic_string 的成員函數實現的。
用字符數組存放字符串容易發生數組越界的錯誤,而且往往難以察覺。因此,C++ 標準模板庫設計了 string 數據類型,專門用於字符串處理。string 作爲類出現,其集成的操作函數足以完成多數情況下的需要。使用時不必擔心內存是否充足、字符串長度等問題。
string 類型的變量就是用來存放字符串的,也叫“string對象”。string 並不是 C++ 的基本數據類型,它是 C++ 標準模板庫中的一個“類”。
string成員函數
string 類提供的各種操作函數大致分爲八類:構造器和析構器、大小和容量、元素存取、字符串比較、字符串修改、字符串接合、I/O 操作以及搜索和查找 。
函數名稱 | 功能 |
---|---|
構造函數 | 產生或複製字符串 |
析構函數 | 銷燬字符串 |
=,assign() | 賦以新值 |
swap() | 交換兩個字符串的內容 |
+=,append(),push_back() | 添加字符 |
insert() | 插入字符 |
back() | 返回字符串最後一個字符的引用 |
front() | 返回字符串第一個字符的引用 |
erase(),pop_back() | 刪除字符 |
clear() | 清空字符串 |
resize() | 改變字符串的長度 |
shrink_to_fit() | 請求字符串減小其容量以適合其大小 |
replace() | 替換字符串 |
+ | 拼接字符串 |
==,! =,<,<=,>,>=,compare() | 比較字符串內容 |
size(),length() | 返回字符串長度 |
max_size() | 返回字符的最大可能個數 |
empty() | 判斷字符串是否爲空 |
capacity() | 返回重新分配之前的字符容量 |
reserve() | 保留內存以存儲一定數量的字符 |
[],at() | 存/取單一字符 |
>>,getline() | 從 stream中讀取某值 |
<< | 將值寫入 stream |
copy() | 將內容複製爲一個 C - string |
c_str() | 將內容以 C - string 形式返回 |
data() | 將內容以字符數組形式返回 |
substr() | 返回子字符串 |
find() | 搜尋某子字符串或字符 |
begin( ),end(),cbegin(),cend() | 提供正向迭代器支持 |
rbegin(),rend(),crbegin(),crend() | 提供逆向迭代器支持 |
get_allocator() | 返回配置器 |
成員類型 | 定義 |
---|---|
value_type | char |
size_type | size_t |
iterator | char的隨機訪問迭代器 |
const_iterator | const char的隨機訪問迭代器 |
pointer | char* |
const_pointer | const char* |
reference | char& |
const_reference | const char& |
成員函數用法示例
1. 構造
構造函數有四個參數,其中三個具有默認值。要初始化一個 string 類,可以使用 C 風格字符串或 string 類型對象,也可以使用 C 風格字符串的部分或 string 類型對象的部分或序列。
注意,不能使用字符或者整數去初始化字符串。//如string str (‘abc’), string str(123) 都是錯誤的
常見的 string 類構造函數有以下幾種形式:
typedef basic_string string;
string var; //生成空字符串
string var(const basic_string& str); //生成字符串str的複製
string var(const basic_string& str, size_type pos); //將字符串str中始於pos的部分作爲構造函數的初始值
string var(const basic_string& str, size_type pos, size_type n);
//將字符串str位於區間[pos,pos+n-1]的子字符串作爲var的初始值
string var(const char* s); //以C_string類型s作爲字符串var的初始值
string var(const char* s, size_type n); //以C_string類型s的前n個字符串作爲字符串var的初始值
string var(size_type n, char c);//生成一個字符串,包含n個c字符
string var(InputIterator beg, InputIterator end); //以閉區間[beg, end]內的字符作爲字符串var的初始值
析構函數形式如下:
~basic_string() //銷燬所有內存,釋放內存
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str ("12345678");
char ch[ ] = "abcdefgh";
string str_1(str); //將str全部複製給str_1
string str_2(str,3);//從字符串str的第3個元素開始,複製後面的所有元素,並賦值給str_2
string str_3(str, 2, 5); //從字符串str的第2個元素開始,複製5個元素,並賦值給str_3
string str_4(ch);//複製C_string類型字符串,並賦值給str_4
string str_5(ch, 5); //將C_string類型字符串ch的前5個元素賦值給str_5
string str_6(5,'X'); //將5個'X'組成的字符串"XXXXX"賦值給str_6
string str_7(str.begin(), str.end()); //複製字符串str的所有元素,並賦值給 str_7
cout << str << endl;
cout << ch << endl;
cout << str_1 << endl;
cout << str_2 << endl;
cout << str_3 << endl;
cout << str_4 << endl;
cout << str_5 << endl;
cout << str_6 << endl;
cout << str_7 << endl;
return 0;
}
以下爲程序運行結果:
12345678
abcdefgh
12345678
45678
34567
abcdefgh
abcde
XXXXX
12345678
2. 字符串輸入輸出
“<<” 和 “>>” 提供了 C++ 語言的字符串輸入和字符串輸出功能。"<<" 可以將字符讀入一個流中(例如 ostream);">>" 可以實現將以空格或回車爲 “結束符” 的字符序列讀入到對應的字符串中,並且開頭和結尾的空白字符不包括進字符串中。
還有一個常用的 getline() 函數,該函數的原型包括兩種形式:
template <class CharType, class Traits, class Allocator > basic_istream<CharType, Traits>& getline (basic_istream<CharType, Traits>& _Istr,basic_string <CharType,Traits, Allocator> &_Str);
//上述原型包含 2 個參數:第 1 個參數是輸入流;第 2 個參數是保存輸入內容的字符串
template <class CharType, class Traits, class Allocator> basic_istream<CharType, Traits>& getline (basic_istream <CharType, Traits>&_ Istr, basic_string <CharType, Traits, Allocator>& _Str,CharType_Delim);
//上述原型包含 3 個參數:第 1 個參數是輸入流,第 2 個參數保存輸入的字符串,第 3 個參數指定分界符
該函數可將整行的所有字符讀到字符串中。在讀取字符時,遇到文件結束符、分界符、回車符時,將終止讀入操作,且文件結束符、分界符、回車符在字符串中不會保存;當已讀入的字符數目超過字符串所能容納的最大字符數時,將會終止讀入操作。
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
//三塊代碼分開執行
string str_1;
cin>>str_1;
cout<<"第一個:"<< str_1<<endl;
/*string str_2;
getline(cin,str_2);
cout<<"第二個:"<<str_2<<endl;*/
/*string str_3;
getline(cin,str_3,'a');
cout<<"第三個:"<<str_3<<endl;*/
return 0;
}
下面爲程序運行結果(三種情況均輸入:qweasd zxc)
第一個:qweasd //>>遇到空格結束
第二個:qweasd zxc //getline讀取字符,直到遇見文件結束符、分界符、回車符停止
第三個:qwe //getline遇到分界符a 讀取結束
3.獲取字符串的長度
string 類型對象包括三種求解字符串長度的函數:size() 和 length()、 maxsize() 和 capacity():
- size() 和 length():這兩個函數會返回 string 類型對象中的字符個數,且它們的執行效果相同。
- max_size():max_size() 函數返回 string 類型對象最多包含的字符數。一旦程序使用長度超過 max_size() 的 string 操作,編譯器會拋出 length_error 異常。
- capacity():該函數返回在重新分配內存之前,string 類型對象所能包含的最大字符數。跟size()不同,它返回的是分配的容量的大小,並不是string裏面字符串的長度。
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("abcdef");
unsigned long size = str.size();
unsigned long length = str.length();
unsigned long max = str.max_size();
unsigned long cap = str.capacity();
cout<<"size:"<<size<<endl;
cout<<"length:"<<length<<endl;
cout<<"max_size:"<<max<<endl;
cout<<"capacity:"<<cap<<endl;
return 0;
}
下面爲程序輸出結果:
size:6
length:6
max_size:9223372036854775807
capacity:15 //至於這裏爲什麼輸出15,還不清楚
string 類型對象包括一個 reserve() 函數。調用該函數可以爲 string 類型對象重新分配內存(預分配,此時不能用下標訪問新分配的內存)。重新分配的大小由其參數決定。reserve() 的默認參數爲 0。
還包含一個 resize() 函數。其功能與 reserve() 相同,但reserve() 只能將內存擴大,而 resize() 可以任意分配內存(直接分配,如果內存變小,則原字符串被截斷,如果內存變大,則用’\0’填充,此時可以用下標訪問新分配的內存)。
這兩個方法分別對應兩個屬性:capacity() 和 size()
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("abcdef");
str.reserve(40);
cout<<"size:"<<str.size()<<endl;
cout<<"capacity:"<<str.capacity()<<endl;
str.resize(60);
//str.shrink_to_fit();
cout<<str<<endl;
cout<<"size:"<<str.size()<<endl;
cout<<"capacity:"<<str.capacity()<<endl;
str.resize(3);//原字符串被截斷
cout<<str<<endl;
return 0;
}
下面爲程序運行結果:
size:6
capacity:40
abcdef
size:60
capacity:80
abc
上述程序中str.reserve(40);
如果將n=40改爲0~14,capacity仍輸出15,而將n改爲15~29時,capacity將輸出30。只有改爲31及以上,纔會輸出值n。
此外從運行結果可以看到resize之後,capacity也會發生改變,resize之後(擴大內存)理論上capacity的值與size相同,上述程序由於預先調用了reserve,影響了結果。但是若添加str.shrink_to_fit();
,則capacity將會與size相同。
- shrink_to_fit()無返回值,功能如下:
- 請求字符串減小其容量以適合其大小。
- 該請求是非綁定的,並且容器實現可以自由地進行優化,否則將使字符串的容量大於其大小。
- 此函數對字符串長度沒有影響,並且不能更改其內容。
4.獲取字符串元素
字符串中元素的訪問是允許的,一般可使用兩種方法訪問字符串中的單一字符:下標操作符[] 和 成員函數at()。兩者均返回指定的下標位置的字符。第 1 個字符索引(下標)爲 0,最後的字符索引爲 length()-1。
需要注意的是,這兩種訪問方法是有區別的:
- 下標操作符 [] 在使用時不檢查索引的有效性,如果下標超出字符的長度範圍,會示導致未定義行爲。對於常量字符串,使用下標操作符時,字符串的最後字符(即 ‘\0’)是有效的。對應 string 類型對象(常量型)最後一個字符的下標是有效的,調用返回字符 ‘\0’。
- 函數 at() 在使用時會檢查下標是否有效。如果給定的下標超出字符的長度範圍,系統會拋出 out_of_range 異常。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("abcdef");
cout<<str[3]<<endl;
cout<<str.at(3)<<endl;
cout<<str[10]<<endl;//越界,返回'\0',但Qt Creator13.01執行時未報錯
cout<<str.at(10)<<endl;//異常
return 0;
}
運行結果:
d
d
terminate called after throwing an instance of ‘std::out_of_range’
what(): basic_string::at: __n (which is 10) >= this->size() (which is 6)
- front() 和 back()
front() 和 back() 分別返回字符串首、尾字符的引用,無參數。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("abcdef");
cout<<str.front()<<endl;
cout<<str.back()<<endl;
str.front() = 'c';
str.back() = 'x';
cout<<str<<endl;
return 0;
}
運行結果爲:
a
f
cbcdex
另外,爲了防止使用下標時,字符串尚未初始化等情況,使用empty() 和 size() 或 length()可以有效防止出錯。
- empty()無參數,功能如下 :
- 判斷字符串是否爲空,是返回真,否則返回假。
- substr()
返回子字符串
basic_string substr(size_type pos = 0, size_type n = npos) const;
//返回區間[pos,pos+n-1]的子字符串
string str("abcdefg");
cout<<str.substr(2,5)<<endl; //輸出cdefg
5.字符串內容的修改
可以通過使用多個函數修改字符串的值。例如 assign(),operator=,erase(),operator+,pop_back(),swap(),insert()等。另外,還可通過 append() ,push_back()函數添加字符,以及clear()清空字符串。
- assign()
使用 assign() 函數可以直接給字符串賦值。該函數既可以將整個字符串賦值給新串,也可以將字符串的子串賦值給新串。其在 basic_string 中的原型爲:
basic_string& assign(const char* s); //直接使用C_string字符串賦值
basic_string& assign(const char* s, size_type n);//將C_string字符串s前n個字符賦值給調用串
basic_string& assign (const basic_string& str); //使用string字符串賦值
basic_string& assign(const basic_string& str, size_type pos, size_type n = npos);
//將str的子串賦值給調用串,n表示長度,默認值爲-1(直到字符串末尾)
basic_string& assign(size_type n, char c); //使用 n個重複字符賦值
basic_string& assign(InputIterator first, InputIterator last); //使用迭代器賦值
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str1("123456");
char s[6] = "abcde";
string str;
str.assign(s);//用C_string類型字符串賦值
cout<<str<<endl;
str.assign(s,3);//將C_string類型字符串s的前3個字符賦值給str
cout<<str<<endl;
str.assign(str1);//用string類型字符串賦值
cout<<str<<endl;
str.assign(str1,3);//將str1從第3個字符到最後一個字符賦值給str
cout<<str<<endl;
str.assign(str1,2,3);//將str1從第2個字符開始,長度爲3的字符串賦值給str
cout<<str<<endl;
str.assign(5,'c');//用5個c字符賦值
cout<<str<<endl;
str.assign(str1.begin()+2,str1.end()-2);//使用迭代器賦值
cout<<str<<endl;
return 0;
}
下面爲程序運行結果:
abcde
abc
123456
456
345
ccccc
34
-
operator=
operator= 的功能就是賦值。 -
operator+
將兩個或多個字符串拼接起來
string str1("123456");
string str("789");
str = str1 + str;
cout<<str<<endl;//輸出123456789
- push_back()
在字符串末尾追加一個字符,參數爲多個字符時,會被截斷
void push_back(char c);
string str("abc");
str.push_back('d')
cout<<str<<endl;//輸出abcd
- swap()
交換兩個字符串的值
void swap (basic_string& str);
string str1("123456");
string str("789");
str.swap(str1);
cout<<str<<endl; //輸出123456
cout<<str1<<endl;//輸出789
- pop_back()
刪除字符串最後一個字符
void pop_back();
- erase()
刪除指定子字符串
basic_string& erase(size_type pos = 0, size_type n = npos);
//刪除從pos開始,長度爲n的子字符串(即區間[pos,pos+n-1]的子字符串)(默認刪除全部)
iterator erase(const_iterator position);//使用迭代器,刪除指定的一個字符
iterator erase(const_iterator first, const_iterator last);//使用迭代器,刪除指定區間的子字符串
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("123456");
str.erase(3);//從第3個開始刪除後續所有字符
cout<<str<<endl;
str = "123456";
str.erase(3,2);//從第3個開始刪除長度爲2的子字符串
cout<<str<<endl;
str = "123456";
str.erase(str.begin()+3);//刪除第3個字符
cout<<str<<endl;
str = "123456";
str.erase(str.begin()+2,str.begin()+4);//刪除區間[2,4)的子字符串
//str.erase(str.end()-4,str.end()-2); //刪除區間{2,4)的子字符串
cout<<str<<endl;
return 0;
}
運行結果:
123
1236
12356
1256
-
clear()
清空字符串,該函數無參數,無返回值。 -
insert()
向指定位置插入字符串
basic_string& insert(size_type pos, const char* s);//在調用串的第pos個元素前面插入C_string類型字符串
basic_string& insert(size_type pos, size_type n, char c);//在調用串的第pos個元素前面插入n個字符c
iterator insert(const_iterator p, char c);//使用迭代器,在正向迭代器指向的位置p前面插入單個字符c
iterator insert(const_iterator p, size_type n, char c);//在正向迭代器指向的位置p前面插入n個字符c
basic_string& insert(size_type pos, const char* s, size_type n);
//在調用串的第pos個元素前面插入C_string類型字符串s的前n個字符
basic_string& insert(size_type pos1, const basic_string& str, size_type pos2, size_type n = npos);
//在調用串的第pos1個元素前插入字符串str位於區間[pos2,pos2+n -1]的子字符串(n默認直到末尾)
basic_string& insert(size_type pos1, const basic_string& str);//在調用串的第pos1個元素前插入字符串str
iterator insert(const_iterator p, InputIterator beg, InputIterator end);
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("123456");
string ss("vwxyz");
char s[6] = "abcde";
str.insert(2,s);//在str第2個元素前面插入C_string類型字符串s
cout<<str<<endl;
str = "123456";
str.insert(2,3,'a');//在str第2個元素前面插入3個字符a
cout<<str<<endl;
str = "123456";
str.insert(str.begin()+1,'b');//在str第1個元素前面插入字符b
cout<<str<<endl;
str = "123456";
str.insert(str.begin(),3,'c');//在str第0個元素前面插入3個字符c
cout<<str<<endl;
str = "123456";
str.insert(3,s,2);//在str第3個元素前面插入c_string類型字符串s的前2位
cout<<str<<endl;
str = "123456";
str.insert(2,ss,2,2);//在str第2個元素前面插入字符串ss從第2個元素開始長度爲2的子字符串
cout<<str<<endl;
str = "123456";
str.insert(2,ss);//在str第2個元素前面插入字符串ss
cout<<str<<endl;
str = "123456";
str.insert(str.begin()+1,ss.begin()+3,ss.end());//在str第1個元素前面插入字符串ss從第3個元素到最後一個元素所構成的子字符串
cout<<str<<endl;
return 0;
}
程序運行結果爲:
12abcde3456
12aaa3456
1b23456
ccc123456
123ab456
12xy3456
12vwxyz3456
1yz23456
- append()
追加字符串
basic_string& append(const basic_string& str);//在調用串末尾添加字符串str
basic_string& append(const basic_string& str, size_type pos, size_type n = npos) ;//在調用串末尾添加字符串從第pos個元素開始長度爲n的子字符串(即區間[pos,pos+n-1]的子字符串)(n默認直到末尾)
basic_string& append(const char* s, size_type n);//在調用串末尾添加c_string類型字符串s的前n個元素
basic_string& append(const char* s);//在調用串末尾添加c_string類型字符串s
basic_string& append(size_type n, char c);//在調用串末尾添加n個字符c
basic_string& append(InputIterator first, InputIterator last);
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("123456");
string ss("vwxyz");
char s[6] = "abcde";
str.append(ss);//在str末尾添加字符串ss
cout<<str<<endl;
str = "123456";
str.append(ss,2,2);//在str末尾添加字符串ss從第2個元素開始長度爲2的子字符串
cout<<str<<endl;
str = "123456";
str.append(s,3);//在str末尾添加c_string類型字符串s的前3個字符
cout<<str<<endl;
str = "123456";
str.append(s);//在str末尾添加c_string類型字符串s
cout<<str<<endl;
str = "123456";
str.append(3,'a');//在str末尾添加3個字符a
cout<<str<<endl;
str = "123456";
str.append(ss.begin()+1,ss.end());//在str末尾添加字符串ss在區間[1,4]上的子字符串
cout<<str<<endl;
return 0;
}
程序運行結果爲:
123456vwxyz
123456xy
123456abc
123456abcde
123456aaa
123456wxyz
6.字符串內容的替換
如果在一個字符串中標識出具體位置,便可以通過下標操作修改指定位置字符的值,或者替換某個子串。完成此項操作需要使用 string 類的成員函數 replace()。
replace() 函數的原型如下:
basic_string& replace(size_type pos, size_type n, const basic_string& str);
//將調用串從第pos個元素開始長度爲n的子字符串(即區間[pos,pos+n-1]的子字符串)替換爲字符串str
basic_string& replace(size_type pos1, size_type n1, const basic_string& str,size_type pos2, size_type n2 = npos);//將調用串從第pos1個元素開始長度爲n1的子字符串(即區間[pos1,pos1 + n1 -1]的子字符串)替換爲字符串str從第pos2個元素開始長度爲n2的子字符串(即區間[pos2,pos2 + n2 -1]的子字符串)(n2默認值指向末尾)
basic_string& replace(size_type pos, size_type n1, const char* s,size_type n2);
//將調用串位於區間[pos,pos+n1 - 1]的子字符串替換爲c_string類型字符串s的前n2個字符
basic_string& replace(size_type pos, size_type n1, const char* s);
//將調用串位於區間[pos,pos + n1 -1]的子字符串替換爲c_string類型字符串s
basic_string& replace(size_type pos, size_type n1, size_type n2, char c);
//將調用串位於區間[pos,pos + n1 -1]的子字符串替換爲n2個字符c
basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str);
//將迭代器i1,i2指向的元素之間的字符串(包括i1)替換爲字符串str
basic_string& replace(const_iterator i1, const_iterator i2,const char* s, size_type n);
//將迭代器i1,i2指向的元素之間的字符串(包括i1)替換爲c_string類型字符串s的前n個字符
basic_string& replace(const_iterator i1, const_iterator i2, const char* s);
//將迭代器i1,i2指向的元素之間的字符串(包括i1)替換爲c_string類型的字符串s
basic_string& replace(const_iterator i1, const_iterator i2, size_type n, char c);
//將迭代器i1,i2指向的元素之間的字符串(包括i1)替換爲n個字符c
basic_string& replace(const_iterator i1, const_iterator i2,InputIterator k1, InputIterator k2);
//將迭代器i1,i2指向的元素之間的字符串(包括i1)替換爲迭代器k1,k2指向的元素之間的字符串(包括k1)
basic_string& replace(const_iterator i1, const_iterator i2 , char* k1, char* k2);
//在測試的時候直接輸入k2沒有作用,要輸入k2+(一個常數)表示k2的前幾位,在下面的例子會有註釋介紹
basic_string& replace(const_iterator i1, const_iterator i2, iterator k1, iterator k2);//使用迭代器替換
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("123456");
string ss("vwxyz");
char s1[6] = "abcde";
char s2[6] = "qwert";
str.replace(2,3,ss);//將str[2,4]的字符串替換爲字符串ss
cout<<str<<endl;
str = "123456";
str.replace(2,3,ss,1,3);//將str[2,4]的字符串替換爲字符串ss[1,3]
cout<<str<<endl;
str = "123456";
str.replace(1,2,s1,3);//將str[1,2]的字符串替換爲c_string類型字符串s1的前3個字符
cout<<str<<endl;
str = "123456";
str.replace(1,2,s1);//將str[1,2]的字符串替換爲c_string類型字符串s1
cout<<str<<endl;
str = "123456";
str.replace(3,2,6,'a');//將str[3,4]的字符串替換爲6個'a',即aaaaaa
cout<<str<<endl;
str = "123456";
str.replace(str.begin()+1,str.begin()+4,ss);//將str[1,4)的字符串替換爲字符串ss
cout<<str<<endl;
str = "123456";
str.replace(str.begin()+1,str.begin()+4,s1,3);//將str[1,4)的字符串替換爲c_string類型字符串的前3個字符
cout<<str<<endl;
str = "123456";
str.replace(str.begin()+1,str.begin()+4,s1);//將str[1,4)的字符串替換爲c_string類型字符串s1
cout<<str<<endl;
str = "123456";
str.replace(str.begin(),str.begin()+5,6,'c');//將str[0,5)的字符串替換爲6個字符c
cout<<str<<endl;
str = "123456";
str.replace(str.begin()+1,str.begin()+3,s1,s2+3);//將str[1,3)的字符串替換爲c_string類型字符串s1+s2的前3個字符
//值的注意的是,s2+n保留s2的前n個字符。而s1+n,則保留s1從第n個字符開始直到末尾的字符串
//即str.replace(str.begin()+1,str.begin()+3,s1+2,s2+3);//則輸出1cdeqwe456
cout<<str<<endl;
str = "123456";
str.replace(str.begin(),str.end(),ss.begin(),ss.end());//將str替換爲ss
cout<<str<<endl;
return 0;
}
以下爲程序運行結果:
12vwxyz6
12wxy6
1abc456
1abcde456
123aaaaaa6
1vwxyz56
1abc56
1abcde56
cccccc6
1abcdeqwe456
vwxyz
7.字符串的比較
字符串可以和類型相同的字符串相比較,也可以和具有同樣字符類型的數組比較。
basic_string 類模板既提供了 >、<、==、>=、<=、!= 等比較運算符,還提供了 compare() 函數,其中 compare() 函數支持多參數處理,支持用索引值和長度定位子串進行比較。該函數返回一個整數來表示比較結果。如果相比較的兩個子串相同,compare() 函數返回 0,大於返回正值,小於返回負值。
- compare()
比較兩字符串大小
類 basic_string 的成員函數 compare() 的原型如下:
int compare(const basic_string& str) const;//直接與str比較
int compare(size_type pos, size_type n, const basic_string& str) const;
//調用串在區間[pos,pos+n-1]上的子字符串與字符串str比較
int compare(size_type pos1, size_type n1, const basic_string& str,size_type pos2, size_type n2 = npos) const;//調用串在區間[pos1 , pos1 + n1 -1]上的子字符串與字符串str在區間[pos2,pos2+n2 - 1]上的子字符串比較(n2默認指向末尾)
int compare(const char* s) const; //直接與c_string類型的字符串s比較
int compare(size_type pos, size_type n1, const char* s) const;
//調用串在區間[pos,pos+n1 - 1]上的子字符串與c_string類型字符串s比較
int compare(size_type pos, size_type n1, const char* s,size_type n2) const;
//調用串在區間[pos,pos+n1 - 1]上的子字符串與c_string類型字符串s的前n2個字符比較
【例】
#include<iostream>
#include<string>
using namespace std;
string comp(int result)
{
if(result==0)
return "=";
else if (result>0)
return ">";
else
return "<";
}
int main()
{
string str("123456");
string ss("1234");
char s[6] = "123ab";
int result;
result = str.compare(ss);//123456與1234比較
cout<<comp(result)<<endl;
result = str.compare(0,5,ss);//12345與1234比較
cout<<comp(result)<<endl;
result = str.compare(0,2,ss,2,2);//12與34比較
cout<<comp(result)<<endl;
result = str.compare(s);//123456與123ab比較
cout<<comp(result)<<endl;
result = str.compare(0,3,s);//123與123ab比較
cout<<comp(result)<<endl;
result = str.compare(0,3,s,3);//123與123比較
cout<<comp(result)<<endl;
return 0;
}
下面爲程序運行結果:
>
>
<
<
<
=
- 重載操作符<,>,==,<=,>=,!=
與數字的比較相同,不再贅述
值得一提的是字符串比較規則:
- 字符串比較大小並不是比較二者的長度。
- 字符串比較大小,從左數第一個字符開始進行比較
- 進行比較的是兩字符的ASCII碼的大小
- 逐一進行比較,如果出現差異直接結束比較,否則繼續比較下一個字符,直到某一個字符串結束
8.字符串的查找
在 C 語言和 C++ 語言中,可用於實現字符串查找功能的函數非常多。在 STL 中,字符串的查找功能可以實現多種功能,比如說:
- 搜索單個字符、搜索子串;
- 實現前向搜索、後向搜索;
- 分別實現搜索第一個和最後一個滿足條件的字符(或子串);
若查找 find() 函數和其他函數沒有搜索到期望的字符(或子串),則返回 npos;若搜索成功,則返回搜索到的第 1 個字符或子串的位置。其中,npos 是一個無符號整數值,初始值爲 -1。當搜索失敗時, npos 表示“沒有找到(not found)”或“所有剩佘字符”。
值得注意的是,所有查找 find() 函數的返回值均是 size_type 類型,即無符號整數類型。該返回值用於表明字符串中元素的個數或者字符在字符串中的位置。
下面分別介紹和字符查找相關的函數。
- find()和rfind()
find() 函數的原型有以下 4 種:
size_type find(const char* s, size_type pos, size_type n) const;
//第1個參數是被搜索的字符串,第2個參數是源串中開始搜索的下標,第3個參數是關於第1個參數的字符個數,可能是 s 的所有字符數,也可能是 s 的子串宇符個數
size_type find(const basic_string& str, size_type pos = 0) const;
//find()函數的第1個參數是被搜索的字符串,第2個參數是在源串中開始搜索的下標位置,默認從頭開始搜索
size_type find(const char* s, size_type pos = 0) const;
//同上,搜索c_string類型字符串
size_type find(char c, size_type pos = 0) const;
//第1個參數是被搜索的單個字符,第2參數是在源串中開始搜索的下標位置,默認從頭開始搜索
rfind() 函數的原型和find()函數的原型類似,參數情況也類似。只不過 rfind() 函數適用於實現逆向查找。
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("Try not to become a man of success "
"but rather try to become a man of value");
string search("but");
string::size_type position1 = str.find("best");
string::size_type position2 = str.find('o');
string::size_type position3 = str.find("todoit",0,2);
cout<<static_cast<int>(position1)<<endl;
cout<<static_cast<int>(position2)<<endl;
cout<<static_cast<int>(position3)<<endl;
string::size_type position4 = str.rfind(search);
string::size_type position5 = str.rfind('o');
string::size_type position6 = str.rfind("todoit",string::npos,2);
cout<<static_cast<int>(position4)<<endl;
cout<<static_cast<int>(position5)<<endl;
cout<<static_cast<int>(position6)<<endl;
return 0;
}
- find_first_of()和 find_last_of()
find_first_of() 函數可實現在源串中搜索某字符串的功能,該函數的返回值是被搜索字符串的某 1 個字符第 1 次出現的下標(位置)。若查找失敗,則返回 npos。
size_type find_first_of(const basic_string& str, size_type pos = 0) const;
//搜索str字符串中的字符第一次在調用串中出現的位置,pos爲搜索起點,默認從頭開始
size_type find_first_of(const char* s, size_type pos, size_type n) const;
//搜索c_string類型字符串s的前n個字符第一次在調用串中出現的位置,pos爲搜索起點
size_type find_first_of(const char* s, size_type pos = 0) const;
//搜索c_string類型字符串s中的字符第一次在調用串中出現的位置,pos爲搜索起點,默認從頭開始
size_type find_first_of(char c, size_type pos = 0) const;
//搜索字符c第一次在調用串中出現的位置,pos爲搜索起點,默認從頭開始
find_last_of() 函數同樣可實現在源串中搜索某字符串的功能。函數的原型和find_first_of()函數的原型類似,參數情況也類似。與 find_first_of() 函數所不同的是,該函數的返回值是被搜索字符串的最後 1 個字符的下標(位置)。若查找失敗,則返回 npos。
- find_first_not_of()和 find_last_not_of()
find_first_not_of() 函數可實現在源字符串中搜索與指定字符(串)不相等的第 1 個字符;
find_last_not_of() 函數可實現在源字符串中搜索與指定字符(串)不相等的最後 1 個字符。
這兩個函數的參數及意義與find_first_of() 和 find_last_of()相同,不再贅述。
【例】
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str("Try not to become a man of success "
"but rather try to become a man of value");
string search("but");
char sh[5] = "some";
string::size_type position1 = str.find_first_of("best");
string::size_type position2 = str.find_first_of(sh,34,1);//從str[34]開始搜索第一個爲s的字符
string::size_type position3 = str.find_first_of(sh,0);
string::size_type position4 = str.find_first_of('v');
cout<<static_cast<int>(position1)<<endl;
cout<<static_cast<int>(position2)<<endl;
cout<<static_cast<int>(position3)<<endl;
cout<<static_cast<int>(position4)<<endl;
string::size_type position5 = str.find_first_not_of(" abcTrynot");
string::size_type position6 = str.find_first_not_of(sh,0,2);//搜索第一個不是s,o,m的字符
string::size_type position7 = str.find_first_not_of(sh,0);//從str的頭開始搜索第一個不是s,o,m,e的字符
string::size_type position8 = str.find_first_not_of('e');//搜索第一個不是e的字符
cout<<static_cast<int>(position5)<<endl;
cout<<static_cast<int>(position6)<<endl;
cout<<static_cast<int>(position7)<<endl;
cout<<static_cast<int>(position8)<<endl;
string::size_type position9 = str.find_last_of(" abcTrynot");
string::size_type position10 = str.find_last_of(sh,string::npos,2);
string::size_type position11 = str.find_last_of(sh,string::npos);
string::size_type position12 = str.find_last_of('e');
cout<<static_cast<int>(position9)<<endl;
cout<<static_cast<int>(position10)<<endl;
cout<<static_cast<int>(position11)<<endl;
cout<<static_cast<int>(position12)<<endl;
string::size_type position13 = str.find_last_not_of(" abcTrynot");
string::size_type position14 = str.find_last_not_of(sh,string::npos,3);
string::size_type position15 = str.find_last_not_of(sh,string::npos);
string::size_type position16 = str.find_last_not_of('e');
cout<<static_cast<int>(position13)<<endl;
cout<<static_cast<int>(position14)<<endl;
cout<<static_cast<int>(position15)<<endl;
cout<<static_cast<int>(position16)<<endl;
return 0;
}
程序運行結果爲:
6
-1
5
69
12
0
0
0
70
66
73
73
73
73
72
72
9.string支持迭代器
迭代器(iterator)是一種對象,它能夠用來遍歷標準模板庫容器中的部分或全部元素,每個迭代器對象代表容器中的確定的地址。迭代器修改了常規指針的接口,所謂迭代器是一種概念上的抽象:那些行爲上像迭代器的東西都可以叫做迭代器。然而迭代器有很多不同的能力,它可以把抽象容器和通用算法有機的統一起來。
迭代器提供一些基本操作符:*、++、==、!=、=。這些操作和C/C++“操作array元素”時的指針接口一致。不同之處在於,迭代器是個所謂的複雜的指針,具有遍歷複雜數據結構的能力。其下層運行機制取決於其所遍歷的數據結構。因此,每一種容器型都必須提供自己的迭代器。事實上每一種容器都將其迭代器以嵌套的方式定義於內部。因此各種迭代器的接口相同,型號卻不同。這直接導出了泛型程序設計的概念:所有操作行爲都使用相同接口,雖然它們的型別不同。
STL 定義了 5 種迭代器,根據所需的迭代器類型對算法進行描述。這 5 種迭代器分別是:輸入迭代器 、輸出迭代器 、 正向迭代器、 雙向迭代器 和 隨機訪問迭代器。對於這 5 種迭代器不僅可以執行解除引用操作(* 操作符),還可進行比較。這裏主要講述 basic_string(或 string 類)中迭代器的使用。
basic_string 和 string 類均提供了常規的迭代器和反向迭代器。string 是字符的有序羣集。
C++ 標準庫爲 string 提供了相應接口,便於將字符串作爲 STL 容器使用。可以使用迭代器遍歷 string 內的所有字符;也可以使用其他算法遍歷 string 內的所有字符。而且能夠訪問字符串中的每個字符,並對這些字符進行排序、逆向重排、找出最大值等操作。
string 類的迭代器是隨機存取迭代器,即支持隨機存取。任何一個 STL 算法都可與其搭配使用。通常 string 的“迭代器型別”由 string 類本身定義,通常可以被簡單地定義爲一般指針。對迭代器而言,如果發生重新分配,或其所指的值發生某些變化時,迭代器會失效。
string 類中和使用迭代器相關的成員函數是很多的,主要包括 begin()、end()、rbegin ()、rend()、append()、assign()、insert()、erase()、replace() 等。
名稱 | 功能 |
---|---|
begin( ) | 返回指向字符串第一個字符的迭代器。 |
end() | 返回指向字符串最後一個字符(’\0’)的迭代器。 |
cbegin() | 返回指向字符串第一個字符的const類型迭代器。 |
cend() | 返回指向字符串最後一個字符(’\0’)的const類型迭代器。 |
rbegin() | 返回一個反向迭代器,該迭代器指向字符串的最後一個字符(即它的反向開始)。 |
rend() | 返回一個反向迭代器,該迭代器指向字符串第一個字符之前的理論元素(該字符被視爲反向元素)。 |
crbegin() | 返回一個const類型反向迭代器,該迭代器指向字符串的最後一個字符(即它的反向開始)。 |
crend() | 返回一個const類型反向迭代器,該迭代器指向字符串第一個字符之前的理論元素(該字符被視爲反向元素)。 |
begin()與cbegin()的區別是 begin()指向非const的字符串時,可以對其進行修改,而cbegin()只能指向const類型字符串(即開頭的c表示const,r表示reverse)。其餘同上。
#include<iostream>
#include<string>
#include<algorithm>
#include<iterator>
using namespace std;
int main()
{
string str("Standing up to your own."
"That would take a real hero.");
cout<<str<<endl;
string::iterator it;//使用正向迭代器遍歷字符串
for(it = str.begin();it!=str.end();it++)
cout<<*it;
//function();//可以進行其他操作
cout<<endl;
string::reverse_iterator rev_it;//使用反向迭代器倒序輸出字符串
for(rev_it = str.rbegin();rev_it!=str.rend();rev_it++)
cout<<*rev_it;
//function();//可以進行其他操作
cout<<endl;
std::ostreambuf_iterator<char> out_it(std::cout);//使用輸出流迭代器正序輸出字符串
std::copy(str.begin(),str.end(),out_it);
cout<<endl;
std::ostreambuf_iterator<char> rev_out_it(std::cout);//使用輸出流迭代器倒序輸出字符串
std::copy(str.rbegin(),str.rend(),rev_out_it);
cout<<endl;
//還有各種函數中使用迭代器,在上文已經涉及
return 0;
}
程序運行結果爲:
Standing up to your own.That would take a real hero.
Standing up to your own.That would take a real hero.
.oreh laer a ekat dluow tahT.nwo ruoy ot pu gnidnatS
Standing up to your own.That would take a real hero.
.oreh laer a ekat dluow tahT.nwo ruoy ot pu gnidnatS
資料來源
- The C++ Resources Network(http://www.cplusplus.com)
- C語言中文網(http://m.biancheng.net)
- 百度百科 (https://baike.baidu.com/item/capacity/6299959)
- 百度百科 (https://baike.baidu.com/item/%E8%BF%AD%E4%BB%A3%E5%99%A8)