技術(shù)交流QQ群:1027579432,歡迎你的加入!
1.Cpp中的字符串
- C++提供了以下兩種類型的字符串表示形式:
- C風(fēng)格字符串
- C++引入的string類類型
1.1 C風(fēng)格字符串
- C風(fēng)格的字符串起源于C語言,并在C++中繼續(xù)得到支持。字符串實際上是使用null字符'\0'終止的一維字符數(shù)組。因此,一個以null結(jié)尾的字符串,包含了組成字符串的字符。
- 下面的聲明和初始化創(chuàng)建了一個"Hello"字符串。由于在數(shù)組的末尾存儲了空字符,所以字符數(shù)組的大小比單詞"Hello"的字符數(shù)多一個。
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; - 依據(jù)數(shù)組初始化規(guī)則,可以把上面的語句寫成以下語句:
char greeting[] = {'H', 'e', 'l', 'l', 'o', '\0'}; -
以下是C/C++中定義的字符串的內(nèi)存表示:
字符串的在內(nèi)存中的表示.png - 其實,不需要把null字符放在字符串常量的末尾。C++編譯器會在初始化數(shù)組時,自動把'\0'放在字符串的末尾,如下面的例子:
#include "iostream" using namespace std; int main(){ char greeting[6] = {'H', 'e', 'l', 'l', 'o'}; cout << "greeting: " << greeting << endl; return 0; } -
C++中有大量的函數(shù)用來操作以null結(jié)尾的字符串,見下表:
常見字符串函數(shù).png// 字符串中的常見函數(shù): char str1[11] = "hello"; char str2[11] = "world"; char str3[11]; int len, result; // 復(fù)制str1到str3 strcpy(str3, str1); cout << "strcpy(str1, str3):" << str3 << endl; // 連接str1和str2 strcat(str1, str2); cout << "strcat(str1, str2):" << str1 << endl; // 連接后,str1的總長度 len = strlen(str1); cout << "strlen(str1):" << len << endl; // str1與str2比較 result = strcmp(str1, str2); cout << "strcmp(str1, str2):" << result << endl;
1.2 C++中的字符串
- C++標(biāo)準庫提供了string類類型,支持上述所有的操作,另外還增加了其他更多的功能,見下面的實例:
#include "string" // Cpp中的字符串 string s1 = "abandon"; string s2 = "banana"; string s3; // 復(fù)制s1到s3 s3 = s1; cout << "s3:" << s3 << endl; // 連接s1和s2 s3 = s1 + s2; cout << "s1 + s2:" << s3 << endl; // 連接后的s3總長度 int len1, result1; len1 = s3.size(); cout << "s3.size():" << len1 << endl; // 比較s1和s2 result1 = s1 > s2; cout << "s1 > s2:" << result1 << endl;
2.字符串中的細節(jié)知識
- string類提供了一系列針對字符串的操作,比如:
- append() -- 在字符串的末尾添加字符
- find() -- 在字符串中查找字符串
- insert() -- 插入字符
- length() -- 返回字符串的長度
- replace() -- 替換字符串
- substr() -- 返回某個子字符串
// 4 string類中的其他函數(shù) string name = "Curry"; cout << "The length of string is:" << name.length() << endl; // 拼接 name.append("Coder"); cout << "name:" << name << endl; // 刪除 int pos; pos = name.find("Coder"); // 查找Coder在字符串中的位置 cout << "pos = " << pos << endl; name.replace(pos, 4, ""); // 從位置pos開始,后面的連續(xù)4個字符都將被替換為空格 cout << "name = " << name << endl; // 找子串 int first = name.find_first_of("r"); // 從頭找到字符r的位置 int last = name.find_last_of("r"); // 從尾部找字符的位置 cout << name.substr(first + 1, last - first -1) << endl; // 提取兩個r之間的字符子串 - C++中輸入的方式很多,下面介紹與C語言中g(shù)etchar()類似的函數(shù)cin.getline()函數(shù),cin.getline()是在輸入一段字符完成后開始讀取數(shù)據(jù)(注意,是輸入完成后,以Enter為結(jié)束標(biāo)志)
// 5 cin.getline()函數(shù) char X[N]; cin.getline(X,N); int a = 0, b = 0; for (int i=0; i < N;i++){ if (X[i] == '#') // #是結(jié)尾標(biāo)志 break; if (X[i] >= '0' && X[i] <= '9') // 統(tǒng)計數(shù)字個數(shù) a++; if ((X[i] >= 'a' && X[i] <= 'z') || (X[i] >= 'A' && X[i] <= 'Z')) // 統(tǒng)計字母個數(shù) b++; } cout << "a = " << a << " b = " << b << endl; - 字符串與vector
- 字符串常量與標(biāo)準庫string不是同一種類型
string s("hello"); cout << "s.size() = " << s.size() << endl; // 正確 // cout << "hello".size() << endl; 錯誤 cout << s + "world" << endl; // 正確 // cout << "hello" + "world" << endl; 錯誤 -
strlen、sizeof與size()求字符串長度的區(qū)別:
cout << strlen("123") << endl; //返回 3 cout << sizeof("123") << endl; //返回 4 string s = "123"; cout << s.size() << endl; //返回 3 -
sizeof和strlen區(qū)分:
- sizeof操作符的結(jié)果類型是size_t,它在頭文件中typedef為unsigned int類型。該類型保證能容納實現(xiàn)所建立的最大對象的字節(jié)大小。
- sizeof是運算符,strlen是函數(shù)
- sizeof可以用類型做參數(shù),如sizeof(int),strlen只能用char*做參數(shù),且必須是以'\0'結(jié)尾的。sizeof還可以用函數(shù)做參數(shù),如short f(); cout << sizeof(f());
- 數(shù)組做sizeof的參數(shù)不退化,傳遞給strlen就退化為指針了
- 大部分編譯程序在編譯的時候就把sizeof計算過了,是類型或是變量的長度,這就是 sizeof(x)可以用來定義數(shù)組維數(shù)的原因。
char str[20] = "0123456789"; int a = strlen(str); 10 int b = sizeof(str); 20 - strlen的結(jié)果要在運行的時候才能計算出來,是用來計算字符串的長度,不是類型占內(nèi)存的大小
- sizeof后如果是類型必須加括弧,如果是變量名可以不加括弧。這是因為sizeof是個操作符不是個函數(shù)
- 當(dāng)適用一個結(jié)構(gòu)類型或變量時,sizeof返回實際的大?。划?dāng)適用一靜態(tài)地空間數(shù)組,sizeof 返回全部數(shù)組的尺寸;sizeof操作符不能返回動態(tài)地被分派了的數(shù)組或外部的數(shù)組的尺寸。
- 字符數(shù)組可以用數(shù)組名來輸出數(shù)組內(nèi)容,而普通數(shù)組不行
- 原因:因為char型數(shù)組中的每一個元素都是1個字節(jié),所以每一個字符之間的地址都是+1的,是連續(xù)的。所以當(dāng)cou 輸出時讀到字符數(shù)組中的 '\0'便停止輸出; 而int數(shù)組每個元素占4個字節(jié),所以數(shù)組中每個元素地址的間隔是4,但其實它也是連續(xù)的,出現(xiàn)亂碼是因沒找到結(jié)束符。
int aa[10] = {1, 2, 3, 4, 6, 7}; char bb[6] = {'h', 'a', 'a', 'p', 'y', '\0'}; char cc[] = "happy"; cout << aa << endl; cout << bb << endl; cout << cc << endl;
- 原因:因為char型數(shù)組中的每一個元素都是1個字節(jié),所以每一個字符之間的地址都是+1的,是連續(xù)的。所以當(dāng)cou 輸出時讀到字符數(shù)組中的 '\0'便停止輸出; 而int數(shù)組每個元素占4個字節(jié),所以數(shù)組中每個元素地址的間隔是4,但其實它也是連續(xù)的,出現(xiàn)亂碼是因沒找到結(jié)束符。
- 字符串常量與標(biāo)準庫string不是同一種類型
- char數(shù)組的幾種表示方法
- C風(fēng)格
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; char greeting[] = {'H', 'e', 'l', 'l', 'o', '\0'}; - C++風(fēng)格
- string類
- char*:指向字符串的指針,指向字符串的首個字母
- const char*(常量指針):指向的是一個const char類型,不能通過當(dāng)前的指針對字符串的內(nèi)容作修改
- char * const(指針常量):指針是一個常量,不能修改指針
- char []:與char*有很多的相同點,代表字符數(shù)組,可以對應(yīng)一個字符串;如char * a = "string1"; char b[] = "string2"; a是一個指向char類型的字符串的指針;b是一個字符數(shù)組
- char *與char[]的不同:a是變量,指向可以改變;b是常量,是該字符數(shù)組的首地址,其值不能改變
- C風(fēng)格
3.注意的地方1
#include <iostream>
using namespace std;
int main(){
// str1與str2是兩個字符串?dāng)?shù)組,我們會為它們分配長度為12字節(jié)的空間,因為是兩個初始地址不同的數(shù)組,故str1!=str2
char str1[] = "hello world";
char str2[] = "hello world";
if(str1 == str2)
cout << "str1與str2相同\n";
else
cout << "str1與str2不同\n";
// str3 與 str4是兩個指針,無須為它們分配內(nèi)存來存儲字符串的內(nèi)容,只需要把它們指向"hello world"在內(nèi)存中的地址就可以了。
// 由于"hello world"是字符串常量,它在內(nèi)存中只有一個拷貝,因此str3與str4指向同一個地址
char *str3 = "hello world";
char *str4 = "hello world";
if(str3 == str4)
cout << "str3與str4相同\n";
else
cout << "str3與str4不同\n";
return 0;
}
4.注意的地方2
#include <iostream>
#include <cstring>
using namespace std;
// 數(shù)組中注意的點
int GetSize(char *data){
return sizeof(data);
}
int GetSize1(char data[]){
return sizeof(data);
}
int GetSize2(int* data){
return sizeof(data);
}
int GetSize3(int data[]){
return sizeof(data);
}
int main(){
char* ch1 = "abcdefghijk";
int size11 = sizeof(ch1);
char* ch11 = ch1;
int size12 = sizeof(ch11);
int size13 = GetSize(ch1);
int size14 = GetSize1(ch1);
/*---------------------------------------------------------------*/
char ch2[] = "abcdefghijk";
int size21 = sizeof(ch2);
char* ch21 = ch2;
int size22 = sizeof(ch21);
int size23 = GetSize(ch2);
int size24 = GetSize1(ch2);
/*---------------------------------------------------------------*/
int data[] = {1, 2, 3, 4, 5};
int size31 = sizeof(data);
int* data11 = data;
int size32 = sizeof(data11);
int size33 = GetSize2(data);
int size34 = GetSize3(data);
/*---------------------------------------------------------------*/
cout << "size11 = " << size11 << endl;
cout << "size12 = " << size12 << endl;
cout << "size13 = " << size13 << endl;
cout << "size14 = " << size14 << endl;
/*---------------------------------------------------------------*/
cout << "size21 = " << size21 << endl;
cout << "size22 = " << size22 << endl;
cout << "size23 = " << size23 << endl;
cout << "size24 = " << size24 << endl;
/*---------------------------------------------------------------*/
cout << "size31 = " << size31 << endl;
cout << "size32 = " << size32 << endl;
cout << "size33 = " << size33 << endl;
cout << "size34 = " << size34 << endl;
return 0;
}

