STL詳解(十) 字符串string

使用場合:

因爲C風格字符串(以空字符結尾的字符數組)太過複雜難於掌握,不適合大程序的開發,所以C++標準庫定義了一種string類,它不必擔心內存是否足夠及字符串長度,可以使用輸入輸出流方式直接進行操作,也可以通過文件等手段進行操作,同時C++的算法庫對string也有着很好的支持 ,而且string還和c語言的字符串之間有着良好的接口,因此現在編程中涉及到字符串的處理,就可以直接使用string類了。

string類是由模板而實例化的一個標準類,本質上不是一個標準數據類型,我們儘可以把它看成是C++的基本數據類型。

string 函數列表

函數名 描述
begin 得到指向字符串開頭的Iterator
end 得到指向字符串結尾的Iterator
rbegin 得到指向反向字符串開頭的Iterator
rend 得到指向反向字符串結尾的Iterator
size 得到字符串的大小
length 和size函數功能相同
max_size 字符串可能的最大大小
capacity 在不重新分配內存的情況下,字符串可能的大小
empty 判斷是否爲空
[  ]、at 下標訪問,取第幾個元素,相當於數組
c_str 取得C風格的const char* 字符串
data 取得字符串內容地址
operator= 賦值操作符
reserve 預留空間
swap 交換函數
insert 插入字符
append 追加字符
push_back 追加字符
+= += 操作符
erase 刪除字符串
clear 清空字符容器中所有內容
resize 重新分配空間
assign 和賦值操作符一樣
replace 替代
copy 字符串到空間
find 查找
rfind 反向查找
find_first_of 查找包含子串中的任何字符,返回第一個位置
find_first_not_of 查找不包含子串中的任何字符,返回第一個位置
find_last_of 查找包含子串中的任何字符,返回最後一個位置
find_last_not_of 查找不包含子串中的任何字符,返回最後一個位置
substr 得到字串
compare 比較字符串
+ 字符串鏈接
== 判斷是否相等
!= 判斷是否不等於
< 、 <= 、 >=  、> 判斷是否小於、小於等於、大於等於、大於
>> 從輸入流中讀入字符串
<< 字符串寫入輸出流
getline 從輸入流中讀入一行

一、string的初始化

    首先,爲了在我們的程序中使用string類型,我們必須包含頭文件

    #include<string>                   //注意這裏不是string.h ,    string.h是C字符串頭文件,   當然也可以用萬能頭文件<bits/stdc++.h>

    using    namespace   std;     //此語句必不可少,否則有的編譯器無法識別。

二、C++字符串聲明與初始化賦值

聲明一個字符串變量:

string s;//聲明一個string 對象

string ss[10];//聲明一個string對象的數組

 

 

 

這樣我們就聲明瞭一個字符串變量s 和一個字符串對象數組。

string是C++中一個類,就有構造函數和析構函數。上面的聲明沒有傳入參數,所以就直接使用了string的默認的構造函數,這個函數所作的就是把Str初始化爲一個空字符串。String類的構造函數和析構函數如下:

#include<bits/stdc++.h>
using namespace std;
int main()
{ freopen("a.in","r",stdin);
  freopen("a.out","w",stdout);
  string str;             //定義了一個空字符串str
  str = "Hello world";    // 給str賦值爲"Hello world",也可以上面定義時直接賦值。
  char cstr[] = "abcde";  //定義了一個C字符串
  
  string s1(str);         //調用複製構造函數生成s1,s1爲str的複製品
  string s4(cstr);        //將C字符串作爲s4的初值
  string str1("1234");    //生成"1234"的複製品
  cout<<s1<<endl;
  cout<<s4<<endl;
  cout<<str1<<endl;
  
  string s2(str,6);       //將str內,開始於位置6的部分當作s2的初值
  string s5(cstr,3);      //將C字符串前3個字符作爲字符串s5的初值。
  string str4("123456",5);//結果爲"12345"
  cout<<s2<<endl; 
  cout<<s5<<endl;
  cout<<str4<<endl;

  string s3(str,6,3);     //將str內,開始於6且長度頂多爲3的部分作爲s3的初值
  string str3("12345",1,3);//結果爲"234"
  cout<<s3<<endl;
  cout<<str3<<endl;
  
  string s6(5,'A');       //生成一個字符串,包含5個'A'字符
  cout<<s6<<endl;
  string s7(str.begin(),str.begin()+5); //區間str.begin()和str.begin()+5內的字符作爲初值
  cout<<s7<<endl;
  str.~string();           //銷燬str字串所有字符,釋放內存
}

程序執行結果爲:

Hello world
abcde
1234
world
abc
12345
wor
234
AAAAA
Hello

三、string特性描述

可用下列函數來獲得string的一些特性:

返回值類型 函數 描述
int capacity() 返回當前容量(即string中不必增加內存即可存放的元素個數
int max_size() 返回string對象中可存放的最大字符串的長度
int size() 返回當前字符串的大小
int length() 返回當前字符串的長度
bool empty() 當前字符串是否爲空
void resize(int len,char c) 把字符串當前大小置爲len,多去少補,多出的字符c填充不足的部分

大小和容量:

1. size()和length():返回string對象的字符個數,他們執行效果相同。C++的話,傾向於用 size();
2.empty()用來檢查字符串是否爲空。
3. max_size():返回string對象最多包含的字符數,很可能和機器本身的限制或者字符串所在位置連續內存的大小有關係。我們一般情況下不用關心他,應該大小足夠我們用的。但是不夠用的話,會拋出length_error異常。
4. capacity()函數返回在重新申請更多的空間前字符串可以容納的字符數.就是string當前能夠容納的最大字符數;即capacity()>=length()。
5.resize()函數,爲string重新分配內存。重新分配的大小由其參數決定,默認參數爲0,這時候會對string進行非強制性縮減。

 

#include<bits/stdc++.h>
using namespace std;
int main()
{   string str;
    if (str.empty())  cout<<"str is NULL."<<endl;
       else   cout<<"str is not NULL."<<endl;
    str = str + "abcdefg";
    cout<<"str is "<<str<<endl;
    cout<<"str's size is "<<str.size()<<endl;
    cout<<"str's capacity is "<<str.capacity()<<endl;
    cout<<"str's max size is "<<str.max_size()<<endl;
    cout<<"str's length is "<<str.length()<<endl;
    str.resize(20,'c');
    cout<<"str is "<<str<<endl;
    str.resize(5);
    cout<<"str is "<<str<<endl;
    return 0;
}

程序執行結果爲:

str is NULL.
str is abcdefg
str's size is 7
str's capacity is 7
str's max size is 1073741820
str's length is 7
str is abcdefgccccccccccccc
str is abcde

 

四、string的比較操作(==、>、<、>=、<=、!=、compare()

1、用運算符 ==、>、<、>=、<=、和!=比較字符串,這些操作符是按從左向右順序逐一比較,遇到不相等的字符就按這個位置上的兩個字符的ASC碼大小比較,ASC碼大的字串大。

2、compare()比較兩個字符串。

compare()爲區分大小寫比較字符串,比如,利用compare比較字串“str”與字串“lpsz”,等同於區分大小寫比較“str”與“lpsz”的第一個相異字符,如果“str”該處的字符比“lpsz”大,則字符串“str”大於“lpsz”,返回1;如果“str”該處的字符比“lpsz”小,則字符串“str”小於“lpsz”,返回-1;“str”與“lpsz”內容完全一致則返回0。

返回值類型 函數 描述
int str.compare(const string &s) 比較字符串str和s的大小
int str.compare(int pos, int n,const string &s) 比較字符串str從pos開始的n個字符組成的字符串與s的大小
int str.compare(int pos, int n,const string &s,int pos2,int n2)

比較字符串str從pos開始的n個字符組成的字符串與s中pos2開始的n2個字符組成的字符串的大小

int str.compare(const char *s) ; 比較字符串str和c字符串s的大小
int  str.compare(int pos, int n,const char *s) ; 比較字符串str從pos開始的n個字符組成的字符串與c字符串s的大小
int str.compare(int pos, int n,const char *s, int pos2,int n2) ; 比較字符串str從pos開始的n個字符組成的字符串與c字符串s中pos2開始的n2個字符組成的字符串的大小

例一、

#include<bits/stdc++.h>
using namespace std;
int main()
{
    string str;
    cout << "Please input your name:"<<endl;
    cin >> str;
    if( str == "Li" )   // 字符串相等比較
        cout << "you are Li!"<<endl;
    else if( str != "Wang" )  // 字符串不等比較
        cout << "you are not Wang!"<<endl;
    else if( str < "Li")     // 字符串小於比較,>、>=、<=類似
        cout << "your name should be ahead of Li"<<endl;
    else
        cout << "your name should be after of Li"<<endl;
    str += ", Welcome!";  // 字符串+=
    cout << str<<endl;
    for(int i = 0 ; i < str.size(); i ++)
        cout<<str[i];  // 類似數組,通過[]獲取特定的字符,可換爲: cout<<str.at(i);
    return 0;
}

程序執行結果爲:

Please input your name:
Zhang↙

you are not Wang!
Zhang, Welcome!
Zhang, Welcome!

例二:

#include<bits/stdc++.h>
using namespace std;
int main()
{ 	string str1="hi,test,hello";
	string str2="hi,test";
	//字符串比較
	if(str1.compare(str2)>0) printf("str1>str2\n");
	else if(str1.compare(str2)<0)	printf("str1<str2\n");
	     else	printf("str1==str2\n");
	
	//str1的子串(從索引3開始,包含4個字符)與str2進行比較
	if(str1.compare(3,4,str2)==0)	printf("str1的指定子串等於str2\n");
	else	printf("str1的指定子串不等於str2\n");
	
	//str1指定子串與str2的指定子串進行比較
	if(str1.compare(3,4,str2,3,4)==0) printf("str1的指定子串等於str2的指定子串\n");
	else printf("str1的指定子串不等於str2的指定子串\n");
	
	//str1指定子串與字符串的前n個字符進行比較
	if(str1.compare(0,2,"hi,hello",2)==0) printf("str1的指定子串等於指定字符串的前2個字符組成的子串\n");
	else	printf("str1的指定子串不等於指定字符串的前2個字符組成的子串\n");
	return 0;	
}

程序執行結果爲:

str1>str2
str1的指定子串不等於str2
str1的指定子串等於str2的指定子串
str1的指定子串等於指定字符串的前2個字符組成的子串

例三:

#include<bits/stdc++.h>
using namespace std;
int main()
{  	string A("aBcdef");	string B("AbcdEf");	string C("123456");	string D("123dfg");
	int m = A.compare(B);
	int n = A.compare(1, 5, B);
	int p = A.compare(1, 5, B, 4, 2);
	int q = A.compare(0, 3, D, 0, 3);
	cout << "m=" << m << endl;
	cout << "n=" << n << endl;
	cout << "p=" << p << endl;
	cout << "q=" << q << endl;
}

程序執行結果爲:

m=1
n=1
p=-1
q=1

 

五、字符串內容修改

(5.1)string類的賦值函數:給字符串賦值assign()函數。

返回值類型 函數 描述
string str=(const string &s); 把字符串s,賦值給字符串str
string str.assign(const char *s); 用c類型字符串s賦值給字符串str
string str.assign(const char *s,int n); 用c字符串s前n個字符,賦值給字符串str
string str.assign(const string &s); 把字符串s,賦值給字符串str
string str.assign(int n,char c); 用n個字符c,賦值給字符串str
string str.assign(const string &s,int start,int n); 把字符串s中從start開始的n個字符,賦值給字符串str
string str.assign(const_iterator first,const_itertor last); 把first和last迭代器之間的部分,賦值給字符串str
#include<bits/stdc++.h>
using namespace std;
int main()
{   string str;
    string base="The quick brown fox jumps over a lazy dog.";
        
    str.assign(base);       //直接把base賦值給str
                            //str(base)是錯誤的,只有在賦初值時可以用str(base)。
    cout<<str<<'\n';
    
    str.assign(base,10,9);  //把base第10個字符以及後面的8個字符賦給str
    cout<<str<<'\n';        // "brown fox"
    
    str.assign("pangrams are cool",7);//把參數中的0到6個字符串賦給str
    cout<<str<<'\n';        // "pangram"
    
    str.assign("c-string"); //直接使用參數賦值
    cout << str << '\n';    // "c-string"
    
    str.assign(10,'*');     //給str賦值10個'*'字符
    cout<<str<<'\n';        // "**********"
    
    str.assign<int>(10,0x2D);//賦值是10個'-'
    cout << str << '\n';     // "----------"
   
    str.assign(base.begin()+16,base.end()-12); //指定base迭代器範圍的字符串
    cout<<str<<'\n';         // "fox jumps over"
}

程序執行結果爲:

The quick brown fox jumps over a lazy dog.
brown fox
pangram
c-string
**********
----------
fox jumps over

(5.2)字符的連接(在尾巴上增加)

        1、append()函數可以用來在字符串的末尾追加字符和字符串,

        2、也可以用 + 和 += 來實現,

        3、push_back()在字符串的末尾追加一個字符,不能追加字符串。

返回值類型 函數 描述
string str+=(const string &s); 把字符串s,連接到字符串str的結尾 
string str.append(const char *s);  把c類型字符串s,連接到字符串str的結尾 
string str.append(const char *s,int n); 把c類型字符串s的前n個字符,連接到字符串str的結尾 
string str.append(const string &s);  把字符串s,連接到字符串str的結尾 ,同+=相同。
string str.append(const string &s,int pos,int n); 把字符串s中從pos開始的n個字符,連接到字符串str的結尾 
string str.append(int n,char c);   在字符串str結尾添加n個字符c
string str.append(const_iterator first,const_iterator last); 把迭代器first和last之間的部分,連接到字符串str的結尾 
string str.push_back(char c) 在字符串str的末尾追加一個字符
#include<bits/stdc++.h>
using namespace std;
int main()
{string str;
 string str2="Writing ";
 string str3="print 10 and then 5 more";

 str.append(str2);        //直接追加一個str2的字符串,追加"Writing "
 str.append(str3,6,3);    //後面追加str3第6個字符開始的3個字符串 ,追加"10 "
 str.append("dots are cool",5); //追加字符串形參的前5個字符,追加"dots "
 str.append("here: ");    //直接追加 "here: "
 str.append(10,'.');     //追加 10個'.' ,追加 ".........."
 str.append(str3.begin()+8,str3.end()); //從str3的第8個字符開始追加" and then 5 more"
 str.append<int>(5,65);   //這個比較特殊,意思是添加5個'A',65對應的asc碼就是65
 
 str+="lalala";           //字符串追加也可以用重載運算符實現
 
 str.push_back('X');    //括號內不能用雙引號如:“X”,不能用多個字符如:“AFF”。 

 cout<<str<<'\n';
}

程序執行結果爲:

Writing 10 dots here: .......... and then 5 moreAAAAAlalalaX

    (5.3)string類的插入函數:插入字符串insert()。

返回值類型 函數 描述
string str.insert(int p0, const char *s); 在p0位置插入C語言字符串s
string str.insert(int p0, const char *s, int n); 在p0位置插入C語言字符串s的前n個字符
string str.insert(int p0,const string &s); 在p0位置插入C++字符串s
string str.insert(int p0,const string &s, int pos, int n); 在p0位置插入C++字符串s從pos開始的連續n個字符
string str.insert(int p0, int n, char c); 在p0處插入n個字符c
iterator str.insert(iterator it, char c); 在it處插入字符c,返回插入後迭代器的位置
void str.insert(iterator it, const_iterator first, const_iteratorlast); 在it處插入從first開始至last-1的所有字符
void str.insert(iterator it, int n, char c); 在it處插入n個字符c

例一、

#include <bits/stdc++.h>
using namespace std;
int main()
{   ios::sync_with_stdio(false);    
    string str="to be question";
    string str2="the ";
    string str3="or not to be";
    string::iterator it;

    //s.insert(pos,str)//在s的pos位置插入str
    str.insert(6,str2);                 // to be the question
    cout<<str<<endl;
    //s.insert(pos,str,a,n)在s的pos位置插入str中插入位置a到後面的n個字符
    str.insert(6,str3,3,4);             // to be not the question
    cout<<str<<endl;
    //s.insert(pos,cstr,n)//在pos位置插入cstr字符串從開始到後面的n個字符
    str.insert(10,"that is cool",8);    // to be not that is the question
    cout<<str<<endl;
    //s.insert(pos,cstr)在s的pos位置插入cstr
    str.insert(10,"to be ");            // to be not to be that is the question
    cout<<str<<endl;
    //s.insert(pos,n,ch)在s.pos位置上面插入n個ch
    str.insert(15,1,':');               // to be not to be: that is the question
    cout<<str<<endl;
    //s.insert(s.it,ch)在s的it指向位置前面插入一個字符ch,返回新插入的位置的迭代器
    it = str.insert(str.begin()+5,','); // to be, not to be: that is the question
    cout<<*it<<endl;
    cout<<str<<endl;
    //s.insert(s.it,n,ch)//在s的it所指向位置的前面插入n個ch
    str.insert (str.end(),3,'.');       // to be, not to be: that is the question...
    cout<<str<<endl;
    //s.insert(it,str.ita,str.itb)在it所指向的位置的前面插入[ita,itb)的字符串
    str.insert (it+2,str3.begin(),str3.begin()+3); // to be, or not to be: that is the question...
    cout<<str<<endl;
}

程序執行結果爲:

to be the question
to be not the question
to be not that is the question
to be not to be that is the question
to be not to be: that is the question
,
to be, not to be: that is the question
to be, not to be: that is the question...
to be, or not to be: that is the question...

在競賽中遇到大數據時,往往讀文件成了程序運行速度的瓶頸,需要更快的讀取方式。cin讀入速度緩慢原因一般cin與stdin總是保持同步的,正因爲這個的特性,導致cin有許多額外的開銷,禁用這個特性只需一個語句std::ios::sync_with_stdio(false);,這樣就可以取消cin於stdin的同步了,效率可以提高几乎10倍。

(5.4)string類的刪除函數 :刪除字符串erase()。

返回值類型 函數 描述
iterator str.erase(iterator first, iterator last); 刪除[first,last)之間的所有字符,返回刪除後迭代器的位置
iterator str.erase(iterator it); 刪除it指向的字符,返回刪除後迭代器的位置
string str.erase(int pos = 0, int n = npos); 刪除pos開始的n個字符,返回修改後的字符串
#include <bits/stdc++.h>
using namespace std;
int main()
{ string str("This is an example sentence.");
  cout << str << '\n';  
                          // "This is an example sentence."
  str.erase (10,8);       //            ^^^^^^^^
  //直接指定刪除的字符串位置第十個後面的8個字符
  cout << str << '\n';
                            // "This is an sentence."
  str.erase (str.begin()+9);//           ^
  //刪除迭代器指向的字符
  cout << str << '\n';
                            // "This is a sentence."
                            //       ^^^^^
  str.erase (str.begin()+5, str.end()-9);
  //刪除迭代器範圍的字符
  cout << str << '\n';
                            // "This sentence."
}

 程序執行結果爲:

This is an example sentence.
This is an sentence.
This is a sentence.
This sentence.

(5.5)string類的替換函數(replace):​​​​​替換字符串。

返回值類型 函數 描述
string str.replace(int p0, int n,const char *s); 刪除從p0開始的n0個字符,然後在p0處插入串s
string str.replace(int p0, int n0,const char *s, int n); 刪除p0開始的n0個字符,然後在p0處插入字符串s的前n個字符
string str.replace(int p0, int n0,const string &s); 刪除從p0開始的n0個字符,然後在p0處插入串s
string str.replace(int p0, int n0,const string &s, int pos, int n); 刪除p0開始的n0個字符,然後在p0處插入串s中從pos開始的n個字符
string str.replace(int p0, int n0,int n, char c); 刪除p0開始的n0個字符,然後在p0處插入n個字符c
string str.replace(iterator first0, iterator last0,const char *s); 把[first0,last0)之間的部分替換爲字符串s
string str.replace(iterator first0, iterator last0,const char *s, int n); 把[first0,last0)之間的部分替換爲s的前n個字符
string str.replace(iterator first0, iterator last0,const string &s); 把[first0,last0)之間的部分替換爲串s
string replace(iterator first0, iterator last0,int n, char c); 把[first0,last0)之間的部分替換爲n個字符c
string replace(iterator first0, iterator last0,const_iterator first, const_iterator last); 把[first0,last0)之間的部分替換成[first,last)之間的字符串

例一:

#include <bits/stdc++.h>
using namespace std;
int main ()
{   string base="this is a test string.";
    string str2="n example";
    string str3="sample phrase";
    string str4="useful.";

string str=base;   // "this is a test string."
cout<<str<<endl; 
	
	//str第9個字符以及後面的5個字符被str2代替
str.replace(9,5,str2);  // "this is an example string." (1)
cout<<str<<endl;
	
	//第19個字符串以及後面的6個字符用str的第7個字符以及後面的6個字符代替
str.replace(19,6,str3,7,6);   // "this is an example phrase." (2)
cout<<str<<endl;
   
    //第8個字符以及後面的9個字符用字符串參數代替
str.replace(8,10,"just a");   // "this is just a phrase."     (3)
cout<<str<<endl;
   
    //第8個字符以及後面的5個字符用字符串參數的前7個字符替換
str.replace(8,6,"a shorty",7); // "this is a short phrase."    (4)
cout<<str<<endl;
	
	//第22以及後面的0個字符用3個歎號替換
str.replace(22,1,3,'!');       // "this is a short phrase!!!"  (5)
cout<<str<<endl;
	
	//迭代器的原理同上
    // Using iterators:    0123456789*123456789*
str.replace(str.begin(),str.end()-3,str3);      // "sample phrase!!!"      (1)
cout<<str<<endl;
str.replace(str.begin(),str.begin()+6,"replace");  // "replace phrase!!!"  (3)
cout<<str<<endl;
str.replace(str.begin()+8,str.begin()+14,"is coolness",7);//"replace is cool!!!" (4)
cout<<str<<endl;
str.replace(str.begin()+12,str.end()-4,4,'o');  // "replace is cooool!!!"  (5)
cout<<str<<endl;
str.replace(str.begin()+11,str.end(),str4.begin(),str4.end()); // "replace is useful." (6)
cout<<str<<endl;
}

程序執行結果爲:

this is a test string.
this is an example string.
this is an example phrase.
this is just a phrase.
this is a short phrase.
this is a short phrase!!!
sample phrase!!!
replace phrase!!!
replace is cool!!!
replace is cooool!!!
replace is useful.

(5.6)sawp()函數:相互交換字符串

#include <bits/stdc++.h>
using namespace std;
int main()
{string str="give me";
 string str1="a cup'";
 str.swap(str1);
 cout<<str<<endl;    //輸出:a cup
 cout<<str1<<endl;   //輸出:give me
}

(5.7)把字符串清空

把字符串清空的方法有三個:

1、s=””;

2、s.clear();

3、s.erase();

(5.8)string和數值轉換  :

在c++11當中有定義好的現成的函數取調用,非常方便。

返回值類型 函數 描述
string to_string(val) 把val轉換成string
int stoi(s,p,b) 把字符串s從p開始轉換成b進制的int
long stol(s,p,b)  把字符串s從p開始轉換成b進制的long
unsigned long stoul(s,p,b)  把字符串s從p開始轉換成b進制的unsigned long
long long stoll(s,p,b) 把字符串s從p開始轉換成b進制的long long
unsigned long long stoull(s,p,b) 把字符串s從p開始轉換成b進制的unsigned long long
float stof(s,p) 把字符串s從p開始轉換成float
double stod(s,p)  把字符串s從p開始轉換成double
long double stold(s,p)  把字符串s從p開始轉換成long double

以上函數是C++11中的庫函數,讓Dev C++支持C++11還要在軟件中進行設置。

1.先在dev的【工具】裏找到【編譯選項】


2.一開始普遍的dev應該都是以下這個界面,在【編譯時加入以下命令】欄是空白的且沒有打鉤。


3.奇蹟就在此刻改變.在這個【編譯時加入以下命令】處打鉤,然後在空白欄輸入【-std=c++11】(c是小寫的),確定.然後就能支持c++1

#include <bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    string s1;
    s1=to_string(100);
    cout<<s1<<endl;
    int a=stoi(s1,0,10)+1;
    cout<<a<<endl;
}

以上程序在Dev C++編譯環境中設置好【-std=c++11】後纔可以運行。

(5.9)String字符串與字符(char類型)數組互相轉換 :

1、字符數組轉化成string類型

#include<bits/stdc++.h>
using namespace std;
int main()
{char ch[] = "ABCDEFG";
 string str(ch);//也可string str = ch;
 cout<<str;
}

或者

#include<bits/stdc++.h>
using namespace std;
int main()
{char ch[]="ABCDEFG";
 string str;
 str=ch;//在原有基礎上添加可以用str+=ch;
 cout<<str;
}


2、將string類型轉換爲字符數組
char buf[10];
string str("ABCDEFG");
length = str.copy(buf, 9);
buf[length] = '\0';
或者
char buf[10];
string str("ABCDEFG");
strcpy(buf, str.c_str());//strncpy(buf, str.c_str(), 10);

標準庫的string類提供了3個成員函數來從一個string得到c類型的字符數組:c_str()、data()、copy(p,n)。

1. c_str():生成一個const char*指針,指向以空字符終止的數組。

注:

①這個數組的數據是臨時的,當有一個改變這些數據的成員函數被調用後,其中的數據就會失效。因此要麼現用先轉換,要麼把它的數據複製到用戶自己可以管理的內存中。注意。看下例:

const char* c;

string s="1234";

c = s.c_str();

cout<<c<<endl; //輸出:1234

s="abcd";

cout<<c<<endl; //輸出:abcd

 

上面如果繼續用c指針的話,導致的錯誤將是不可想象的。就如:1234變爲abcd

其實上面的c = s.c_str(); 不是一個好習慣。既然c指針指向的內容容易失效,我們就應該按照上面的方法,那怎麼把數據複製出來呢?這就要用到strcpy等函數(推薦)。

//const char* c; //①

//char* c;       //②

//char c[20];

char* c=new char[20];

string s="1234";

//c = s.c_str();

strcpy(c,s.c_str());

cout<<c<<endl; //輸出:1234

s="abcd";

cout<<c<<endl; //輸出:1234

注意:不能再像上面一樣①所示了,const還怎麼向裏面寫入值啊;也不能②所示,使用了未初始化的局部變量“c”,運行會出錯的 。

② c_str()返回一個客戶程序可讀不可改的指向字符數組的指針,不需要手動釋放或刪除這個指針。

2. data():與c_str()類似,但是返回的數組不以空字符終止。

3. copy(p,n,size_type _Off = 0):從string類型對象中至多複製n個字符到字符指針p指向的空間中。默認從首字符開始,但是也可以指定,開始的位置(記住從0開始)。返回真正從對象中複製的字符。------用戶要確保p指向的空間足夠保存n個字符。

#include <bits/stdc++.h>

using namespace std;

int main( )

{   string str1 ( "1234567890" );

    basic_string <char>::iterator str_Iter;

    char array1 [ 20 ] = { 0 };

    char array2 [ 10 ] = { 0 };

    basic_string <char>:: pointer array1Ptr = array1;

    basic_string <char>:: value_type *array2Ptr = array2;



    cout << "The original string str1 is: ";

    for ( str_Iter = str1.begin( ); str_Iter != str1.end( ); str_Iter++ )

        cout << *str_Iter;

    cout << endl;



    basic_string <char>:: size_type nArray1;

    // Note: string::copy is potentially unsafe, consider

    // using string::_Copy_s instead.

    nArray1 = str1.copy ( array1Ptr , 12 );  // C4996

    cout << "The number of copied characters in array1 is: "

        << nArray1 << endl;

    cout << "The copied characters array1 is: " << array1Ptr << endl;



    basic_string <char>:: size_type nArray2;

    // Note: string::copy is potentially unsafe, consider

    // using string::_Copy_s instead.

    nArray2 = str1.copy ( array2Ptr , 5 , 6  );  // C4996

    cout << "The number of copied characters in array2 is: "

        << nArray2 << endl;

    cout << "The copied characters array2 is: " << array2Ptr << endl;

六、訪問單個字符。可以通過[ ]下標,函數at()及迭代器三種方法來訪問單個字符。

#include <bits/stdc++.h>
using namespace std;
int main()
{   string s1 = "abcdefg";

    //1、數組方式
    cout << "數組方式:" << endl;
    for (int i = 0; i < s1.length(); i++)
        cout <<s1[i] <<endl;
        
    //2、函數方式
    cout << "數組方式:" << endl;
    for (int i = 0; i < s1.length(); i++)
        cout <<s1.at(i) <<endl;    

    //3、迭代方式
    cout << "迭代方式:" << endl;
    for (string::iterator it = s1.begin(); it != s1.end(); it++)
        cout<<*it<< endl;
}

注意:運算符[  ]和at()均返回當前字符串中第n個字符的位置,但at函數提供範圍檢查,當越界時會拋出out_of_range異常,下標運算符[  ]不提供檢查訪問。

 

七、字符串的輸入輸出。>>、 << 、getline()

1、string類重載運算符operator>>用於輸入,同樣重載運算符operator<<用於輸出操作。

2、getline()的原型: getline ( istream &is , string &str , char delim );

其中:

istream &is 表示一個輸入流,譬如cin;

string&str表示把從輸入流讀入的字符串存放在這個字符串中(可以自己隨便命名,str什麼的都可以);

char delim表示遇到這個字符停止讀入,在不設置的情況下系統默認該字符爲'\n',也就是回車換行符(遇到回車停止讀入)。

例如:

string line;
cout<<"please cin a line:";
getline(cin,line,'#');
cout<<"The line you give is:"<<line<<endl;

輸入"You are the #best!" 的時候,輸入流實際上只讀入了"You are the ",#後面的並沒有存放到line中。

程序運行結果應該是這樣的: 

please cin a line:You are the #best!
The line you give is:You are the 

while(getline(cin,line))語句

注意這裏默認回車符停止讀入,按Ctrl+Z或鍵入回車即可退出循環。

在這個語句中,首先getline從標準輸入設備上讀入字符,然後返回給輸入流cin,注意了,是cin,所以while判斷語句的真實判斷對象是cin,也就是判斷當前是否存在有效的輸入流。在這種情況下,我想只要你的電腦不中毒不發神經你的輸入流怎麼會沒有效?所以這種情況下不管你怎麼輸入都跳不出循環,因爲你的輸入流有效,跳不出循環。

然而有些同學誤以爲while判斷語句的判斷對象是line(也就是line是否爲空),然後想通過直接回車(即輸入一個空的line)跳出循環,卻發現怎麼也跳不出循環。這是因爲你的回車只會終止getline()函數的讀入操作。getline()函數終止後又進行while()判斷(即判斷輸入流是否有效,你的輸入流當然有效,滿足條件),所以又運行getline()函數。

所以,以下的寫法根本不可能讓你推出while()循環的:

while(getline(cin,line))    cout<<line<<endl;

二、cin.getline()

此函數會一次讀取多個字符(包括空白字符)。它以指定的地址爲存放第一個讀取的字符的位置,依次向後存放讀取的字符,直到讀滿N-1個,或者遇到指定的結束符爲止。若不指定結束符,則默認結束符爲'\n'。其語法爲:

cin.getline(字符指針(char*),字符個數N(int),結束符(char));

#include <bits/stdc++.h>
using namespace std;
int main()
{char a[30];
 cout << "請輸入一個字符串:" << endl;
 cin.getline(a, 10);//第10位存放字符串結束符'\0'
 for (int i = 0; i<10; i++)
 cout << "第"<<i+1<<"個值爲:"<<a[i] << endl;
 return 0;
}

輸入:1234567890123

輸出:

請輸入一個字符串:
第1個值爲:1
第2個值爲:2
第3個值爲:3
第4個值爲:4
第5個值爲:5
第6個值爲:6
第7個值爲:7
第8個值爲:8
第9個值爲:9
第10個值爲:

 

八、string的搜索操作: 

1、 find()  和  rfind() 函數:  find函數主要是查找一個字符串是否在調用的字符串中出現過,大小寫敏感。

str.find(str2),當str2是str的子串時,返回其在str中第一次出現的位置,否則返回string::npos。

str.find(str2,pos),是從str的pos號位開始查找匹配str2,找到返回其位置;否則返回string::npos。

string::npos是一個常數,其本身的值等於-1,但由於是unsigned int類型,因此,也可以認爲是unsigned int類型的最大值(4294967295)。

rfind()與find()很相似,差別在於查找順序不一樣,find()是從指定位置起向後查找,直到串尾。rfind()是從指定位置起向前查找,直到串首,相當於逆向查找,返回的位置仍然是從前往後數的。

返回值類型 函數 描述
int str.find(char c, int pos = 0); 從pos開始查找字符c在C++字符串str中的位置
int str.find(const char *s, int pos = 0);  從pos開始查找c語言字符串s在C++字符串str中的位置
int str.find(const char *s, int pos, int n); 從pos開始查找c語言字符串s中前n個字符在C++字符串str中的位置
int str.find(const string &s, int pos = 0);  從pos開始查找c++字符串s在C++字符串str中的位置。
int str.rfind(char c, int pos = npos); 從pos開始從後向前查找字符c在C++字符串str中的位置
int str.rfind(const char *s, int pos = npos);   從pos開始從後向前查找c語言字符串s在C++字符串str中的位置
int str.rfind(const char *s, int pos, int n = npos); 從pos開始從後向前查找c語言字符串s中前n個字符在C++字符串str中的位置
int str.rfind(const string &s,int pos = npos); 從pos開始從後向前查找c++字符串s在C++字符串str中的位置。

例一、

#include <bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    string str ("There are two needles in this haystack with needles.");
    string str2 ("needle");

    //在str當中查找第一個出現的needle,找到則返回出現的位置,否則返回結尾
    size_t found = str.find(str2);
    if (found!=string::npos)
    cout << "first 'needle' found at: " << found << '\n';
    //在str當中,從第found+1的位置開始查找參數字符串的前6個字符
    found=str.find("needles are small",found+1,6);
    if (found!=string::npos)
    cout << "second 'needle' found at: " << found << '\n';
    //在str當中查找參數中的字符串
    found=str.find("haystack");
    if (found!=string::npos)
    cout << "'haystack' also found at: " << found << '\n';
    //查找一個字符
    found=str.find('.');
    if (found!=string::npos)
    cout << "Period found at: " << found << '\n';
    //組合使用,把str2用參數表中的字符串代替
    // let's replace the first needle:
    str.replace(str.find(str2),str2.length(),"preposition");
    cout << str << '\n';
    return 0;
}

程序結果:

first 'needle' found at: 14
second 'needle' found at: 44
'haystack' also found at: 30
Period found at: 51
There are two prepositions in this haystack with needles.

例二、

#include <bits/stdc++.h>
using namespace std;
int main()
{//測試find (charT c, size_type pos = 0) const noexcept;
 string st1("babbabab");
 cout <<st1.find('a')<<endl;//1 由原型知,若省略第2個參數,則默認從位置0(即第1個字符)起開始查找
 cout<<st1.find('a',0)<<endl;//1
 cout<<st1.find('a',1)<<endl;//1   
 cout<<st1.find('a',2)<<endl;//4  在st1中,從位置2(包括位置2)開始查找字符a,返回首次匹配的位置,匹配失敗,返回npos
 cout<<st1.rfind('a',7)<<endl;//6  
 cout<<st1.find('c',0)<<endl;//4294967295
 cout<<(st1.find('c',0) == -1)<<endl;//1
 cout<<(st1.find('c',0)==4294967295)<<endl;//1 兩句均輸出1,原因是計算機中-1和4294967295都表示爲32個1(二進制)
 cout<<st1.find('a',100)<<endl;//4294967295  當查找的起始位置超出字符串長度時,按查找失敗處理,返回npos
 
//測試find (const basic_string& str, size_type pos = 0);
 string st2("aabcbcabcbabcc");
 string str1("abc");
 cout<<st2.find(str1,2)<<endl;//6  從st2的位置2開始匹配,返回第一次成功匹配時匹配的串(abc)的首字符在st2中的位置,失敗返回npos

//測試size_type find (const charT* s, size_type pos = 0) ;
 cout << st2.find("abc",2)<<endl; //6   同上,只不過參數不是string而是char*

//測試size_type find (const charT* s, size_type pos, size_type n) ;
 cout<<st2.find("abcdefg",2,3)<<endl;//6   取abcdefg得前3個字符(abc)參與匹配,相當於st2.find("abc",2)
 cout<<st2.find("abcbc",0,5)<<endl;//1  相當於st2.find("abcbc", 0)
 cout<<st2.find("abcbc",0,6)<<endl;//4294967295  第3個參數超出第1個參數的長度時,返回npos
}

例三、

#include <bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    string str ("The sixth sick sheik's sixth sheep's sick.");
    string key ("sixth");//                    ^
    //rfind是找最後一個出現的匹配字符串
    size_t found = str.rfind(key);
    if (found!=string::npos)
    {
        cout<<found<<endl;//輸出23
        str.replace (found,key.length(),"seventh");//找到的sixth替換成seventh
    }
    cout << str << '\n';
    return 0;
}

程序結果:

23
The sixth sick sheik's seventh sheep's sick.

2、find_first_of()和 find_first_not_of()和 函數: 
        在源串中從位置pos起往後查找,只要在源串中遇到一個字符,該字符與目標串中任意一個字符相同,就停止查找,返回該字符在源串中的位置;若匹配失敗,返回npos。

        注意find_first_of函數和find函數的區別,如果是str.find(“abc”)的話,則必須找到完全匹配abc的纔算查找成功,而find_first_of只需要abc中任何一個出現即可。

返回值類型 函數 描述
int str.find_first_of(char c, int pos = 0); 從pos開始查找字符c在C++字符串str中的位置
int str.find_first_of(const char *s, int pos = 0);  從pos開始查找c語言字符串s中任何一個字符首次在C++字符串str中的位置
int str.find_first_of(const char *s, int pos, int n); 從pos開始查找c語言字符串s中前n個字符中任何一個字符首次在C++字符串str中的位置
int str.find_first_of(const string &s,int pos = 0);  從pos開始查找c++字符串s中任何一個字符首次在C++字符串str中的位置。
int str.find_first_not_of(char c, int pos = 0); 從pos開始查找字符c以外的任何一個字符在C++字符串str中的位置
int str.find_first_not_of(const char *s, int pos = 0);   從pos開始c語言字符串s以外的任何一個字符在C++字符串str中的位置
int str.find_first_not_of(const char *s, int pos,int n); 從pos開始查找c語言字符串s中前n個字符以外的任何一個字符在C++字符串str中的位置
int str.find_first_not_of(const string &s,int pos = 0); 從pos開始查找c++字符串s以外的任何一個字符在C++字符串str中的位置。

3、find_last_of()和 find_last_not_of()和 函數: 

在源串中從位置pos起往前查找,只要在源串中遇到一個字符,該字符與目標串中任意一個字符相同,就停止查找,返回該字符在源串中的位置;若匹配失敗,返回npos。find_last_of和find_last_not_of與find_first_of和find_first_not_of相似,只不過是從後向前查找

返回值類型 函數 描述
int str.find_last_of(char c, pos = npos); 從pos開始由後向前查找字符c在C++字符串str中的位置
int str.find_last_of(const char *s, int pos = npos);  從pos開始由後向前查找c語言字符串s中任何一個字符首次在C++字符串str中的位置
int str.find_last_of(const char *s, int pos, int n=npos); 從pos開始由後向前查找c語言字符串s中前n個字符中任何一個字符首次在C++字符串str中的位置
int str.find_last_of(const string &s,int pos = npos);  從pos開始由後向前查找c++字符串s中任何一個字符首次在C++字符串str中的位置。
int str.find_last_not_of(char c, int pos = npos); 從pos開始由後向前從後向前查找字符c以外的任何一個字符在C++字符串str中的位置
int str.find_last_not_of(const char *s, int pos = npos);   從pos開始由後向前從後向前查找c語言字符串s以外的任何一個字符在C++字符串str中的位置
int str.find_last_not_of(const char *s, int pos,int n); 從pos開始由後向前從後向前查找c語言字符串s中前n個字符以外的任何一個字符在C++字符串str中的位置
int str.find_last_not_of(const string &s,int pos = npos); 從pos開始由後向前從後向前查找c++字符串s以外的任何一個字符在C++字符串str中的位置。

九、string的子串substr():

這個函數的作用是取字符串str中位置爲pos開始的len個字符,返回一個字符串。

如果pos開始後len個字符長度超出了字符串的長度,則取到最後一個字符。

返回值類型 函數 描述
string str.substr(int pos = 0,int n = npos) ; 返回pos開始的n個字符組成的字符串給str字符串

假設:string s = “0123456789”;

string sub1 = s.substr(5); //只有一個參數5,  則表示從下標爲5開始一直到結尾:sub1 = “56789”

string sub2 = s.substr(5, 3); //有二個參數(5,3),表示從下標爲5開始截取長度爲3位:sub2 = “567”

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章