1. 程式人生 > >我不熟悉的string類

我不熟悉的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.

好的現在來歸納這四個段落寫了什麼。

  1. std::string::npos是一個static const size_t型別的,定義為-1,也就是無符號數的最大值。
  2. 當在string類函式中被用作一個作為長度的引數時, 以為著字串的末尾。
  3. 如果是作為一個返回值,通常表示為找到合適匹配(匹配失敗)。
  4. 由於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函式。