C++ 提供了以下两种类型的字符串表示形式:
C 风格字符串
C++ 引入的 string 类类型(string class type)
C语言没有提供字符串类型,使用元素类型为char的数组代替,具体而言,字符串一般用一维字符数组来存放,还可以用二维字符数组可以存放多个字符串。
C++ 大大增强了对字符串的支持,除了可以使用C风格的字符串,还可以使用内置的 string 类。string 类处理起字符串来会方便很多,完全可以代替C语言中的字符数组或字符串指针。
一、C 风格字符串
C 风格的字符串起源于 C 语言,并在 C++ 中继续得到支持。字符串实际上是使用 null 字符 '\0' 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。
下面的声明和初始化创建了一个 "Hello" 字符串。由于在数组的末尾存储了空字符,所以字符数组的大小比单词 "Hello" 的字符数多一个。
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
依据数组初始化规则,您可以把上面的语句写成以下语句:
char greeting[] = "Hello";
以下是 C/C++ 中定义的C风格字符串的内存表示示意:
使用C风格字符串时,您不需要把 null 字符放在字符串常量的末尾。C++ 编译器会在初始化数组时,自动把 '\0' 放在字符串的末尾。
输出上面的字符串的代码:
#include
using namespace std;
int main ()
{
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
cout << greeting << endl;
return 0;
}
运行之,参见下图:
C语言没有提供字符串类型,使用元素类型为char的数组代替,具体而言,字符串一般用一维字符数组来存放,还可以用二维字符数组可以存放多个字符串。
字符数组定义的一般格式为:
一维字符数组:char 数组名[整型常量表达式];
二维字符数组:char 数组名[整型常量表达式1][整型常量表达式2];
如: char cA[10],cB[2][15];
字符数组的初始化与赋值与一般数组的很相似,但也有其特殊之处。
一维字符数组的初始化
如下例:
char cA[5]={ ' a', 'b', 'c', 'd', 'e'};
这是最基本的初始化方式。在初始化时要注意数组元素存放的是字符,因此用单引号而不是用双引号,如下面的初始化:
char cA[5]={ " a","b","c","d","e"}; //错误初始化方式
这时每个元素的初值变成了字符串,这显然是错误的。
当字符数组用来存放字符串时,要注意字符串中包含了一个字符串结束标志'\0',这个结束标志也要占用一个单元。其初始化方式有以下几种:
☆用{ }列出初值列表实现。如:
char s1[5]={ 'a', 'b', 'c', 'd', '\0'};
s1中存放的是字符串"abcd"
☆用字符串常量直接初始化。如:
char s1[5]= "abcd";
这种方式初始化时,一定要注意数组的长度和字符串的长度的关系:字符串长度不包含结束符'\0',数组长度要把结束符算在其内,因此数组的长度要大于字符串的长度。如下面的操作是错误的:
char s1[5]= "abcde"; /*数组的空间不够存放字符串*/
☆ 省略数组的大小,进行初始化。这是根据初值中字符的个数确定数组的长度。如:
char s2[]="hello";
它等价于 char s2[6]= "hello";
赋值
与一般数组赋值相同,不能将一个字符串直接赋值给一个数组名,只能对字符数组的元素逐个赋值。如:
char sC[6];
要给它赋值为"hello",只能如下方式:
sC[0]= 'h',sC[1]= 'e',sC[2]= 'l',sC[3]= 'l',sC[4]= 'o',sC[5]= '\0';
而不能是:sC="hello";
也不能是:sC[6]= "hello";
注意:C/C++语言中,无论是字符数组还是数值型数组在程序中只能给它的元素赋值。
字符数组的输入输出
其它类型的数组元素在输入输出时,只能逐个元素实现输入输出,但用字符数组来存放字符串时,可以进行整体的输入输出,当然也可以使用循环将字符数组中的字符一个一个处理输入输出。
一维字符数组的输入输出
例、元素类型为char的数组输入输出例
#include
using namespace std;
int main ()
{
char s[10];
cout << "请输入字符串:" ;
cin >>s; //scanf(" %s",s);
cout << "字符串是:" << s << endl; // printf("符串是是: %s ",s);
return 0;
}
运行之,参见下图:
C风格字符串将字符串放在字符数组中,并以空字符'\0'结束,一般利用指针来操作这些字符串。尽管C++支持C风格字符串,但建议在C++程序中尽量不要使用它们。一些用于操作C风格字符串的标准库函数定义在cstring头文件中,是C语言头文件string.h的C++版本。
1)字符串复制函数:
char *strcpy(char *s,const char ct)
返回值是指向复制后字符串中首字符的指针。。
例子
#include
//#include
#include
using namespace std;
int main ()
{
char str[] = "just test";
char des[20];
//cout << strcpy(des, str)<< endl; //本句和下面两句效果相同,但下面两句更直观说明 strcpy()的含义
strcpy(des, str);
cout << des<< endl;
return 0;
}
运行,参见下图:
2)字符串连接函数:char *strcat(char *s,const char *ct)
将串ct复制到串s的后面,形成一个长串。例如:
#include
//#include
#include
using namespace std;
int main ()
{
char str1[]="李小明";
char str2[]="是大学生";
//cout << strcat(str1,str2)<< endl; //本句和下面两句效果相同
strcat(str1,str2);
cout < return 0; } 运行,参见下图: 3)字符串比较函数:int strcmp(const char *cs,const char ct)。 两字符串比较是按字典排序方法进行。两个字符串从第一个字符比较起,如果相同,则比较第二个字符,依此类推,直到不同。哪个字符串对应的字符的ASCII码值大,串就大。如果两串直到结束符都相同,则一样大。若两个字符串相等,则返回0;串cs大,则返回正整数;串ct大,则返回负整数。 例 #include //#include #include using namespace std; int main () { char strA[] = "Hello world"; char strB[] = "Hello, world"; cout << strcmp(strA, strB)<< endl; return 0; } 运行,参见下图: 4)求字符串长度函数:int strlen(const char *s) 这里求出的串长度不包含串结束符在内。而sizeof运算符包括结束符,还包括没有使用的单元。 #include //#include #include using namespace std; int main () { char str[] = "Hello world"; cout << strlen(str) << endl; return 0; } 运行,参见下图: 现在简要介绍二维字符数组 二维字符数组的初始化 与其它二维数组初始化一样,有以下几种方式: ☆用初值列表方式。如: char s3[2][4]={{ ' a', 'b', 'c', '\0'},{' m', 'n', 'l', '\0'}}; ☆用字符串常量方式。如: char s3[2][4]={ " abc"," mnl"}; ☆省略第一维大小的方式来初始化。如: char s3[][4]={{ ' a', 'b', 'c', '\0'},{' m', 'n', 'l', '\0'}}; 或 char s3[][4]={ " abc","mnl"}; 根据分行赋值的大括号{}的个数或常量字符串的个数确定第一维的大小为2。 二维字符数组的输入输出 二维字符数组的每一行可以用来存放一个字符串,因此可以将二维字符数组看成是一个一维数组,数组中的元素为字符串,即被看作是字符串数组。如: char ss[3][10]; 数组ss可以被看作是用来存放3个字符串的字符串数组,每个字符串的长度不超过9。这时,对数组中字符串的引用,只使用第一个下标。即: ss[0]:表示第一个字符串的首地址; ss[1]:表示第二个字符串的首地址; ss[2]:表示第三个字符串的首地址; 元素类型为char的二维数组输入输出例: #include using namespace std; int main () { char ss[3][10]; int i; for(i=0;i<3;i++) { cout << "请输入字符串:" ; cin >>ss[i]; //scanf(" %s",ss[i]); } for(i=0;i<3;i++) cout << "字符串" << i + 1 << "是:"<< ss[i] << endl; // printf("字符串%d是:%s ",,i+1,ss[i]); return 0; } 运行,参见下图: 二、C++ 中的 String 类 使用 string 类需要包含头文件 C++ 标准库提供了 string 类类型(string class type),支持上述所有的操作,另外还增加了其他更多的功能。我们将学习 C++ 标准库中的这个类,现在让我们先来看看下面这个实例: 现在您可能还无法透彻地理解这个实例,因为到目前为止我们还没有讨论类和对象。所以现在您可以只是粗略地看下这个实例,等理解了面向对象的概念之后再回头来理解这个实例。 例 #include #include using namespace std; int main () { string str1 = "Hello"; string str2 = "World"; string str3; int len ; // 复制 str1 到 str3 str3 = str1; cout << "str3 : " << str3 << endl; // 连接 str1 和 str2 str3 = str1 + str2; cout << "str1 + str2 : " << str3 << endl; // 连接后,str3 的总长度 len = str3.size(); cout << "str3.size() : " << len << endl; return 0; } 运行之,参见下图: 定义 string 变量(对象)的方法: string s1; string s2 = "c plus plus"; string s3 = s2; string s4 (5, 's'); 变量 s1 只是定义但没有初始化,编译器会将默认值赋给 s1,默认值是"",也即空字符串。 变量 s2 在定义的同时被初始化为"c plus plus"。与C风格的字符串不同,string 的结尾没有结束标志'\0'。 变量 s3 在定义的时候直接用 s2 进行初始化,因此 s3 的内容也是"c plus plus"。string 变量也可以用C风格的字符串进行赋值。 变量 s4 被初始化为由 5 个's'字符组成的字符串,也就是"sssss"。 当我们需要知道字符串长度时,可以调用 string 类提供的 length() 函数。如 string s = "http://c.biancheng.net"; int len = s.length(); //结果为22。string 的末尾没有'\0'字符,所以 length() 返回的是字符串的真实长度,而不是长度 +1。 string 类为我们提供了一个转换函数 c_str(),该函数能够将 string 字符串转换为C风格的字符串,并返回该字符串的 const 指针(const char*)。例如 string path = "D:\\demo.txt"; path.c_str() string 字符串的输入输出 string 类重载了输入输出运算符,可以像对待普通变量那样对待 string 变量,也就是用>>进行输入,用<<进行输出。例: #include #include using namespace std; int main(){ string s; cin>>s; //输入字符串 cout< return 0; } 下面介绍字符串的常见操作。 ☆访问字符串中的字符的例: #include #include using namespace std; int main(){ string s = "abcDEF1234"; for(int i=0,len=s.length(); i cout< } cout< s[4] = '6'; cout< return 0; } 运行之,参见下图: ☆字符串的拼接 有了 string 类,我们可以使用+或+=运算符来直接拼接字符串,非常方便,就不需要使用C语言中的 strcat()、strcpy()、malloc() 等函数来拼接字符串了,不用担心空间不够会溢出问题了。 可以用+运算符来拼接字符串时,运算符的两边可以都是 string 字符串,也可以是一个 string 字符串和一个C风格的字符串,还可以是一个 string 字符串和一个字符数组,或者是一个 string 字符串和一个单独的字符。例: #include #include using namespace std; int main(){ string s1 = "Hello "; string s2 = "World"; char s3[] = "世界"; string s5 = s1 + s2; string s6 = s1 + s3; cout< return 0; } 运行输出如下: ☆string 字符串的增删改查 C++ 提供的 string 类包含了若干实用的成员函数,大大方便了字符串的插入、删除、更改、查询等操作。 插入子字符串函数 insert (size_t pos, const string& str); pos 表示要插入的位置,也就是下标;str 表示要插入的字符串,它可以是 string 字符串,也可以是C风格的字符串。 删除子字符串函数 erase (size_t pos = 0, size_t len = npos); pos 表示要删除的子字符串的起始下标,len 表示要删除子字符串的长度。如果不指明 len 的话,那么直接删除从 pos 到字符串结束处的所有字符(此时 len = str.length - pos)。 提取子字符串函数 substr (size_t pos = 0, size_t len = npos); pos 为要提取的子字符串的起始下标,len 为要提取的子字符串的长度。 字符串插入、删除、提取子字符串的例 #include #include using namespace std; int main(){ string s1, s2, s3, s4, s5; s1 ="1234567890"; s2 = "aaa"; s1.insert(5, s2); //插入字符串 cout<< s1 < s3 ="1234567890"; s3.erase(8); //删除字符串 cout<< s3 < s4 ="1234567890"; s5 = s4.substr(4, 3); //提取子字符串 cout<< s5 < return 0; } 运行输出如下: 字符串查找 string 类提供了几个与字符串查找有关的函数:find() 函数、rfind() 函数、find_first_of() 函数 在此仅介绍find() 函数,其它可上网查阅。 find()函数两种原型为: find (const string& str, size_t pos = 0) find (const char* s, size_t pos = 0) 第一个参数为待查找的子字符串,它可以是 string 字符串,也可以是C风格的字符串。第二个参数为开始查找的位置(下标);如果不指明,则从第0个字符开始查找。 find()函数的例子 #include #include using namespace std; int main(){ string s1 = "first second third"; string s2 = "second"; int index = s1.find(s2,5); if(index < s1.length()) cout<<"Found at index : "<< index < else