1. 程式人生 > >C++標準庫型別-string

C++標準庫型別-string

1:首先區分開C和C++中的string

解釋:C語言中的並沒有string型別(C語言連類都沒,當然沒有string),C中的有個string.h標頭檔案,這個標頭檔案只是包含對字串的處理,比如說strcat等函式。而C++中的string是一個標準庫型別,表示可變長的字元序列,而由於是標準庫型別,所以string定義在名稱空間std中。

 

2:定義和初始化string物件

如何初始化類的物件是由類本身決定的。一個類可以定義很多種初始化物件的方式。

初始化string物件的方式

(1)string s1;  //預設初始化,s1是一個空串

(2)string s2(s1);   //s2是s1的副本

(3)string s3("value");     //s3是字面值“value”的副本,除了字面值最後那個空字元除外

(4)string s3 = "value";   //等價於上面

(5)string s4(n,'C');     //把s4初始化由連續n個字元c組成的串

這裡初始化方式,是由string類中的預設建構函式、顯示建構函式、賦值/拷貝建構函式決定的。

 

另外:string中的字串,最後有沒有'\0',C++11中的string以‘\0’結尾的,這是為了相容C。

但是'\0'並不作為string的結束符,則string中的'\0'是允許在中間的,只不過顯示是空而已。因為string類中已經記錄了長度,並不需要'\0'來結尾。

驗證:參考程式碼

  1 #include<stdio.h>
  2 #include<string>
  3 
  4 int main()
  5 {
  6     std::string s1 = "abc";
  7     if(s1[4] == '\0')
  8     {
  9         printf("yes!\n");
 10     }
 11     printf("s1_length=%d\n",s1.size());
 12 
 13     return 0;
 14 }


輸出結果:
yes!
s1_length=3

 

3:string物件上的操作

列舉string的一些操作:

os << s;   //將s寫到輸出流os當中,返回os

is >> s;    //從is中讀取字串賦給s,字串以空白分隔,返回is

getline(is, s);   //從is中讀一行賦給s,返回is

s.empty();   //s為空返回true,否則返回false

s[n];   //返回s中第n個字元的引用,位置n從0計起

s.size();    //返回s中字元的個數

s1 + s2;   //返回s1+s2連線後的結果

s1 = s2;   //用s2的副本代替s1中原來的字元

s1 == s2;    //如果s1和s2中所含的字元完全一樣,則它們相等;string物件的相等性判斷等字母的大小寫敏感

s1 != s2;

<,<=,>,>=;    //利用字元在字典中的順序進行比較,且對字母的大小敏感

 

讀寫string物件

使用標準庫中的iostream來讀寫int,double等內建型別值。也可以使用IO操作符讀寫string物件。

  1 #include<stdio.h>
  2 #include<string>
  3 #include<iostream>
  4 
  5 int main()
  6 {
  7     std::string s;   //空字串
  8     std::cin >> s;   //將string物件讀入s,遇到空白停止
  9     std::cout << s << std::endl;  //輸出s
 10     return 0;
 11 }

在執行讀取操作時,string物件會自動忽略開頭的空白(即空白符、換行符、製表符等)並從第一個真正的字元開始讀起,知道遇到下一處空白為止。

如上所述,如果輸入的是“   Hello World!   ”,則將輸出“Hello”,輸出結果沒有任何空格。

和內建型別的輸入輸出操作一樣,string物件的此類操作也是返回運算子左側的運算物件作為其結果。因此,多個輸入或者多個輸出可以連寫在一起。

sting s1,s2;

cin >> s1 >> s2;

cout << s1 << s2 <<endl;

假設給上面這段程式輸入與之前一樣的內容“   Hello World!   ”,輸出將是“HelloWorld!”。

 

讀取未知數量的string物件

 

  1 #include<stdio.h>
  2 #include<string>
  3 #include<iostream>
  4 
  5 int main()
  6 {
  7     std::string world ;
  8     while(std::cin >> world)
  9     {
 10         std::cout << world << std::endl;
 11     }
 12     return 0;
 13 }
     

這裡注意的是,while迴圈會一直執行直至遇到檔案結束符(或輸入錯誤,如要求輸入整數,實際輸入不是整數),這個while其實是檢測流的狀態,因為cin返回左側流的物件。

從鍵盤上輸入檔案結束符:在Windows系統中,輸入檔案結束符的方法是敲Ctrl + Z,然後按Enter或Return。在UNIX系統中,包括Mac  OS X系統中,檔案結束符輸入是用Ctrl + D

 至於為什麼要加上endl。endl是一個被稱為操縱符的特殊值,寫入endl的效果是結束當前行,並將於裝置關聯的緩衝區中的內容刷到裝置中。緩衝重新整理操作可以保證到目前為止程式所產生的所有輸出都真正寫入輸出流中,而不是僅停留在記憶體中等待寫入流。

 

使用getline讀取一整行

前面的用>>讀取字串時,是遇到空白符就結束的。可以用getline函式替代>>運算子,這樣最終得到的字串中保留輸入時的空白符。getline函式的引數時一個輸入流和一個string物件,函式從給定的輸入流中讀入內容,知道遇到換行符為止(注意這是換行符也被讀進來),然後把所讀的內容存入到那個string物件中(注意這裡不存換行符)。getline只要一遇到換行符就結束讀取操作並返回結果,哪怕輸入的一開始就是換行符也是如此。如果輸入真的一開始就是換行符,那麼所得的結果就是空的string。

和輸入>>運算子一樣,getline也會返回它的流引數。因此既然輸入運算子能作為判斷的條件,也能用getline的結果作為判斷的條件。

  1 #include<stdio.h>
  2 #include<string>
  3 #include<iostream>
  4 
  5 int main()
  6 {
  7     std::string world ;
  8 //  while(std::cin >> world)
  9 //  {
 10 //      std::cout << world << std::endl;
 11 //  }
 12     while (getline(std::cin,world))
 13     {
 14         std::cout << world << std::endl;
 15     }
 16     return 0;
 17 }
 18 

因為world中最後那個換行符最終是沒有儲存的,所以最後要加個endl。

 

string::size_type型別

如string中的操作,s.size()返回的是string::size_type型別的值。string類及其他大多數標準庫型別都定義了幾種配套的型別。這種配套型別體現了標準庫型別與機器無關的特性,型別szie_type即是其中的一種。在具體使用時,通過作用域操作符來表明名字size_type是在類string中定義的。

size_type是一個無符號的值,而且足夠存放下任何string物件的大小。可以用auto或者decltype來推斷變數的型別。

auto len = s.size() ;  //len的型別是string::size_type

由於size_type是一個無符號整型數,因此切記,如果在表示式中混用了帶符號數和無符號數將可能產生意想不到的結果。例如,假設n是一個負值的int,則表示式s.size() < n的判斷結果幾乎肯定是true。這是因為負值n會自動轉換成一個比較大的無符號值。所以表示式中有了size()函式就不用int了。

 

比較string物件

string物件比較對大小寫敏感。

相等性運算子(==和!=)分別檢驗兩個string物件相等或不相等,string物件相等意味著他們的長度相同而且所包含的字元也全部相同。

關係運算符(<,>=)按照字典順序:(1)如果兩個string物件的長度不同,而且較短string物件的每個字元都與較長string物件對應上的位置上的字元相同,就說較短的string物件小於較長的string物件。 (2)如果兩個string物件在某些對應的位置上不一致,則string物件比較的結果其實是string物件中第一對相異字元比較的結果。

示例:

string str = "Hellp";

string phrase = "Hello World";

string slang = "Hiya";

根據(1)可以判斷,物件str小於物件phrase,根據(2)可判斷,物件slang既大於str也大於phrase。

 

 

為string物件幅值

string s1 = "aaa",s2;

s1 = s2;  

這裡就不解釋了。。

 

兩個string物件相加

兩個string物件相加得到一個新的string物件,其內容是把左側的運算物件與右側的運算物件串接而成。

string s1 = "hello, ", s2 = "world\n";

string s3 = s1 + s2;  //s3的內容是“hello, world\n”

 

字面值與string物件相加

因為標準庫允許把字元字面值和字串字面值轉換成string物件,所以在需要string物件的地方就可以使用這兩種字面值來替代。如 string s1 = "hello", s2 = "world";

string s3 = s1 + ", "(這裡是字串逗號加空格) + s2 + '\n';

但是注意:當把string物件和字元字面值及字串字面值混在一條語句中時,必須確保每個加法運算子+的兩側物件至少有一個是string:

string s4 = s1 + ", ";   //正確

string s5 = "hello" + “, ”;      //錯誤

string s6 = s1 + ", " + “world";   //正確

string s7 = "hello" + ", "  + s2;    //錯誤

為什麼s6正確而s7錯誤,因為s6可以轉換成如下 s6 = (s1 + ", ") + “world”;  括號裡s1 + ", "的結果是一個string物件。

還要注意一點:字串字面值與string是不同的型別。

 

處理string物件中的字元

可以參考cctype標頭檔案中的函式,如判斷是否為數字,大小寫字元等。