我不熟悉的string類
我不常用的string函式
多的不說,直接上:
assign函式
string& assign(const char *s); //把字串s賦給當前的字串 string& assign(const string &s); //把字串s賦給當前字串 string& assign(const char *s, int n);//把字串s的前n個字元賦給當前的字串 string& assign(int n, char c); //用n個字元c賦給當前字串 string& assign(const string &s, int start, int n);//將s從start開始n個字元賦值給字串
assign函式很好用的。在我實習期間,將資料包轉成字串arr的時候,我直接用:
string str = arr;
最後出現了資料缺失的現象。這就是因為轉成的字串arr中間含有結束符,而如果我用賦值運算子的話,賦值到這個結束符就會停止,後面的資料都會被拋棄。
這個時候assign函式就派上了用場,我指定字串的大小,就可以全部賦值進去。下面用一個簡單例子來說明:
int main() { string str; char arr[5] = { 'a', 'c', 's', '\0', 'e' }; str = arr; cout << "使用str = arr的結果:" << endl; cout << "str = " << str << endl; cout << "str.size() = " << str.size() << endl; cout << "str.capacity() = " << str.capacity() << endl; cout << endl << "使用str.assign的結果:" << endl; string ss = str.assign(arr, 5); cout << "str = " << ss << endl; cout << "str.size() = " << ss.size() << endl; cout << "str.capacity() = " << ss.capacity() << endl; return 0; }
執行結果:
可以看到,無論是列印結果還是size,都不一樣。足以說明assign並不是以結束符為界。
assign函式可以重新賦值,可以從一個char * 或string的變數中讀取指定位元組數去賦值。
at函式
at函式和普通的過載運算子[]都是取元素的操作,但是at函式提供邊界檢查,當陣列越界的時候會丟擲異常,如果我們捕捉異常程式就可以正常進行下去。
int main() { string str = "abcdefg"; try{ str.at(10); //str[10]; } catch (exception &e) { cout << e.what() << endl; } return 0; }
當我們用at執行,結果為:
我們可以捕捉到這個異常:無效的字串位置。
而如果我們使用str[10]則會直接崩潰。
append函式
關於append函式,顧名思義就是在末尾新增。這就沒什麼好說的了,平常我用的不多,所以記錄下來append函式各種過載版本。
string& append(const char *s); //把字串s連線到當前字串結尾
string& append(const char *s, int n); //把字串s的前n個字元連線到當前字串結尾
string& append(const string &s); //同operator+=()
string& append(const string &s, int pos, int n);//把字串s中從pos開始的n個字元連線到當前字串結尾
string& append(int n, char c); //在當前字串結尾新增n個字元c
綜上,append函式可以連線一個char,char * ,string,以及string和char * 中指定位元組數。
查詢和替換函式
即find, rfind, replace 函式。
int find(const string& str, int pos = 0) const; //查詢str第一次出現位置,從pos開始查詢
int find(const char* s, int pos = 0) const; //查詢s第一次出現位置,從pos開始查詢
int find(const char* s, int pos, int n) const; //從pos位置查詢s的前n個字元第一次位置
int find(const char c, int pos = 0) const; //查詢字元c第一次出現位置
int rfind(const string& str, int pos = npos) const; //查詢str最後一次位置,從pos開始查詢
int rfind(const char* s, int pos = npos) const; //查詢s最後一次出現位置,從pos開始查詢
int rfind(const char* s, int pos, int n) const; //從pos查詢s的前n個字元最後一次位置
int rfind(const char c, int pos = npos) const; //查詢字元c最後一次出現位置
string& replace(int pos, int n, const string& str); //替換從pos開始n個字元為字串str
string& replace(int pos, int n, const char* s); //替換從pos開始的n個字元為字串s
先來說一下查詢功能:
find
find就是從0位置找到最後一個位置為止,第一次出現返回其位置。
注意其引數,無論是string還是char或者是char * ,我們都可以查詢。
另外,如果要查詢一串字元的前n個字元是否出現過,find的第一個引數是const char * ,而不是string. 所以我們要傳入一個C-style的字串才可以。
rfind
rfind就是find的反過來,從末尾位置查詢到0位置,出現的第一次返回其位置。也就是在原本字串中最後一次出現的位置。
和find一樣,倘若要查詢一個字串前n個字元,需要轉成C-style風格字串(使用c_str()函式即可)。
另外我們注意到,find是從0位置開始查詢,而rfind的預設引數值是npos,npos是什麼呢?
std::string::npos
這邊先引入C++官方的解釋:
static const size_t npos = -1;
Maximum value for size_t
npos is a static member constant value with the greatest possible value for an element of type size_t.
This value, when used as the value for a len (or sublen) parameter in string's member functions, means "until the end of the string".
As a return value, it is usually used to indicate no matches.
This constant is defined with a value of -1, which because size_t is an unsigned integral type, it is the largest possible representable value for this type.
好的現在來歸納這四個段落寫了什麼。
- std::string::npos是一個static const size_t型別的,定義為-1,也就是無符號數的最大值。
- 當在string類函式中被用作一個作為長度的引數時, 以為著字串的末尾。
- 如果是作為一個返回值,通常表示為找到合適匹配(匹配失敗)。
- 由於size_t是一個無符號的整型,所以,npos是表示size_t的最大值。
綜上,講得很清楚了吧。新增一點,size_t是四個位元組的,所以npos為4294967295.
以下簡單驗證了find和rfind的函式:
int main()
{
string str = "abcdefghabcdefgh";
char *p = "de";
string s = "efg";
// 輸出find函式返回的位置
cout << str.find(p) << endl;
cout << str.find(s.c_str(), 0, 2) << endl;
// 輸出rfind函式返回的位置
cout << str.rfind(p) << endl;
cout << str.rfind(s.c_str(), 16, 2) << endl;
cout << str.rfind('c') << endl;
// 查詢一個不存在字串的返回值
cout << str.find("gfdg") << endl;
return 0;
}
輸出結果:
replace 函式
如上述函式原型,就是源字串從pos位置開始的n個長度替換成指定的字串,可以是string型別也可以是char * 型別。
注意是單純的替換,不會因為要替換的字串長度大於n的值而覆蓋原來的。且返回一個引用,也就是說,呼叫之後會原字串會得到改變。如下程式碼顯示:
int main()
{
string str = "fuck off";
cout << str.replace(0, 3, "我不giao了") << endl; // 現在的str就改變了。所以下面重新賦值。
str = "fuck off";
cout << str.replace(4, 1, "黑貓警長giao哥") << endl;
return 0;
}
執行結果:
substr
這個其實我自己還是常用的,就是擷取子串。
//返回由pos開始的n個字元組成的字串
string substr(int pos = 0, int lenth = npos) const;
就是從pos位置開始,擷取lenth長度的字串。
插入和刪除函式
一樣,上函式原型:
string& insert(int pos, const char* s); //插入字串
string& insert(int pos, const string& str); //插入字串
string& insert(int pos, int n, char c); //在指定位置插入n個字元c
string& erase(int pos, int n = npos); //刪除從Pos開始的n個字元
插入、刪除都會直接改變原字串。返回一個引用。
字面上意思如此,注意一點,插入是在pos位置的前面插入。而刪除是從pos位置開始刪除。
如程式碼所示:
int main()
{
string str = "黑貓警長giao哥";
// 在0位置之前插入
cout << str.insert(0, "I am ") << endl;
// 從0位置開始刪除
cout << str.erase(0, 5) << endl;
// 在結尾位置插入
cout << str.insert(str.size(), "是我") << endl;
return 0;
}
執行結果如下:
C-style和string的隱式轉換關係
C-style字串可以直接賦值給string , 也就是說可以隱式轉換成string。
但是string型別不能直接隱式轉換成C-style。 但是提供了c_str函式。