九、【C++ STL】string的簡單使用

1、String類

  string類本不是STL的容器,可是它與STL容器有着不少類似的操做,所以,把string放在這裏一塊兒進行介紹。之因此拋棄char*的字符串而選用C++標準程序庫中的string類,是由於他和前者比較起來,沒必要擔憂內存是否足夠、字符串長度等等,並且做爲一個類出現,他集成的操做函數足以完成咱們大多數狀況下的須要。咱們盡能夠把它當作是C++的基本數據類型。
  首先,爲了在咱們的程序中使用string類型,咱們必須包含頭文件。以下:  ios

1 #include  <string>  // 注意這裏不是string.h,string.h是C字符串頭文件

一、聲明一個C++字符串

  聲明一個字符串變量很簡單:數組

1  string str;

  這樣咱們就聲明瞭一個字符串變量,但既然是一個類,就有構造函數和析構函數。上面的聲明沒有傳入參數,因此就直接使用了string的默認的構造函數,這個函數所做的就是把str初始化爲一個空字符串。string類的構造函數和析構函數以下:  app

1) string s;  // 生成一個空字符串s 
2) string s(str) ; // 拷貝構造函數生成str的複製品 
3) string s(str, stridx);  // 將字符串str內"始於位置stridx"的部分看成字符串的初值 
4) string s(str, stridx, strlen) ; // 將字符串str內"始於stridx且長度頂多strlen"的部分做爲字符串的初值 
5) string s(cstr) ;  // 將C字符串(以NULL結束)做爲s的初值 
6) string s(chars, chars_len) ;  // 將C字符串前chars_len個字符做爲字符串s的初值。 
7) string s(num, ‘c’) ;  // 生成一個字符串,包含num個c字符 
8) string s(「value」); string s=「value」;  // 將s初始化爲一個字符串字面值副本 
9) string s(begin, end);  // 以區間begin/end(不包含end)內的字符做爲字符串s的初值 
10) s.~string();  //銷燬全部字符,釋放內存 

二、string與C字符數組的比較

  string串要取得其中某一個字符,和傳統的C字符串同樣,能夠用s[i]的方式取得。比較不同的是若是s有三個字符,傳統C的字符串的s[3]是’\0’字符,可是C++的string則是隻到s[2]這個字符而已。函數

(1)C風格字符串spa

  •     用」「括起來的字符串常量,C++中的字符串常量由編譯器在末尾添加一個空字符;
  •     末尾添加了‘\0’的字符數組,C風格字符串的末尾必須有一個’\0’。

(2)C字符數組及其與string串的區別指針

  •     char ch[ ]={‘C’, ‘+’, ‘+’}; //末尾無NULL
  •     char ch[ ]={‘C’, ‘+’, ‘+’, ‘\0’}; //末尾顯式添加NULL
  •     char ch[ ]=」C++」; //末尾自動添加NULL字符 若[ ]內數字大於實際字符數,將實際字符存入數組,其他位置所有爲’\0’。

三、string對象的操做

1     string s;
2     s.empty(); // s爲空串 返回true 
3     s.size(); // 返回s中字符個數 類型應爲:string::size_type 
4     s[n]; // 從0開始至關於下標訪問
5     s1+s2; // 把s1和s2鏈接成新串 返回新串
6     s1=s2; // 把s1替換爲s2的副本
7     v1==v2; // 比較,相等返回true
8     `!=, <, <=, >, >=` 慣有操做 任何一個大寫字母都小於任意的小寫字母

當進行string對象和字符串字面值混合鏈接操做時,+操做符的左右操做數必須至少有一個是string類型的:code

1   string s1(「hello」);
2   string s3=s1+」world」;  //合法操做
3   string s4=」hello」+」world」;  //非法操做:兩個字符串字面值相加

四、字符串操做函數

(1)string類函數對象

1) =, s.assign() // 賦以新值
2) swap() // 交換兩個字符串的內容
3) +=, s.append(), s.push_back() // 在尾部添加字符
4) s.insert() // 插入字符
5) s.erase() // 刪除字符
6) s.clear() // 刪除所有字符
7) s.replace() // 替換字符
8) + // 串聯字符串
9) ==,!=,<,<=,>,>=,compare() // 比較字符串
10) size(),length() // 返回字符數量
11) max_size() // 返回字符的可能最大個數
12) s.empty() // 判斷字符串是否爲空
13) s.capacity() // 返回從新分配以前的字符容量
14) reserve() // 保留必定量內存以容納必定數量的字符
15) [ ], at() // 存取單一字符
16) >>,getline() // 從stream讀取某值
17) << // 將謀值寫入stream
18) copy() // 將某值賦值爲一個C_string
19) c_str() // 返回一個指向正規C字符串(C_string)的指針 內容與本string串相同 有’\0’
20) data() // 將內容以字符數組形式返回 無’\0’
21) s.substr() // 返回某個子字符串
22) begin() end() // 提供相似STL的迭代器支持
23) rbegin() rend() // 逆向迭代器
24) get_allocator() // 返回配置器

(2)函數說明

s.assign()

1 s.assign(str); // 不說 
2 s.assign(str,1,3); // 若是str是"iamangel" 就是把"ama"賦給字符串 
3 s.assign(str,2,string::npos); // 把字符串str從索引值2開始到結尾賦給s 
4 s.assign("gaint"); // 不說 
5 s.assign("nico",5); // 把’n’ ‘I’ ‘c’ ‘o’ ‘\0’賦給字符串 
6 s.assign(5,'x'); // 把五個x賦給字符串

大小和容量函數

一個C++字符串存在三種大小:
  1) 現有的字符數,函數是s.size()和s.length(),他們等效。s.empty()用來檢查字符串是否爲空。
  2) max_size(); 這個大小是指當前C++字符串最多能包含的字符數,極可能和機器自己的限制或者字符串所在位置連續內存的大小有關係。
  3) capacity()從新分配內存以前string所能包含的最大字符數。
  這裏另外一個須要指出的是resize()函數,這個函數爲string從新分配內存。從新分配的大小由其參數決定,默認參數爲0,這時候會對string進行非強制性縮減。 blog

元素存取

  咱們可使用下標操做符[]和函數at()對元素包含的字符進行訪問。可是應該注意的是操做符[]並不檢查索引是否有效(有效索引0~str.length()),若是索引失效,會引發未定義的行爲。而at()會檢查,若是使用at()的時候索引無效,會拋出out_of_range異常。
  有一個例外不得不說,const string a;的操做符[]對索引值是a.length()仍然有效,其返回值是’\0’。其餘的各類狀況,a.length()索引都是無效的。       排序

比較函數

  C ++字符串支持常見的比較操做符(>,>=,<,<=,==,!=),甚至支持string與C-string的比較(如 str<」hello」)。在使用>,>=,<,<=這些操做符的時候是根據」當前字符特性」將字符按字典順序進行逐一的比較。字典排序靠前的字符小,比較的順序是從前向後比較,遇到不相等的字符就按這個位置上的兩個字符的比較結果肯定兩個字符串的大小。
  另外一個功能強大的比較函數是成員函數compare()。他支持多參數處理,支持用索引值和長度定位子串來進行比較。他返回一個整數來表示比較結果,返回值意義以下:0-相等 、>0-大於、<0-小於。

插入字符

  也許你須要在string中間的某個位置插入字符串,這時候你能夠用insert()函數,這個函數須要你指定一個安插位置的索引,被插入的字符串將放在這個索引的後面。

1 s.insert(0,」my name」);
2 s.insert(1,str);

  這種形式的insert()函數不支持傳入單個字符,這時的單個字符必須寫成字符串形式。爲了插入單個字符,insert()函數提供了兩個對插入單個字符操做的重載函數:

1 insert(size_type index, size_type num, chart c)
2 insert(iterator pos, size_type num, chart c)

其中size_type是無符號整數,iterator是char*,因此,你這麼調用insert函數是不行的:
insert(0, 1, ‘j’);這時候第一個參數將轉換成哪個呢?
因此你必須這麼寫:insert((string::size_type)0, 1, ‘j’)!第二種形式指出了使用迭代器安插字符的形式。

提取子串s.substr()

1 s.substr(); // 返回s的所有內容 
2 s.substr(11); // 從索引11日後的子串 
3 s.substr(5,6); // 從索引5開始6個字符

五、字符串流stringstream操做

  Iostream標準庫支持內存中的輸入輸出,只要將流與存儲在程序內存中的string對象捆綁起來便可。此時,可以使用iostream輸入和輸出操做符讀寫這個stream對象。使用stringstream,咱們必須包含頭文件#include。

(1)string s

1) >>操做符 // 用於從istream對象中讀入輸入 
2) is >> s; // 從輸入流is中讀取一個以空白字符分割的字符串,寫入s 
3) <<操做符 // 用於把輸出寫到ostream對象中 
4) os << s; // 將s寫到輸出流os中 
5) getline(is, s); // 從輸入流is中讀取一行字符,寫入s,直到遇到分行符或到了文件尾 
6) istream // 輸入流 提供輸入操做 
7) ostream // 輸出流 提供輸出操做

(2)stringstream特定的操做

1) stringstream strm; // 建立自由的stringstream對象 
2) stringstream strm(s); // 建立存儲s的副本的stringstream對象,s是stringstream類型 
3) strm.str(); // 返回strm中存儲的string類型對象 
4) strm.str(s); // 將string類型的s複製給strm 返回void

(3)string到int的轉換

  stringstream一般是用來作數據轉換的,若是你打算在屢次轉換中使用同一個stringstream對象,記住在每次轉換前要使用clear()方法。在屢次轉換中重複使用同一個stringstream(而不是每次都建立一個新的對象)對象最大的好處在於效率。stringstream對象的構造和析構函數一般是很是耗費CPU時間的。
string到int的轉換(與其餘類型間的轉換同樣大同小異):

1     string result=」10000」;  
2     int n=0;
3     stream<<result;
4     stream>>n;  // n等於10000

六、C字符串、string串、stringstream之間的關係

  首先必須瞭解,string能夠被當作是以字符爲元素的一種容器。字符構成序列(字符串)。有時候在字符序列中進行遍歷,標準的string類提供了STL容器接口。具備一些成員函數好比begin()、end(),迭代器能夠根據他們進行定位。注意,與char*不一樣的是,string不必定以NULL(‘\0’)結束。string長度能夠根據length()獲得,string能夠根據下標訪問。因此,不能將string直接賦值給char*。

(1)string轉換成const char *

  若是要將字面值string直接轉換成const char *類型。string有2個函數能夠運用:一個是.c_str(),一個是data成員函數。
  c_str()函數返回一個指向正規C字符串的指針,內容與本string串相同。這是爲了與C語言兼容,在C語言中沒有string類型,故必須經過string類對象的成員函數c_str()把string 對象轉換成C中的字符串樣式。注意:必定要使用strcpy()函數等來操做方法c_str()返回的指針

1     string str = "Hello World";
2     const char *ch1 = str.c_str();
3     const char *ch2 = str.data();

此時,ch1與ch2的內容將都是」Hello World」。可是隻能轉換成const char*,若是去掉const編譯不能經過。

(2)string轉換成char *

  C++提供的由C++字符串獲得對應的C_string的方法是使用data()、c_str()和copy(),其中
    1) data()以字符數組的形式返回字符串內容,但並不添加’\0’。
    2) c_str()返回一個以’\0’結尾的字符數組,返回值是const char*。
    3) copy()則把字符串的內容複製或寫入既有的c_string或字符數組內。
  C++字符串並不以’\0’結尾。個人建議是在程序中能使用C++字符串就使用,除非萬不得已不選用c_string。
若是要轉換成char*,能夠用string的一個成員函數strcpy實現。

1     string str = "Hello World"; 
2     int len = str.length(); 
3     char *data = new char[len+1]; //這裏+1仍是不+1須要注意 
4     strcpy(data, str.c_str()); // const char *data = new char[len+1];  strcpy(data, str);

此時,data中的內容爲」Hello World」使用c_str()要麼str賦給一個const指針,要麼用strcpy()複製。

(3)char *轉換成string

string類型可以自動將C風格的字符串轉換成string對象:

1 string str; 
2 const char *pc = "Hello World"; 
3 str = pc;
4 printf(「%s\n」, str);  //此處出現錯誤的輸出
5 cout<<str<<endl;

  不過這個是會出現問題的。有一種狀況我要說明一下。當咱們定義了一個string類型以後,用printf(「%s」,str);輸出是會出問題的。這是由於「%s」要求後面的對象的首地址。可是string不是這樣的一個類型。因此確定出錯。用cout輸出是沒有問題的,若必定要printf輸出。那麼能夠這樣:

1 printf("%s",str.c_str());

(4)char[ ] 轉換成string

  這個與char*的狀況相同,也能夠直接賦值,可是也會出現上面的問題,須要一樣的處理。
- 字符數組轉化成string類型:

1   char ch [] = "ABCDEFG";
2   string str(ch); //也可string str = ch;

或者

1   char ch [] = "ABCDEFG";
2   string str;
3   str = ch; //在原有基礎上添加能夠用str += ch;

(5)string轉換成char[ ]

string對象轉換成C風格的字符串:

1     const char *str = s.c_str();

  這是由於爲了防止字符數組被程序直接處理c_str()返回了一個指向常量數組的指針。因爲咱們知道string的長度能夠根據length()函數獲得,又能夠根據下標直接訪問,因此用一個循環就能夠賦值了,這樣的轉換不能夠直接賦值。

1 string str = "Hello World"; 
2 int len=str.length(); 
3 char ch[255]={}; 
4 for( int i=0;i<str.length();i++) 
5     ch[i] = str[i]; 
6 ch[len+1] = '\0'; 
7 printf("%s\n", ch); 
8 cout<<ch<<endl;

(6)stringstream與string間的綁定

1 stringstream strm;
2 string s;
3 strm<<s;  // 將s寫入到strm
4 strm>>s;  // 從strm讀取串寫入s
1 strm.str(); // 返回strm中存儲的string類型對象
2 strm.str(s); // 將string類型的s複製給strm 返回void
1 char* cstr;  // 將C字符數組轉換成流
2 string str(cstr);
3 stringstream ss(str);
相關文章
相關標籤/搜索