1. 程式人生 > >C++ string操作彙總

C++ string操作彙總

C++ string與C字串轉換

1、首先必須瞭解,string可以被看成是以字元為元素的一種容器。字元構成序列(字串)。有時候在字元序列中進行遍歷,標準的string類提供了STL容器介面。具有一些成員函式比如begin()、end(),迭代器可以根據他們進行定位。

注意,與char*不同的是,string不一定以NULL('\0')結束。string長度可以根據length()得到,string可以根據下標訪問。所以,不能將string直接賦值給char*。

2、string 轉換成 char *

如果要將string直接轉換成const char *型別。string有2個函式可以運用。

一個是.c_str(),一個是data成員函式。

例子如下:

string s1 = "abcdeg";
const char *k = s1.c_str();
const char *t = s1.data();
printf("%s%s",k,t);
cout<<k<<t<<endl;

如上,都可以輸出。內容是一樣的。但是隻能轉換成const char*,如果去掉const編譯不能通過。

那麼,如果要轉換成char*,可以用string的一個成員函式copy實現。

string s1 = "abcdefg";
char *data;
int len = s1.length();
data = (char *)malloc((len+1)*sizeof(char));
s1.copy(data,len,0);
printf("%s",data);
cout<<data;

3、char *轉換成string

可以直接賦值。

string s;

char *p = "adghrtyh";

s = p;

不過這個是會出現問題的。

有一種情況我要說明一下。當我們定義了一個string型別之後,用printf("%s",s1);輸出是會出問題的。這是因為“%s”要求後面的物件的首地址。但是string不是這樣的一個型別。所以肯定出錯。

用cout輸出是沒有問題的,若一定要printf輸出。那麼可以這樣:
printf("%s",s1.c_str())

4、char[] 轉換成string

這個也可以直接賦值。但是也會出現上面的問題。需要同樣的處理。

5、string轉換成char[]

這個由於我們知道string的長度,可以根據length()函式得到,又可以根據下標直接訪問,所以用一個迴圈就可以賦值了。

這樣的轉換不可直接賦值。

    string pp = "dagah";
    char p[8];
    int i;
    for( i=0;i<pp.length();i++)
        p[i] = pp[i];
    p[i] = '\0';
    printf("%s\n",p);
    cout<<p;

string輸入輸出操作

由於呼叫系統函式在螢幕上逐個顯示字元是很慢的,因此cin/cout為了加快速度使用緩衝區技術,粗略的講就是暫時不輸出指定的字元,而是存放在緩衝區中,在合適的時機一次性輸出到螢幕上。如果單純使用C++的輸入/輸出流來操作字元是不存在同步的問題的,但是如果要和C標準庫的stdio庫函式混合使用就必須要小心的處理緩衝區了。如果要與scanf和printf聯合使用,務必在呼叫cout前加上cout.sync_with_stdio(),設定與stdio同步,否則輸出的資料順序會發生混亂。

flush和endl都會將當前緩衝區中的內容立即寫入到螢幕上,而unitbuf/nounitbuf可以禁止或啟用緩衝區。示例程式碼如下:

1 2 3 4 5 6 7 8 #include <iomanip> #include <iostream> using namespace std; int main(void) { cout << 123 << flush << 456 << endl; cout << unitbuf << 123 << nounitbuf << 456 << endl; return 0; }
字串的輸出處理主要是對齊,這一點在第二部分已經介紹過了,下面主要介紹字串的輸入方法。為了方便起見,我們使用<string>庫。在輸入字串時,可以利用<string>庫提供的getline函式讀取整行資料。getline函式有兩個版本,第一個版本有兩個引數,第一個引數指定輸入流(比如cin),第二個引數指定一個string物件。getline會讀取螢幕上輸入的字元,直到遇到換行符“\n”為止;第二個版本有三個引數,前兩個與第一個版本相同,第三個引數為指定的結束字元。注意,getline不會讀入預設或指定的結束字元,但在呼叫之後讀取的位置已經跳過結束字元。

cout是STL庫提供的一個iostream例項,擁有ios_base基類的全部函式和成員資料。進行格式化操作可以直接利用setf/unsetf函式和flags函式。cout維護一個當前的格式狀態,setf/unsetf函式是在當前的格式狀態上追加或刪除指定的格式,而flags則是將當前格式狀態全部替換為指定的格式。cout為這個函式提供瞭如下引數(可選格式):

  • ios::dec  以10進製表示整數
  • ios::hex  以16進製表示整數
  • ios::oct  以8進製表示整數
  • ios::showbase  為整數新增一個表示其進位制的字首
  • ios::internal  在符號位和數值的中間插入需要數量的填充字元以使串兩端對齊
  • ios::left  在串的末尾插入填充字元以使串居左對齊
  • ios::right  在串的前面插入填充字元以使串居右對齊
  • ios::boolalpha  將bool型別的值以true或flase表示,而不是1或0
  • ios::fixed  將符點數按照普通定點格式處理(非科學計數法)
  • ios::scientific  將符點數按照科學計數法處理(帶指數域)
  • ios::showpoint  在浮點數表示的小數中強制插入小數點(預設情況是浮點數表示的整數不顯示小數點)
  • ios::showpos  強制在正數前新增+號
  • ios::skipws  忽略前導的空格(主要用於輸入流,如cin)
  • ios::unitbuf  在插入(每次輸出)操作後清空快取
  • ios::uppercase  強制大寫字母

以上每一種格式都佔用獨立的一位,因此可以用“|”(位或)運算子組合使用。呼叫setf/unsetf或flags設定格式一般按如下方式進行:

1 2 cout.setf(ios::right | ios::hex); //設定16進位制右對齊 cout.setf(ios::right, ios::adjustfield); //取消其它對齊,設定為右對齊

setf可接受一個或兩個引數,一個引數的版本為設定指定的格式,兩個引數的版本中,後一個引數指定了刪除的格式。三個已定義的組合格式為:

  • ios::adjustfield  對齊格式的組合位
  • ios::basefield  進位制的組合位
  • ios::floatfield  浮點表示方式的組合位

設定格式之後,下面所有使用cout進行的輸出都會按照指定的格式狀態執行。但是如果在一次輸出過程中需要混雜多種格式,使用cout的成員函式來處理就顯得很不方便了。STL另提供了一套<iomanip>庫可以滿足這種使用方式。<iomanip>庫中將每一種格式的設定和刪除都進行了函式級的同名封裝,比如fixed函式,就可以將一個ostream的物件作為引數,在內部呼叫setf函式對其設定ios::fixed格式後再返回原物件。此外<iomanip>還提供了setiosflags、setbase、setfill、setw、setprecision等方便的格式控制函式

小數可分為兩種格式型別,一種是定點表示“ios::fixed”(不帶指數域),另一種是科學計數法表示“ios::scientific”(帶指數域)。與<iomanip>的setprecision配合使用,可以表示指定小數點後面的保留位數(四捨五入)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iomanip> #include <iostream> using namespace std; int main(void) { cout.setf(ios::fixed); cout << setprecision(0) << 12.05 << endl; cout << setprecision(1) << 12.05 << endl; cout << setprecision(2) << 12.05 << endl; cout << setprecision(3) << 12.05 << endl; cout.setf(ios::scientific, ios::floatfield); cout << setprecision(0) << 12.05 << endl; cout << setprecision(1) << 12.05 << endl; cout << setprecision(2) << 12.05 << endl; cout << setprecision(3) << 12.05 << endl; return 0; }

結果:

12
12.1
12.05
12.050
1.205000e+001
1.2e+001
1.21e+001
1.205e+001

需要注意的是,有時會因為機器的精度問題導致四捨五入的結果不正確。這種問題一般需要手動修正,見如下程式碼示例:

1 2 3 4 5 6 7 8 #include <iomanip> #include <iostream> using namespace std; int main(void) { cout << fixed << setprecision(1) << 2.05 << endl; cout << fixed << setprecision(1) << 2.05 + 1e-8 << endl; return 0; }

結果:

2.0
2.1


string容器類

string類的建構函式:
string(const char *s);    //用c字串s初始化
string(int n,char c);     //用n個字元c初始化
此外,string類還支援預設建構函式和複製建構函式,如string s1;string s2="hello";都是正確的寫法。當構造的string太長而無法表達時會丟擲length_error異常

string類的字元操作:
const char &operator[](int n)const;
const char &at(int n)const;
char &operator[](int n);
char &at(int n);
operator[]和at()均返回當前字串中第n個字元的位置,但at函式提供範圍檢查,當越界時會丟擲out_of_range異常,下標運算子[]不提供檢查訪問。
const char *data()const;//返回一個非null終止的c字元陣列
const char *c_str()const;//返回一個以null終止的c字串
int copy(char *s, int n, int pos = 0) const;//把當前串中以pos開始的n個字元拷貝到以s為起始位置的字元陣列中,返回實際拷貝的數目

string的特性描述:
int capacity()const;    //返回當前容量(即string中不必增加記憶體即可存放的元素個數)
int max_size()const;    //返回string物件中可存放的最大字串的長度
int size()const;        //返回當前字串的大小
int length()const;       //返回當前字串的長度
bool empty()const;        //當前字串是否為空
void resize(int len,char c);//把字串當前大小置為len,並用字元c填充不足的部分

string類的輸入輸出操作:
string類過載運算子operator>>用於輸入,同樣過載運算子operator<<用於輸出操作。
函式getline(istream &in,string &s);用於從輸入流in中讀取字串到s中,以換行符'\n'分開。
 

string的賦值:
string &operator=(const string &s);//把字串s賦給當前字串
string &assign(const char *s);//用c型別字串s賦值
string &assign(const char *s,int n);//用c字串s開始的n個字元賦值
string &assign(const string &s);//把字串s賦給當前字串
string &assign(int n,char c);//用n個字元c賦值給當前字串
string &assign(const string &s,int start,int n);//把字串s中從start開始的n個字元賦給當前字串
string &assign(const_iterator first,const_itertor last);//把first和last迭代器之間的部分賦給字串
 

string的連線:
string &operator+=(const string &s);//把字串s連線到當前字串的結尾 

string &append(const char *s);            //把c型別字串s連線到當前字串結尾
string &append(const char *s,int n);//把c型別字串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
string &append(const_iterator first,const_iterator last);//把迭代器first和last之間的部分連線到當前字串的結尾 

string的比較:
bool operator==(const string &s1,const string &s2)const;//比較兩個字串是否相等
運算子">","<",">=","<=","!="均被過載用於字串的比較;
int compare(const string &s) const;//比較當前字串和s的大小
int compare(int pos, int n,const string &s)const;//比較當前字串從pos開始的n個字元組成的字串與s的大小
int compare(int pos, int n,const string &s,int pos2,int n2)const;//比較當前字串從pos開始的n個字元組成的字串與s中pos2開始的n2個字元組成的字串的大小
int compare(const char *s) const;
int compare(int pos, int n,const char *s) const;
int compare(int pos, int n,const char *s, int pos2) const;
compare函式在>時返回1,<時返回-1,==時返回0 

string的子串:
string substr(int pos = 0,int n = npos) const;//返回pos開始的n個字元組成的字串


string的交換:
void swap(string &s2);    //交換當前字串與s2的值

string類的查詢函式:

int find(char c, int pos = 0) const;//從pos開始查詢字元c在當前字串的位置
int find(const char *s, int pos = 0) const;//從pos開始查詢字串s在當前串中的位置
int find(const char *s, int pos, int n) const;//從pos開始查詢字串s中前n個字元在當前串中的位置
int find(const string &s, int pos = 0) const;//從pos開始查詢字串s在當前串中的位置
//查詢成功時返回所在位置,失敗返回string::npos的值

int rfind(char c, int pos = npos) const;//從pos開始從後向前查詢字元c在當前串中的位置
int rfind(const char *s, int pos = npos) const;
int rfind(const char *s, int pos, int n = npos) const;
int rfind(const string &s,int pos = npos) const;
//從pos開始從後向前查