C++ string使用方法詳細介紹

更多關於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;
}

下面爲程序運行結果:

>
>
<
<
<
=

  • 重載操作符<,>,==,<=,>=,!=
    與數字的比較相同,不再贅述

值得一提的是字符串比較規則:

  1. 字符串比較大小並不是比較二者的長度。
  2. 字符串比較大小,從左數第一個字符開始進行比較
  3. 進行比較的是兩字符的ASCII碼的大小
  4. 逐一進行比較,如果出現差異直接結束比較,否則繼續比較下一個字符,直到某一個字符串結束

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

資料來源

  1. The C++ Resources Network(http://www.cplusplus.com
  2. C語言中文網(http://m.biancheng.net
  3. 百度百科 (https://baike.baidu.com/item/capacity/6299959
  4. 百度百科 (https://baike.baidu.com/item/%E8%BF%AD%E4%BB%A3%E5%99%A8
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章