C++標準庫型別string用法小結

li27z發表於2017-03-27

標準庫型別string表示可變長的字元序列,使用string型別必須首先包含string標頭檔案。作為標準庫的一部分,string定義在名稱空間std中。

#include <string>
using namaspace std::string;

常用操作羅列

 =, assign()   // 賦以新值
 swap()   // 交換兩個字串的內容
 +=, append(), push_back()  // 在尾部新增字元
 insert()  // 插入字元
 erase()  // 刪除字元
 clear()  // 刪除全部字元
 replace()  // 替換字元
 +  // 串聯字串
 ==, !=, <, <=, >, >=, compare()  // 比較字串
 size(), length()  // 返回字元數量
 max_size()  // 返回字元的可能最大個數
 empty()  // 判斷字串是否為空
 capacity()  // 返回重新分配之前的字元容量
 reserve()  // 保留一定量記憶體以容納一定數量的字元
 [ ], at()  // 返回某一位置的字元
 >>, getline()  // 輸入
 <<  // 輸出
 copy()  // 拷貝
 c_str()  // 將內容以C_string返回
 data()  // 返回一個非null終止的c字元陣列
 substr()  // 返回某個子字串
 查詢函式(find, rfind...)
 begin(), end()  // 提供類似STL的迭代器支援
 rbegin(), rend()  // 逆向迭代器
 get_allocator()  // 返回配置器

定義和初始化string物件

1.以預設的方式初始化一個string物件:

string s;  // 會得到一個空的string,該string物件中沒有任何字元

2.如果提供了一個字串字面值,則該字面值中除了最後那個空字元外其他所有的字元都被拷貝到新建立的string物件中去。

string s("Hello");  // s是字面值"Hello"的副本,除了字面值最後的那個空字元外
string s = "Hello";  // 等價於s("Hello")

3.如果提供的是一個數字和一個字元,則string物件的內容是給定字元連續重複若干次後得到的序列。

string s(10, 'a');  // 把s初始化為由連續10個字元'a'組成的串,即"aaaaaaaaaa"

string物件上的基本操作

1.讀寫string物件

使用IO操作符讀寫string物件:

// 注:在執行讀取操作時,string物件會自動忽略開頭的空白並從第一個真正的字元開始讀起,直到遇見下一處空白
// 例如:輸入“   Hello World”,輸出將是“Hello”
string s;
cin >> s;
cout << s << endl;

使用getline讀取一整行:
有時我們希望能在最終得到的字串中保留輸入時的空白符,這時應該用getline函式代替原來的>>運算子。getline函式的引數是一個輸入流和一個string物件,函式從給定的輸入流中讀入內容,直到遇到換行符為止(注意:換行符也讀進來了),然後把所讀的內容存入到那個string物件中去(注意:不存換行符)。

string line;
while(getline(cin, line))
    cout << line << endl;

2.string的empty和size操作

empty函式根據string物件是否為空返回一個對應的布林值。

size函式返回string物件的長度(即string物件中字元的個數),size函式返回的是一個string::size_type型別的值(是一個無符號型別的值)。

3.比較string物件

相等性運算子(== 和 !=)分別檢驗兩個string物件相等或不相等,string物件相等意味著它們的長度相同而且所包含的字元也全都相同。

關係運算子<、<=、>、>=分別檢驗一個string物件是否小於、小於等於、大於、大於等於另外一個string物件,這些運算子都依照(大小寫敏感的)字典排序。

如果兩個string物件的長度不同,且較短的string物件的每個字元都與較長string物件對應位置上的字元相同,則認為較短string物件小於較長string物件。

如果兩個string物件在某些對應的位置上不一致,則string物件比較的結果是string物件中的第一對相異字元比較的結果。

標準庫string型別還提供了一組compare函式進行string物件的比較:

int compare(const string &s) const;  // 比較當前字串和s的大小
int compare(int pos, int n, const string &s) const;  // 比較當前字串從pos開始的n個字元組成的字串與s的大小
int compare(int pos, int n, const string &s, int pos2, int n2) const;  //比較當前字串從pos開始的n個字元組成的字串與s中從pos2開始的n2個字元組成的字串的大小
int compare(const char *s) const;
int compare(int pos, int n, const char *s) const;
int compare(int pos, int n, const char *s, int pos2) const;

返回值:
>時返回1,<時返回-1,==時返回0  

4.相加操作

兩個string物件相加(使用加法運算子 +)得到一個新的string物件,其內容是把左側的運算物件與右側的運算物件串接而成。

複合賦值運算子(+=)負責把右側string物件的內容追加到左側string物件的後面。

string s1 = "Hello, ", s2 = "World";
string s3 = s1 + s2;  // s3的內容是"Hello, World"
s1 += s2;  // 等價於s1 = s1 + s2

字面值也可與string物件相加,但要注意,當把string物件和字元字面值及字串字面值混在一條語句中使用時(字串字面值與string是不同的型別),必須確保每個加法運算子(+)的兩側的運算物件至少有一個是string。

例:

string s = s1 + ",";   // 正確
string s = "hello" + ",";  // 錯誤
string s = s1 + "," + "world";  // 正確

處理string物件中的字元

我們經常需要單獨處理string物件中的字元,有時需要處理string物件中的每一個字元,有時只需處理string物件中的某個特定的字元…

首先來了解一下改變某個字元特性的一些函式:

cctype標頭檔案中的函式,列舉幾個常用的:

isalpha(c)  // 當c是字母時為真
isdigit(c)  // 當c是數字時為真
islower(c)  // 當c是小寫字母時為真
isspace(c)  // 當c是空白時為真
isupper(c)  // 當c是大寫字母時為真
tolower(c)  // 如果c是大寫字母,輸出對應的小寫字母,否則原樣輸出c
toupper(c)  // 如果c是小寫字母,輸出對應的大寫字母,否則原樣輸出c

要想訪問string物件中的單個字元有兩種方式:一種是使用下標,另外一種是使用迭代器。

1.使用下標
無論何時用到字串的下標,都應該注意檢查其合法性。

例:

// 使用下標運算子輸出string物件中的第一個字元
if(!s.empty())
    cout << s[0] << endl;

// 使用下標執行隨機訪問--把0到15之間的十進位制數轉換成對應的十六進位制數
const string hexdigits = "0123456789ABCDEF";
string result;
string::size_type n;
while(cin >> n)
    if(n < hexdigits.size())
        result += hexdigits[n];
cout << "Your hex number is: " << result << endl; 

2.使用迭代器
迭代器提供對物件的間接訪問,其物件是容器中的元素或者string物件中的字元。使用迭代器可以訪問某個元素,也可以從一個元素移動到另一個元素。

例:

// 處理string物件中的字元直至處理完全部字元或遇到空白
string::iterator it;
for(it = s.begin(); it != s.end() && !isspace(*it); ++it)
    *it = toupper(*it);  // 將當前字元改成大寫形式

構造string的其他方法

1.string s(cp, n)
s是cp指向的字元陣列中的前n個字元的拷貝。此陣列至少應該包含n個字元。

例:

const char *cp = "Hello World!";
char noNull[] = {'H', 'i'};
string s1(cp);  // 拷貝cp中的字元直到遇到空字元 '\0',s1 == "Hello World!"
string s2(noNull, 2);  // 從noNull拷貝兩個字元,s2 == "Hi"
string s3(noNull);  // 未定義:noNull不是以空字元 '\0' 結束

2.string s(s2, pos2)
s是string s2從下標pos2開始的字元的拷貝。若pos2 > s2.size(),建構函式的行為未定義。

例:

const char *cp = "Hello World!";
string s1(cp);  // 拷貝cp中的字元直到遇到空字元 '\0',s1 == "Hello World!"
string s2(s1, 6);  // 從s1[6]開始拷貝,直至s1末尾,s2 == "World!"
string s3(s1, 16);  // 丟擲out_of_range異常

3.string s(s2, pos2, len2)
s是string s2從下標pos2開始len2個字元的拷貝。若pos2 > s2.size(),建構函式的行為未定義。不管len2的值是多少,建構函式至多拷貝s2.size() - pos2個字元。

例:

const char *cp = "Hello World!";
string s1(cp);  // 拷貝cp中的字元直到遇到空字元 '\0',s1 == "Hello World!"
string s2(s1, 6, 5);  // 從s1[6]開始拷貝5個字元,s2 == "World"
string s3(s1, 6, 15);  // 從s1[6]開始拷貝,只拷貝到s1末尾,s3 == "World!"  

4.substr操作

s.substr(pos, n) 返回一個string,包含s中從pos開始的n個字元的拷貝。pos的預設值為0。n的預設值為s.size() - pos,即拷貝從pos開始的所有字元。

例:

string s("Hello world");
string s2 = s.substr(0, 5);  // s2 == "Hello"
string s3 = s.substr(6);  // s3 == "world"
string s4 = s.substr(6, 11);  // s4 == "world"
string s5 = s.substr(12);  // out_of_range

修改string的操作

1.assign操作

string &assign(const char *s);  // 用c型別字串s賦值
string &assign(const char *s, int n);  // 用c字串s開始的n個字元賦值
string &assign(const string &s);  // 把字串s賦給當前字串
string &assign(int n, char c);  // 用n個字元c賦值給當前字串
string &assign(const string &s, int start, int n);  // 把字串s中從start開始最多n個字元賦給當前字串
template <class InputIterator>
string& assign (InputIterator first, InputIterator last);  // 把first和last迭代器之間的部分賦給字串

2.insert操作

// 以下4個函式在p位置之前插入字串s中pos開始最多n個字元
string &insert(int p, const char *s);
string &insert(int p, const char *s, int n);
string &insert(int p, const string &s);
string &insert(int p, const string &s, int pos, int n);

string &insert(int pos, int n, char c);  // 在pos之前插入n個字元c
iterator insert(iterator it, char c);  // 在it之前插入字元c,返回插入後迭代器的位置
template <class InputIterator>
void insert (iterator p, InputIterator first, InputIterator last);  // 在it之前插入[first,last)之間的字元
void insert(iterator it, int n, char c);  // 在it之前插入n個字元c

3.erase操作

iterator erase(iterator first, iterator last);  // 刪除[first,last)之間的所有字元,返回指向最後一個被刪元素之後元素的迭代器
iterator erase(iterator it);  // 刪除it指向的字元,返回被刪元素之後元素的迭代器
string &erase(int pos = 0, int n = npos);  // 刪除pos開始的n個字元,返回修改後的字串

4.append操作
append操作是在string末尾進行插入操作的一種簡寫形式:

例:

string s("Hello"), s2 = s;  // 將s和s2初始化為"Hello"
s.insert(s.size(), " world");  // s == "Hello world"
s2.append(" world");  // 等價方法,s == s2

5.replace操作
replace操作是呼叫erase和insert的一種簡寫形式:

例:

string s("C++ 4th Edition"), s2 = s;  // 將s和s2初始化為"C++ 4th Edition"
s.erase(4, 3);  // s == "C++  Edition" 
s.insert(4, "5th");  // s == "C++ 5th Edition"
s2.replace(4, 3, "5th");  // 等價方法:s == s2

string搜尋操作

函式原型如下(rfind()類似,只是從反向查詢):

size_t find (const string& str, size_t pos = 0) const;  // 從pos開始查詢字串s在當前串中的位置
size_t find (const char* s, size_t pos = 0) const; // 從pos開始查詢字串s在當前串中的位置
size_t find (const char* s, size_t pos, size_t n) const;  // 從pos開始查詢字串s中前n個字元在當前串中的位置
size_t find (char c, size_t pos = 0) const;  // 從pos開始查詢字元c在當前字串的位置

返回值:
找到則返回第一個字元的索引
沒找到則返回 string::npos

例:

string name("AnnaBelle");
int pos = name.find("Anna");  // pos == 0
pos = name.find("anna");  // pos == npos

其他還有 find_first_of(),find_last_of(),find_first_not_of(),find_last_not_of(),作用是查詢字串中任一個字元滿足的查詢條件。

例:

string s("cobra");
int index = s.find_first_of("hark");  // 返回3,因為"hark"中的字元在s--"cobra"中第一次出現的是字元'r'3"cobra"'r'的索引)
index = s.find_last_of("hark");  // 返回4,因為"hark"中的字元在s--"cobra"中最後一次出現的是字元'a'4"cobra"'a'的索引)

string和C字串的轉換

C++提供的由C++字串得到對應的C_string的方法是使用data()、c_str()和copy(),其中,data()以字元陣列的形式返回字串內容,但並不新增’\0’。c_str()返回一個以’\0’結尾的字元陣列,而copy()則把字串的內容複製或寫入既有的c_string 或字元陣列內。C++字串並不以’\0’結尾。

const char *data() const;  // 返回一個非null終止的c字元陣列
const char *c_str() const;  // 返回一個以null終止的c字串
int copy(char *s, int n, int pos = 0) const;  // 把當前串中從pos開始的n個字元拷貝到以s為起始位置的字元陣列中,返回實際拷貝的數目

參考資料:
C++ string 用法詳解. https://www.byvoid.com/zht/blog/cpp-string
標準C++中的string類的用法總結. http://www.cnblogs.com/xFreedom/archive/2011/05/16/2048037.html
《C++ Primer(第5版)》

更多C++標準庫型別string的資料可查閱 http://www.cplusplus.com/reference/string/

相關文章