在C语言中是使用字符型数组来存放字符串,C++程序也仍然可以沿用这种方法。不仅如此,C++库中还预定义了string类。
1.用字符数组存储和处理字符串
字符串常量是用一对双引号括起来的字符序列。例如"abcd","China"都是字符串常量。
字符串常量在内存中的存放形式:是按串中字符的排列次序顺序存放的,每一个字符占一个字节,并在末尾添加’\0’作为结尾标记。这实际上是一个隐含创建的类型为char的数组。一个字符串常量就表示这样一个数组的首地址。因此,可以把字符串常量赋给字符串指针,由于常量值不能修改,应将字符串常量赋值给指向常量的指针,例如:
const char*string1="This is a srting.";
这时可以直接对string1进行输出,例如:
cout<<string1;
字符串变量也可以用类似方式来表示。如果创建一个char数组,每个元素存放字符串的一个字符,在末尾放置一个’\0’,便构成了C++字符串。它的存储方式与字符串常量一样,但是由于它是程序员创建的数组,因此可以改写其内容,所以这就是字符串变量而非常量了。
这时要注意,用于存放字符串的数组其元素个数应该不小于字符串的长度(字符个数)加1。对字符数组进行初始化赋值时,初值的形式可以是以逗号分隔的ASCII码或者字符常量,也可以是整体的字符串常量(这时末尾’\0’是隐含的)。下面列出的语句都可以创建一个初值为"program"的字符串变量,3种写法是等价的:
char str[8]={'p','r','o','g','r','a','m','\0'};
char str[8]="program";
char str[]="program";
内存中数组str的内容如下:
尽管对用字符数组表示的字符串进行初始化比较容易、直观,但进行许多其他字符串操作时却比较麻烦。执行很多字符串操作需要借助cstring头文件中的字符串处理函数。例如,strcpy函数,strcmp函数,strcat函数。另外,当字符串长度很不确定时,需要用new来动态创建字符串数组,最后用delete释放。C++对这些繁琐的操作进行了封装,形成了string类,可以更加方便地操作字符串。
2. string类
C++标准库将面向对象的串的概念加入到C++语言中,预定了字符串类(string类)。string类提供了对字符串进行处理所需要的操作。使用string类需要包含头文件string。string封装了串的属性并提供了一系列允许访问这些属性的函数。
严格地说,string并非一个独立的类,而是类模板basic_string的一个特化实例。不过对于string的使用者来说,它的特点与一个类无异,因此可以把它当作一个类来看待。
(1)string类的构造函数原型
string();//默认构造函数,建立一个长度为0的串
string(const string &rhs);//拷贝构造函数
//将对象rhs中的串从位置pos开始取n个字符,用来初始化string类的对象
//注意:串中的第一个字符的位置是0
string(const string&rhs,unsigned int pos,unsigned int n);
//用指针s所指向的字符串中的前n个字符初始化string类的对象
string(const char*s,unsigned int n);
//将参数c中的字符重复n次,用来初始化string类的对象
由于string类具有接收const char*
类型的构造函数,因此字符串常量和用字符串数组表示的字符串变量都可以隐含地转换为string对象。例如,可以直接使用字符串常量对string对象进行初始化:
string str="Hello World!";
(2)string类的操作符
string类提供了丰富的操作符,可以方便地完成字符串赋值(内容复制)、字符串连接、字符串比较等功能。
下表具体列出了string类的操作符及说明:
之所以能够通过上面的操作符来操作string对象,是因为string类对这些操作符进行了重载。
这里所说的对两个串的大小进行比较,是依据字典顺序的比较。
设有两个字符串s1和s2,二者大小比较的规则如下:
①如果s1和s2长度相同,且所有字符完全相同,则s1=s2。
②如果s1和s2所有字符不完全相同,则比较第一对不相同字符的ASCII码,较小字符所在的串为较小的串。
③如果s1的长度n1小于s2的长度n2,且两个字符串的前n1个字符完全相同,则s1<s2。
(3)常用成员函数
string类的成员函数有很多,每个函数都有许多重载形式。在下面的函数说明中,将成员函数所属的对象称为“本对象”,其中存放的字符串称为“本字符串”。
//将字符串s添加在本串尾:
string append(const char*s);
//赋值,将s所指向的字符串赋值给本对象
string assign(const char*s);
//比较本串与str中串的大小,
//当本串<str串时返回负数;
//当本串>str串时返回正数;
//两串相等时,返回0
int compare(const string&str)const;
//将s所指的字符串插入在本串中位置p0之前
string &insert(unsigned int p0,const char*s);
//取子串,取本串中位置从pos开始的n个字符,构成新的string类对象作为返回值
string substr(unsigned int pos,unsigned int n)const;
//查找并返回str在本串中第一次出现的位置
unsigned int find(const basic_string &str)const;
//返回串的长度(字符个数)
unsigned int length()const;
//将本串与str中的字符串进行交换
viod swap(string&str);
【例】string类应用举例
#include<iostream>
#include<string>
using namespace std;
//根据value的值输出true或false,title为提示文字
inline void test(const char*title,bool value)
{
cout << title << "returns " << (value ? "true" : "false") << endl;
}
int main()
{
string s1 = "DEF";
cout << "s1为:" << s1 << endl;
string s2;
cout << "请输入s2:";
cin >> s2;
cout << "s2的长度为:" << s2.length() << endl;
//比较运算符的测试
test("s1<=\"ABC\" ", s1 <= "ABC");
test("\"DEF\"<=s1 ", "DEF" <= s1);
//连接运算符测试
s2 += s1;
cout << "s2=s2+s1:" << s2 << endl;
cout << "s2的长度为:" << s2.length() << endl;
return 0;
return 0;
}
运行结果:
上面的例子中使用cin的“>>”操作符从键盘输入字符串,以这种方式输入时,空格会被当作输入的分隔符。例如,如果从键盘输入字符串“123 ABC”,那么被读入的字符串实际上是“123”,“ABC”将在下一次从键盘输入字符串时被读入。例如,在上述代码运行结束时从键盘输入123 ABC
,结果如下图所示:
如果希望从键盘读入字符串,直到行末为止,不以中间的空格作为输入的分隔符,可以使用头文件string中定义的getline。例如,如果将上述代码中输入s2的语句 cin >> s2;
改写为getline(cin,s2);
,这时,如果从键盘输入字符串123 ABC
,那么整个字符串都会被赋给s2,结果如下图所示:
这实际表示输入字符串时只以换行符作为分隔符。getline还允许在输入字符串时增加其他分隔符,使用方法是把可以作为分隔符的字符作为第3个参数传递给getline。例如,如果在代码中将cout<<s2;
改写为getline(cin,s2,',');
,使用这个语句,可以把逗号作为分隔符,结果如下图所示:
从结果可以看出,在从键盘输入字符串的时候,不读入分隔符后边的字符串内容,只读入作为分隔符的字符前面的字符串。
【例】用getline输入字符串
#include<iostream>
#include<string>
using namespace std;
int main()
{
for (int i = 0; i < 2; i++)
{
string str1, str2;
getline(cin, str1, ',');
getline(cin, str2);
cout << "str1:" << str1 << " str2" << str2 << endl;
}
return 0;
}
运行结果: