1. 程式人生 > >C++字串操作詳解

C++字串操作詳解

選用C++標準程式庫中的string類,是因為他和c-string比較起來,不必擔心記憶體是否足夠、字串長度等等,而且作為一個類出現,他整合的操作函式足以完成我們大多數情況下(甚至是100%)的需要。我們可以用 = 進行賦值操作,== 進行比較,+ 做串聯。

首先,為了在我們的程式中使用string型別,我們必須包含標頭檔案 。如下:
#include //注意這裡不是string.h string.h是C字串標頭檔案
1.定義和構造初始化(參考百科,自己動手體會用法)
宣告一個字串變數很簡單:
string Str;
這樣我們就聲明瞭一個字串變數,但既然是一個類,就有建構函式和解構函式。上面的宣告沒有傳入引數,所以就直接使用了string的預設的建構函式,這個函式所作的就是把Str初始化為一個空字串。String類的建構函式和解構函式如下:
a) string s; //生成一個空字串s
b) string s(str) //拷貝建構函式 生成str的複製品
c) string s(str,stridx) //將字串str內“始於位置stridx”的部分當作字串的初值
d) string s(str,stridx,strlen) //將字串str內“始於stridx且長度頂多strlen”的部分作為字串的初值
e) string s(cstr) //將C字串作為s的初值
f) string s(chars,chars_len) //將C字串前chars_len個字元作為字串s的初值。
g) string s(num,c) //生成一個字串,包含num個c字元
h) string s(beg,end) //以區間beg;end(不包含end)內的字元作為字串s的初值
i) s.~string() //銷燬所有字元,釋放記憶體
測試如下:

# include <iostream>
# include <string>
using namespace std;
int main()
{
    string str1 = "yesterday once more";
    string str2 ("my heart go on");
    string str3 (str1,6); // = day once more
    string str4 (str1,6,3); // = day

    char ch_music[] = {"Roly-Poly"};

    string str5 = ch_music; // = Roly-Poly 
string str6 (ch_music); // = Roly-Poly string str7 (ch_music,4); // = Roly string str8 (10,'i'); // = iiiiiiii string str9 (ch_music+5, ch_music+9); // = Poly str9.~string(); //cout<<str9<<endl; // 測試輸出 getchar(); return 0; }

2.字串操作函式
這裡是C++字串的重點
1) =,assign()

//賦以新值
“=”的用法不作詳細說明,assign用法如下:

# include <iostream>
# include <string>
using namespace std;
int main()
{
    string str1 = "yesterday once more";
    string str2 ("my heart go on");
    string str3,str4;

    str3.assign(str2,3,6);  // = heart
    str4.assign(str2,3,string::npos); // = heart go on (從2開始到結尾賦給str4)
    str4.assign("gaint"); // =gaint
    str4.assign("nico",5); // = nico,超出長度會發生什麼。。。
    str4.assign(5,'x'); // = xxxxx
    cout<<str4<<endl;

    getchar();
    return 0;
}

2) swap() //交換兩個字串的內容
用法如下:

# include <iostream>
# include <string>
using namespace std;
int main()
{
    string str1 = "yesterday once more";
    string str2 ("my heart go on");

    str2.swap(str1);
    cout<<str1<<endl; // = my heart go on
    cout<<str2<<endl; // = yesterday once more

    getchar();
    return 0;
}

3) +=,append(),push_back() *//在尾部新增字元*
增加字元(這裡說的增加是在尾巴上),函式有 +=、append()、push_back()。舉例如下:
s+=str;//加個字串
s+=”my name is jiayp”;//加個C字串
s+=’a’;//加個字元
s.append(str);
s.append(str,1,3);//不解釋了同前面的函式引數assign的解釋
s.append(str,2,string::npos)//不解釋了
s.append(“my name is jiayp”);
s.append(“nico”,5);
s.append(5,’x’);
s.push_back(‘a’);//這個函式只能增加單個字元

4) insert() //插入字元**
在string中間的某個位置插入字串,可以用insert()函式,這個函式需要指定一個安插位置的索引,被插入的字串將放在這個索引的後面。
s.insert(0,”my name”);
s.insert(1,str);
這種形式的insert()函式不支援傳入單個字元,這時的單個字元必須寫成字串形式。注意:為了插入單個字元,insert()函式提供了兩個對插入單個字元操作的過載函式:insert(size_type index,size_type num,chart c)和insert(iterator pos,size_type num,chart c)。其中size_type是無符號整數,iterator是char*,所以,這麼呼叫insert函式是不行的:insert(0,1, ’j’);這時候第一個引數將轉換成哪一個呢?所以必須這麼寫:insert((string::size_type)0,1,’j’)!第二種形式指出了使用迭代器安插字元的形式,在後面會提及。順便提一下,string有很多操作是使用STL的迭代器的,他也儘量做得和STL靠近。
5) erase() //刪除字元**

s.erase(13);//從索引13開始往後全刪除
s.erase(7,5);//從索引7開始往後刪5個
6) clear() //刪除全部字元**
用法不作說明;
7) replace() //替換字元**
string s=”il8n”;
s.replace(1,2,”nternationalizatio”);//從索引1開始的2個替換成後面的
C_string s = internationalization
8) + //串聯字串**
9) ==,!=,<,<=,>,>=,compare() //比較字串
C ++字串支援常見的比較操作符(>,>=,<,<=,==,!=),甚至支援string與C-string的比較(如 str<”hello”)。在使用>,>=,<,<=這些操作符的時候是根據“當前字元特性”將字元按字典順序進行逐一得比較。字典排序靠前的字元小,比較的順序是從前向後比較,遇到不相等的字元就按這個位置上的兩個字元的比較結果確定兩個字串的大小。
另一個功能強大的比較函式是成員函式compare()。他支援多引數處理,支援用索引值和長度定位子串來進行比較。他返回一個整數來表示比較結果,返回值意義如下:0-相等 >0-大於 <0-小於。舉例如下:
string s(“abcd”);
s.compare(“abcd”); //返回0
s.compare(“dcba”); //返回一個小於0的值
s.compare(“ab”); //返回大於0的值
s.compare(s); //相等
s.compare(0,2,s,2,2); //用”ab”和”cd”進行比較小於零
s.compare(1,2,”bcx”,2); //用”bc”和”bc”比較。
10) size(),length() //返回字元數量
現有的字元數,函式是size()和length(),他們等效。
11) max_size() //返回字元的可能最大個數???
max_size() 這個大小是指當前C++字串最多能包含的字元數,很可能和機器本身的限制或者字串所在位置連續記憶體的大小有關係。我們一般情況下不用關心他,應該大小足夠我們用的。但是不夠用的話,會丟擲length_error異常
12) empty() //判斷字串是否為空
Empty()用來檢查字串是否為空。
13) capacity() //返回重新分配之前的字元容量
capacity()重新分配記憶體之前 string所能包含的最大字元數。
14) reserve() //保留一定量記憶體以容納一定數量的字元
這個函式為string重新分配記憶體。重新分配的大小由其引數決定,預設引數為0,這時候會對string進行非強制性縮減。
15) [ ], at() //存取單一字元
可以使用下標操作符[]和函式at()對元素包含的字元進行訪問。但是應該注意的是操作符[]並不檢查索引是否有效(有效索引0~str.length()),如果索引失效,會引起未定義的行為。而at()會檢查,如果使用 at()的時候索引無效,會丟擲out_of_range異常。

   string str1 = "Iphone 5";
   cout<<str1[2]<<endl; // = h
   cout<<str1.at(4)<<endl; // = n

    string stuff;
    getline(cin,stuff); // 輸入一行字元賦值給stuff
    getline(cin,stuff,'!'); // 輸入一行字元以“!”結束
    cout<<stuff<<endl;

16) >>,getline() //從stream讀取某值
17) << //將謀值寫入stream
18) copy() //將某值賦值為一個C_string
c_str() //將內容以C_string返回
data() //將內容以字元陣列形式返回
C ++提供的由C++字串得到對應的C_string的方法是使用data()、c_str()和copy(),其中,data()以字元陣列的形式返回字串內容,但並不新增’\0’。c_str()返回一個以‘\0’結尾的字元陣列,而copy()則把字串的內容複製或寫入既有的c_string或字元陣列內。C++字串並不以’\0’結尾。我的建議是在程式中能使用C++字串就使用,除非萬不得已不選用c_string。
19) substr() //返回某個子字串
substr(),形式如下:
s.substr();//返回s的全部內容
s.substr(11);//從索引11往後的子串
s.substr(5,6);//從索引5開始6個字元
20)查詢函式
查詢函式很多,功能也很強大,包括了:
find()
rfind()
find_first_of()
find_last_of()
find_first_not_of()
find_last_not_of()
這些函式返回符合搜尋條件的字元區間內的第一個字元的索引,沒找到目標就返回npos。所有的函式的引數說明如下:
第一個引數是被搜尋的物件。第二個引數(可有可無)指出string內的搜尋起點索引,第三個引數(可有可無)指出搜尋的字元個數。比較簡單,不多說不理解的可以向我提出,我再仔細的解答。當然,更加強大的STL搜尋在後面會有提及。
最後再說說npos的含義,string::npos的型別是string::size_type,所以,一旦需要把一個索引與npos相比,這個索引值必須是string::size)type型別的,更多的情況下,我們可以直接把函式和npos進行比較(如:if(s.find(“jia”)== string::npos))。

# include <iostream>
# include <string>

using namespace std;
int main()
{
    string str = "when i was young, i listen to radio.";
    string::size_type position;

    position  = str.find("listen");

    if (position != str.npos) //npos是個很大的數,如果沒找到就會返回npos的值給position
    {
        cout<<"第一次出現的下標是:"<<position<<endl;
    }

    //從字串下標9開始,查詢字串you,返回you 在str中的下標
    position = str.find("you",9);
    cout<<"str.find("you",9")is:"<<position<<endl;

    //查詢子串出現的所有位置
    string substr = "i";
    position = 0;
    int i = 1;
    while((position = str.find_first_of(substr,position)) != string::npos)
    {
        cout<<"position "<<i++<<position<<endl;
        position++;
    }

    //反向查詢子串在str中最後出現的位置
    string flag = "to";
    position = str.rfind(flag);
    cout<<"str.rfind(flag):"<<position<<endl;
    getchar();
    return 0;
}

21)begin() end() //提供類似STL的迭代器支援

# include <iostream>
# include <string>
# include <algorithm>
using namespace std;
int main()
{
    string str;

    str.push_back('Q');
    str.push_back('A');

    sort(str.begin(),str.end());
    string::iterator itstr = str.begin();

    for ( ; itstr != str.end(); itstr++)
    {
        cout<<*itstr;
    }   

    //str.pop_back();

    getchar();
    return 0;   //輸出AQ
}

22) rbegin() rend() //逆向迭代器
23) get_allocator() //返回配置器