C++之字串
C++字串
C中的字串
C語言中不提供字串型別,因此所謂的字串不過是一組以’\0’結尾的字元序列。
C語言中通常以char型的陣列來儲存字串,如下例:
#include <stdio.h>
#include <string.h>
int main()
{
char s[] = "Hello World!";
printf("%s\nLength of s : %d\n Size of s : %d" , s, strlen(s),sizeof(s));
return 0;
}
Hello World!
Length of s : 12
Size of s : 13
上例中,strlen()函式用於求字元陣列長度,而sizeof關鍵字用於求字元陣列佔用的位元組數。可以看出,字串佔用的位元組數比陣列長度大1,這也印證了上面說到的C語言中的字串實際上是以’\0’結尾的字元陣列。
C語言提供了<string.h>來方便程式設計師處理字串,<string.h>中主要包含以下用於字串處理的函式:
函式 | 函式 | 函式 |
---|---|---|
strcpy() | stricmp () | strtec() |
strncpy() | strerror() | strspn() |
strcat() | strcmpi() | strstr() |
strchr() | strncmp() | strtod() |
strcmp() | strncpy() | strtok() |
strnicmp() | strtol() | strlen() |
strnset() | strupr() | strcspn() |
strpbrk() | swab() | strdup() |
strrchr() |
上述函式的具體用法不在此進行描述。
當然,C++仍舊保留了這種C語言的字串操作方式,而<string.h>中的相關內容以C++的表現形式被包含於<cstring>中。為了方便描述,本文後面的內容把C語言下的字串用cstring來表示。
C++中的字串
C++中除了支援C中的字元陣列外,還提供了一個更加強大的string類。但由於string類涉及太多面向物件的內容,這裡只作一些簡單的討論。
字串建立
C++對string的建構函式實現了多個過載,因此有很多不同的方法來定義並初始化一個字串。下面是幾個常用的方式:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1;//建立空串
string s2("Hello World!"); //以cstring作為初值
string s3(s2); //以string作為初值,相當於拷貝
string s4(s2, 5); //取string第5個字元之後的所有字元
string s5("Hello World!", 5); //取cstring的前5個字元
string s6(s2, 6, 5); //取string第6個字元之後的5個字元
string s7("Hello World", 6, 5); //取cstring第6個字元之後的5個字元
cout << "s1 = " << s1 << endl;
cout << "s2 = " << s2 << endl;
cout << "s3 = " << s3 << endl;
cout << "s4 = " << s4 << endl;
cout << "s5 = " << s5 << endl;
cout << "s6 = " << s6 << endl;
cout << "s7 = " << s7 << endl;
return 0;
}
s1 =
s2 = Hello World!
s3 = Hello World!
s4 = World!
s5 = Hello
s6 = World
s7 = World
這裡需要注意的是s4和s5的不同,當分別以string和cstring作為源建立string時,兩種過載的第二個引數意義是不同的,前者為起始位置,後者為字元數。
字元元素存取
C++提供了三種方式對string中的字元進行索引,分別為:
1. 下標索引 [ i ]
2. at( i )訪問
3. back()/front()訪問首字元和末字元。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s("Hello World!");//以cstring作為初值
cout << s[0] << endl;
cout << s.at(0) << endl;
cout << s.front() << endl;
cout << s.back() << endl;
return 0;
}
H
H
H
!
字串賦值
string類過載了“=”操作符,因此可以直接用"="進行賦值,此外,C++還提供了更加靈活的assign()成員函式來對字串進行賦值。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1, s2, s3, s4, s5, s6;
s1 = "Hello World !";//=cstring
s2 = s1; //=string
s3.assign(s1); //assign(string)
s3.assign("Hello World !");//assign(cstring)
s4.assign("Hello World !", 5);//assign(cstring, n)
s5.assign(s1, 5); //assign(string, pos)
s6.assign(12, '-'); //assign(n, char)
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
cout << s4 << endl;
cout << s5 << endl;
cout << s6 << endl;
return 0;
}
Hello World !
Hello World !
Hello World !
Hello
World !
------------
同使用建構函式建立字串時相同,這裡的s4和s5也得到了不同的結果,因此對於ctring和string,assign實現了不同的過載,意義同構造函式。
字串操作
C++提供了許多對字串進行操作的方法,包括增、刪、查詢、替換、交換、屬性獲取等許多方便的功能。下面就幾個常用的方法進行簡要的總結。
1.增刪操作
string過載了”+=操作符",因此可以利用“+=”來增長字串。此外,C++還提供了append()和push_back()來對字串進行增操作,erase()來對字串進行減操作,clear()來對字串進行清空等操作。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Hello World !";
cout << "s = " << s << endl;
s += " I'm";//後面增加字串" I'm"
s.append(" C++");//後面增加字串" C++"
s.push_back('!');//後面增加'!'字元
cout << "s = " << s << endl;
s.erase(5);//刪除第5個字元後的所有字元
cout << "s = " << s << endl;
s.erase(1,3);//刪除第1到3個字元
cout << "s = " << s << endl;
s.clear();//清空字串
cout << "s = " << s << endl;
return 0;
}
s = Hello World !
s = Hello World ! I'm C++!
s = Hello
s = Ho
s =
2.查詢操作
string類提供了一些用於字元查詢和字串查詢的方法,主要有:
find()
rfind()
find_first_of()
find_last_of()
find_first_not_of()
find_last_not_of()
string類對上述6個方法進行了多個過載,可以滿足大多數情況下的要求。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Hello World ! Hello World !";
int pos0 = s.find('l');//查詢字元‘l’的位置
cout << pos0 << endl;
int pos1 = s.find('l', 10);//從下標10開始查詢字元‘l'的位置
cout << pos1 << endl;
int pos2 = s.find("World");//查詢字串"World"的位置
cout << pos2 << endl;
int pos3 = s.find("World", 10);//從下標10開始查詢字串"World"的位置
cout << pos3 << endl;
int pos4 = s.find("World????", 10, 5);//從下標10開始查詢字串"Wordl????"的前五個字元"World"的位置
cout << pos4 << endl;
return 0;
}
2
16
6
20
20
這裡僅給出了find的用法,其餘五個方法的用法類似。
此外,STL中還提供了許多功能強大的查詢功能,同樣可以對字串進行操作,這裡不展開討論。
3.子串操作
string類提供了提取字串的方法substr(),用法如下:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Hello World !";
string s1 = s.substr(); //全部
string s2 = s.substr(6); //從下標6開始的所有字元
string s3 = s.substr(2, 7);//從下標2開始7個字元,不是2到7!
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
return 0;
}
Hello World !
World !
llo Wor
4.屬性操作
string類提供了一些關於屬性操作的方法,較常用的如下:
size() 返回字串大小
length() 返回字串長度,和size()幾乎沒區別
max_size() 可能的最大大小
empty() 判斷字串是否為空
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Hello World !";
cout << s.size() << endl;
cout << s.length() << endl;
cout << s.max_size() << endl;
cout << s.empty() << endl;
return 0;
}
13
13
2147483647
0
字串流
sstream庫中定義了三個類:istringstream、ostringstream和stringstream,分別用來進行字串流的輸入、輸出和輸入輸出操作。
字串流常用於資料轉換和字串的處理,下面分別簡單的介紹一下兩個功能的實現:
1.資料轉換
在C語言中,將float型資料與字元陣列之間的相互轉換可以這樣做:
#include <stdio.h>
int main() {
char s[12];
float ft0 = 32.23,ft1;
sprintf(s, "%f", ft0);//float轉字元陣列
sscanf(s, "%f", &ft1);//字元陣列轉float
for (int i = 0; s[i] != '\0'; ++i) printf("%c ", s[i]);
printf("\n%f\n", ft1);
return 0;
}
當然,在C++中也可以這樣做,但C++中提供的字串流可以提供更強大的功能。下面是一個例子:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
float data, sum=0;
string line = "12.34 23.45 34.56 45.67";
stringstream ss(line);//以string建立字串流
//stringstream ss; ss << line;
while (ss >> data) sum += data;//逐個輸出求和
cout << "sum = " << sum << endl;
return 1;
}
上例中以字串"12.34 23.45 34.56 45.67"建立一個字串流ss,然後依次從字串流ss中讀取資料進行求和,最後輸出求和的結果。
下面再舉一個數據轉換的簡單例子:
void float_to_string(string &s, float ft) {
stringstream ss;
ss << ft;
s=ss.str();
//ss >> s;
}
這個例子通過字串流將float型資料轉換為string,因為不用擔心string的長度問題,所以也就不用擔心是否會溢位。將其他型別轉換為string的做法也是一樣的,通過泛型程式設計可以實現任意資料型別之間的轉換。
2.輸入和輸出
字串流還可以用於輸入與輸出。上面提到,istringstream、ostringstream和stringstream,分別用來進行字串流的輸入、輸出和輸入輸出操作。我們利用stringstream可以很方便的對從標準輸入讀取的資料進行處理。將上面求和的例子稍作修改如下:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
float data, sum = 0;
string line;
stringstream ss;
while (getline(cin, line)) {
ss << line; sum = 0;//流入
while (ss >> data) sum += data;//流出求和
cout << "sum = " << sum << endl;//列印
ss.clear();//清空
}
return 1;
}
上例中,使用string類提供的getline可以從某個輸入流(cin)中讀取一行資料賦值給字串。利用字串流來臨時儲存資料並且進行資料轉換,然後逐個讀出求和。
總結
(1) C++仍然保留了C語言中字元陣列的機制。
(2) C++還提供更加靈活且強大的string類。
(3) string類提供了非常靈活的建立、操作方法。
(4) 字串流可以很方便的用於資料轉換和資料處理。