1. 程式人生 > >c++ string使用詳解

c++ string使用詳解

之所以拋棄char*的字串而選用C++標準程式庫中的string類,是因為他和前者比較起來,不必擔心記憶體是否足夠、字串長度等等,而且作為一個類出現,他整合的操作函式足以完成我們大多數情況下(甚至是100%)的需要。我們可以用 = 進行賦值操作,== 進行比較,+ 做串聯(是不是很簡單?)。我們儘可以把它看成是C++的基本資料型別。
string ( );
string ( const string& str );
string ( const string& str, size_t pos, size_t n = npos );
string ( const char * s, size_t n );
string ( const char * s );
string ( size_t n, char c );
template<class InputIterator> string (InputIterator begin, InputIterator end);

Construct string object

Constructs a standard string object and initializes its content.

The different constructor versions allow for the content to be initialized in different ways:
string ( );
Content is initialized to an empty string.
string ( const string& str );
Content is initialized to a copy of the string object str
.
string ( const string& str, size_t pos, size_t n = npos );
Content is initialized to a copy of a substring of str. The substring is the portion ofstr that begins at the character positionpos and takes up to n characters (it takes less than n if the end ofstr is reached before).
string ( const char * s, size_t n );
Content is initialized to a copy of the string formed by the first n characters in the array of characters pointed bys.
string ( const char * s );
Content is initialized to a copy of the string formed by the null-terminated character sequence (C string) pointed bys. The length of the character sequence is determined by the first occurrence of a null character (as determined bytraits.length(s)). This version can be used to initialize astring object using astring literal constant.
string ( size_t n, char c );
Content is initialized as a string formed by a repetition of character c,n times.
template<class InputIterator> string (InputIterator begin, InputIterator end);
If InputIterator is an integral type, behaves as the sixth constructor version (the one right above this) by typecastingbegin andend to call it:
string(static_cast<size_t>(begin),static_cast<char>(end));
In any other case, the parameters are taken as iterators, and the content is initialized with the values of the elements that go from the element referred by iteratorbegin to the element right before the one referred by iteratorend.

Member functions


Iterators:


Capacity:


Element access:


Modifiers:


String operations:

翻譯:

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() //銷燬所有字元,釋放記憶體
都很簡單,我就不解釋了。
2.字串操作函式
   這裡是C++字串的重點,我先把各種操作函式羅列出來,不喜歡把所有函式都看完的人可以在這裡找自己喜歡的函式,再到後面看他的詳細解釋。
a) =,assign()   //賦以新值
b) swap()   //交換兩個字串的內容
c) +=,append(),push_back() //在尾部新增字元
d) insert() //插入字元
e) erase() //刪除字元
f) clear() //刪除全部字元
g) replace() //替換字元
h) + //串聯字串
i) ==,!=,<,<=,>,>=,compare()  //比較字串
j) size(),length()  //返回字元數量
k) max_size() //返回字元的可能最大個數
l) empty()  //判斷字串是否為空
m) capacity() //返回重新分配之前的字元容量
n) reserve() //保留一定量記憶體以容納一定數量的字元
o) [ ], at() //存取單一字元
p) >>,getline() //從stream讀取某值
q) <<  //將謀值寫入stream
r) copy() //將某值賦值為一個C_string
s) c_str() //將內容以C_string返回
t) data() //將內容以字元陣列形式返回
u) substr() //返回某個子字串
v)查詢函式
w)begin() end() //提供類似STL的迭代器支援
x) rbegin() rend() //逆向迭代器
y) get_allocator() //返回配置器

下面為轉載內容

下面詳細介紹:
2.1 C++字串和C字串的轉換
   C++提供的由C++字串得到對應的C_string的方法是使用data()、c_str()和copy(),其中,data()以字元陣列的形式返回字串內容,但並不新增’/0’。c_str()返回一個以‘/0’結尾的字元陣列,而copy()則把字串的內容複製或寫入既有的c_string或字元陣列內。C++字串並不以’/0’結尾。我的建議是在程式中能使用C++字串就使用,除非萬不得已不選用c_string。由於只是簡單介紹,詳細介紹掠過,誰想進一步瞭解使用中的注意事項可以給我留言(到我的收件箱)。我詳細解釋。
2.2 大小和容量函式
   一個C++字串存在三種大小:a)現有的字元數,函式是size()和length(),他們等效。Empty()用來檢查字串是否為空。b)max_size() 這個大小是指當前C++字串最多能包含的字元數,很可能和機器本身的限制或者字串所在位置連續記憶體的大小有關係。我們一般情況下不用關心他,應該大小足夠我們用的。但是不夠用的話,會丟擲length_error異常c)capacity()重新分配記憶體之前 string所能包含的最大字元數。這裡另一個需要指出的是reserve()函式,這個函式為string重新分配記憶體。重新分配的大小由其引數決定,預設引數為0,這時候會對string進行非強制性縮減。

還有必要再重複一下C++字串和C字串轉換的問題,許多人會遇到這樣的問題,自己做的程式要呼叫別人的函式、類什麼的(比如資料庫連線函式Connect(char*,char*)),但別人的函式引數用的是char*形式的,而我們知道,c_str()、data()返回的字元陣列由該字串擁有,所以是一種const char*,要想作為上面提及的函式的引數,還必須拷貝到一個char*,而我們的原則是能不使用C字串就不使用。那麼,這時候我們的處理方式是:如果此函式對引數(也就是char*)的內容不修改的話,我們可以這樣Connect((char*)UserID.c_str(), (char*)PassWD.c_str()),但是這時候是存在危險的,因為這樣轉換後的字串其實是可以修改的(有興趣地可以自己試一試),所以我強調除非函式呼叫的時候不對引數進行修改,否則必須拷貝到一個char*上去。當然,更穩妥的辦法是無論什麼情況都拷貝到一個char*上去。同時我們也祈禱現在仍然使用C字串進行程式設計的高手們(說他們是高手一點兒也不為過,也許在我們還穿開襠褲的時候他們就開始程式設計了,哈哈…)寫的函式都比較規範,那樣我們就不必進行強制轉換了。

2.3元素存取
   我們可以使用下標操作符[]和函式at()對元素包含的字元進行訪問。但是應該注意的是操作符[]並不檢查索引是否有效(有效索引0~str.length()),如果索引失效,會引起未定義的行為。而at()會檢查,如果使用at()的時候索引無效,會丟擲out_of_range異常。
   有一個例外不得不說,const string a;的操作符[]對索引值是a.length()仍然有效,其返回值是’/0’。其他的各種情況,a.length()索引都是無效的。舉例如下:
const string Cstr(“const string”);
string Str(“string”);

Str[3];    //ok
Str.at(3);  //ok
Str[100]; //未定義的行為
Str.at(100);  //throw out_of_range
Str[Str.length()]  //未定義行為
Cstr[Cstr.length()] //返回 ‘/0’
Str.at(Str.length());//throw out_of_range
Cstr.at(Cstr.length()) ////throw out_of_range

我不贊成類似於下面的引用或指標賦值:
char& r=s[2];
char* p= &s[3];
因為一旦發生重新分配,r,p立即失效。避免的方法就是不使用。

2.4比較函式
   C++字串支援常見的比較操作符(>,>=,<,<=,==,!=),甚至支援string與C-string的比較(如 str<”hello”)。在使用>,>=,<,<=這些操作符的時候是根據“當前字元特性”將字元按字典順序進行逐一得比較。字典排序靠前的字元小,比較的順序是從前向後比較,遇到不相等的字元就按這個位置上的兩個字元的比較結果確定兩個字串的大小。同時,string(“aaaa”)    另一個功能強大的比較函式是成員函式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”比較。
怎麼樣?功能夠全的吧!什麼?還不能滿足你的胃口?好吧,那等著,後面有更個性化的比較演算法。先給個提示,使用的是STL的比較演算法。什麼?對STL一竅不通?靠,你重修吧!

2.5 更改內容
這在字串的操作中佔了很大一部分。
首先講賦值,第一個賦值方法當然是使用操作符=,新值可以是string(如:s=ns) 、c_string(如:s=”gaint”)甚至單一字元(如:s=’j’)。還可以使用成員函式assign(),這個成員函式可以使你更靈活的對字串賦值。還是舉例說明吧:
s.assign(str); //不說
s.assign(str,1,3);//如果str是”iamangel” 就是把”ama”賦給字串
s.assign(str,2,string::npos);//把字串str從索引值2開始到結尾賦給s
s.assign(“gaint”); //不說
s.assign(“nico”,5);//把’n’ ‘I’ ‘c’ ‘o’ ‘/0’賦給字串
s.assign(5,’x’);//把五個x賦給字串
把字串清空的方法有三個:s=””;s.clear();s.erase();(我越來越覺得舉例比說話讓別人容易懂!)。
string提供了很多函式用於插入(insert)、刪除(erase)、替換(replace)、增加字元。
先說增加字元(這裡說的增加是在尾巴上),函式有 +=、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’);

    字串操作是一個不小的主題,在標準C++中,string字串類成為一個標準,之所以拋棄char*的字串而選用C++標準程式庫中的string類,是因為他和前者比較起來,不必擔心記憶體是否足夠、字串長度等等,而且作為一個類出現,他整合的操作函式足以完成我們大多數情況下的需要.
    下面我們首先從一些示例開始學習下string類的使用.
1)
  1. #include <string>
  2. #include <iostream>
  3. usingnamespace std;  
  4. void main()  
  5. {  
  6.     string s("hehe");  
  7.     cout<<s<<endl;  
  8.     cin.get();  
  9. }  
  10. 2)  
  11. #include <string>
  12. #include <iostream>
  13. usingnamespace std;  
  14. void main()  
  15. {  
  16.     char chs[] = "hehe";  
  17.     string s(chs);  
  18.     cout<<s<<endl;  
  19.     cin.get();  
  20. }  
  21. 3)  
  22. #include <string>
  23. #include <iostream>
  24. usingnamespace std;  
  25. void main()  
  26. {  
  27.     char chs[] = "hehe";  
  28.     string s(chs,1,3);    //指定從chs的索引1開始,最後複製3個位元組
  29.     cout<<s<<endl;  
  30.     cin.get();  
  31. }  
  32. 4)  
  33. #include <string>
  34. #include <iostream>
  35. usingnamespace std;  
  36. void main()  
  37. {  
  38.     string s1("hehe");  
  39.     string s2(s1);     
  40.     cout<<s2<<endl;  
  41.     cin.get();  
  42. }  
  43. 5)  
  44. #include <string>
  45. #include <iostream>
  46. usingnamespace std;  
  47. void main()  
  48. {  
  49.     string s1("hehe",2,3);  
  50.     string s2(s1);     
  51.     cout<<s2<<endl;  
  52.     cin.get();  
  53. }  
  54. 6)  
  55. #include <string>
  56. #include <iostream>
  57. usingnamespace std;  
  58. void main()  
  59. {  
  60.     char chs[] = "hehe";  
  61.     string s(chs,3);    //將chs前3個字元作為初值構造
  62.     cout<<s<<endl;  
  63.     cin.get();  
  64. }  
  65. 7)  
  66. #include <string>
  67. #include <iostream>
  68. usingnamespace std;  
  69. void main()  
  70. {  
  71.     string s(10,'k');    //分配10個字元,初值都是'k'
  72.     cout<<s<<endl;  
  73.     cin.get();  
  74. }  
  75. //以上是string類例項的構造手段,都很簡單.
  76. 9)  
  77. //賦新值
  78. #include <string>
  79. #include <iostream>
  80. usingnamespace std;  
  81. void main()  
  82. {  
  83.     string s(10,'k');    //分配10個字元,初值都是'k'
  84.     cout<<s<<endl;  
  85.     s = "hehehehe";  
  86.     cout<<s<<endl;  
  87.     s.assign("kdje");  
  88.     cout<<s<<endl;  
  89.     s.assign("fkdhfkdfd",5);    //重新分配指定字串的前5的元素內容
  90.     cout<<s<<endl;         
  91.     cin.get();  
  92. }  
  93. 10)  
  94. //swap方法交換
  95. #include <string>
  96. #include <iostream>
  97. usingnamespace std;  
  98. void main()  
  99. {  
  100.     string s1 = "hehe";  
  101.     string s2 = "gagaga";  
  102.     cout<<"s1 : "<<s1<<endl;  
  103.     cout<<"s2 : "<<s2<<endl;  
  104.     s1.swap(s2);  
  105.     cout<<"s1 : "<<s1<<endl;  
  106.     cout<<"s2 : "<<s2<<endl;  
  107.     cin.get();  
  108. }  
  109. 11)  
  110. //+=,append(),push_back()在尾部新增字元
  111. #include <string>
  112. #include <iostream>
  113. usingnamespace std;  
  114. void main()  
  115. {  
  116.     string s = "hehe";  
  117.     s += "gaga";  
  118.     cout<<s<<endl;  
  119.     s.append("嘿嘿");    //append()方法可以新增字串
  120.     cout<<s<<endl;  
  121.     s.push_back('k');    //push_back()方法只能新增一個字元...
  122.     cout<<s<<endl;  
  123.     cin.get();  
  124. }  
  125. 12)  
  126. //insert() 插入字元.其實,insert運用好,與其他的插入操作是一樣的.
  127. #include <string>
  128. #include <iostream>
  129. usingnamespace std;  
  130. void main()  
  131. {  
  132.     string s = "hehe";  
  133.     s.insert(0,"頭部");            //在頭部插入
  134.     s.insert(s.size(),"尾部");    //在尾部插入
  135.     s.insert(s.size()/2,"中間");//在中間插入
  136.     cout<<s<<endl;  
  137.     cin.get();  
  138. }  
  139. 13)  
  140. #include <string>
  141. #include <iostream>
  142. usingnamespace std;  
  143. void main()  
  144. {  
  145.     string s = "abcdefg";  
  146.     s.erase(0,1);    //從索引0到索引1,即刪除掉了'a'
  147.     cout<<s<<endl;  
  148.     //其實,還可以使用replace方法來執行刪除操作
  149.     s.replace(2,3,"");//即將指定範圍內的字元替換成"",即變相刪除了
  150.     cout<<s<<endl;  
  151.     cin.get();  
  152. }  
  153. 14)  
  154. //clear() 刪除全部字元
  155. #include <string>
  156. #include <iostream>
  157. usingnamespace std;  
  158. void main()  
  159. {  
  160.     string s = "abcdefg";  
  161.     cout<<s.length()<<endl;  
  162.     s.clear();  
  163.     cout<<s.length()<<endl;  
  164.     //使用earse方法變相全刪除
  165.     s = "dkjfd";  
  166.     cout<<s.length()<<endl;  
  167.     s.erase(0,s.length());  
  168.     cout<<s.length()<<endl;  
  169.     cin.get();  
  170. }  
  171. 15)  
  172. //replace() 替換字元
  173. #include <string>
  174. #include <iostream>
  175. usingnamespace std;  
  176. void main()  
  177. {  
  178.     string s = "abcdefg";  
  179.     s.replace(2,3,"!!!!!");//從索引2開始3個位元組的字元全替換成"!!!!!"
  180.     cout<<s<<endl;  
  181.     cin.get();  
  182. }  
  183. 16)  
  184. //==,!=,<,<=,>,>=,compare()  比較字串
  185. #include <string>
  186. #include <iostream>
  187. usingnamespace std;  
  188. void main()  
  189. {  
  190.     string s1 = "abcdefg";  
  191.     string s2 = "abcdefg";     
  192.     if (s1==s2)cout<<"s1 == s2"<<endl;  
  193.     else cout<<"s1 != s2"<<endl;  
  194.     if (s1!=s2)cout<<"s1 != s2"<<endl;  
  195.     else cout<<"s1 == s2"<<endl;  
  196.     if (s1>s2)cout<<"s1 > s2"<<endl;  
  197.     else cout<<"s1 <= s2"<<endl;  
  198.     if (s1<=s2)cout<<"s1 <= s2"<<endl;  
  199.     else cout<<"s1 > s2"<<endl;  
  200.     cin.get();  
  201. }  
  202. 17)  
  203. //size(),length()  返回字元數量
  204. #include <string>
  205. #include <iostream>
  206. usingnamespace std;  
  207. void main()  
  208. {  
  209.     string s = "abcdefg";  
  210.     cout<<s.size()<<endl;  
  211.     cout<<s.length()<<endl;  
  212.     cin.get();  
  213. }  
  214. 18)  
  215. //max_size() 返回字元的可能最大個數
  216. #include <string>
  217. #include <iostream>
  218. usingnamespace std;  
  219. void main()  
  220. {  
  221.     string s = "abcdefg";  
  222.     cout<<s.max_size()<<endl;  
  223.     cin.get();  
  224. }  
  225. 19)  
  226. //empty()  判斷字串是否為空
  227. #include <string>
  228. #include <iostream>
  229. usingnamespace std;  
  230. void main()  
  231. {  
  232.     string s ;  
  233.     if (s.empty())  
  234.         cout<<"s 為空."<<endl;  
  235.     else
  236.         cout<<"s 不為空."<<endl;  
  237.     s = s + "abcdefg";  
  238.     if (s.empty())  
  239.         cout<<"s 為空."<<endl;  
  240.     else
  241.         cout<<"s 不為空."<<endl;  
  242.     cin.get();  
  243. }  
  244. 20)  
  245. // [ ], at() 存取單一字元
  246. #include <string>
  247. #include <iostream>
  248. usingnamespace std;  
  249. void main()  
  250. {  
  251.     string s = "abcdefg1111";  
  252.     cout<<"use []:"<<endl;  
  253.     for(int i=0; i<s.length(); i++)  
  254.     {  
  255.         cout<<s[i]<<endl;  
  256.     }  
  257.     cout<<endl;  
  258.     cout<<"use at():"<<endl;  
  259.     for(int i=0; i<s.length(); i++)  
  260.     {  
  261.         cout<<s.at(i)<<endl;  
  262.     }  
  263.     cout<<endl;  
  264.     cin.get();  
  265. }  
  266. 21)  
  267. #include <string>
  268. #include <iostream>
  269. usingnamespace std;  
  270. void main()  
  271. {  
  272.     string s = "abcdefg1111";  
  273.     constchar * chs1 = s.c_str();  
  274.     constchar * chs2 = s.data();  
  275.     cout<<"use at():"<<endl;  
  276.     int i;  
  277.     for(i=0; i<s.length(); i++)  
  278.     {  
  279.         cout<<"c_str() : "<<chs1[i]<<endl;  
  280.         cout<<"data() : "<<chs2[i]<<endl;  
  281.     }  
  282.     cout<<"c_str() : "<<chs1<<endl;  
  283.     cout<<"data() : "<<chs2<<endl;  
  284.     cout<<endl;  
  285.     cin.get();  
  286. }  
  287. 22)  
  288. // substr() 返回某個子字串
  289. #include <string>
  290. #include <iostream>
  291. usingnamespace std;  
  292. void main()  
  293. {  
  294.     string s = "abcdefg1111";  
  295.     string str = s.substr(5,3);//從索引5開始3個位元組
  296.     cout<<str<<endl;  
  297.     cin.get();  
  298. }  
  299. 23)  
  300. // find 查詢函式
  301. #include <string>
  302. #include <iostream>
  303. usingnamespace std;  
  304. void main()  
  305. {  
  306.     string s = "abcdefg1111";  
  307.     string pattern = "fg";  
  308.     string::size_type pos;  
  309.     pos = s.find(pattern,0);        //從索引0開始,查詢符合字串"f"的頭索引
  310.     cout<<pos<<endl;  
  311.     string str = s.substr(pos,pattern.size());  
  312.     cout<<str<<endl;  
  313.     cin.get();  
  314. }  
  315. 24)  
  316. // begin() end() 提供類似STL的迭代器支援
  317. #include <string>
  318. #include <iostream>
  319. usingnamespace std;  
  320. void main()  
  321. {  
  322.     string s = "abcdefg1111";  
  323.     for(string::iterator iter = s.begin(); iter!=s.end(); iter++)  
  324.     {  
  325.         cout<<*iter<<endl;  
  326.     }  
  327.     cout<<endl;  
  328.     cin.get();  
  329. }  
        一個C++字串存在三種大小:a)現有的字元數,函式是size()和length(),他們等效。 Empty()用來檢查字串是否為空。b)max_size() 這個大小是指當前C++字串最多能包含的字元數,很可能和機器本身的限制或者字串所在位置連續記憶體的大小有關係。我們一般情況下不用關心他,應該大小足夠我們用的。但是不夠用的話,會丟擲length_error異常c)capacity()重新分配記憶體之前 string所能包含的最大字元數。這裡另一個需要指出的是reserve()函式,這個函式為string重新分配記憶體。重新分配的大小由其引數決定,預設引數為0,這時候會對string進行非強制性縮減。