标准库类型string 表示可变长的字符序列,使用string 类型必须首先包含string 头文件。
本节描述最常用的string 操作,9.5 节还将介绍另外一些。
3.2.1 定义和初始化string 对象
【如何初始化类的对象是由类本身决定的。
string s1 // 默认初始化,s1 是一个空串
string s2(s1) // s2 是s1 的副本
string s2 = s1 // 等价于上一条语句
string s3("value") // s3 是字面值的副本,不包含该字面值末尾表示结束的空字符
string s3 = "value" // 等价于上一条语句
string s4(n, 'c') // 把s4 初始化为由连续n 个字符c 组成的串
注意将字符串字面值赋值给string 对象时,字符串末尾的空字符不拷贝。
使用等号进行初始化,实际上执行的是拷贝初始化;
不使用等号进行初始化,执行的则是直接初始化。】
3.2.2 string 对象上的操作
【一个类除了要规定初始化其对象的方式外,还要定义对象上所能执行的操作。
类既能定义通过函数名调用的操作,也能定义各种运算符在该类对象上的新含义。】
【读写string 对象:
在执行 cin >> s 的操作时,string 对象会自动忽略开头的空白(空格符、换行符、制表符等)并从第一个真正的字符开始读起,直到下一处空白为止(不读取该空白)。】
【使用getline 读取一整行:getline(cin, line)
若希望保留输入流中的空白符,则该用getline 操作。
getline 函数的参数是一个输入流和一个string 对象,函数读入数据,直到遇到换行符为止,读取该换行符,却不在string 对象中存入该换行符(注意读取与存入的差异),触发getline 函数返回的那个换行符实际上被丢弃掉了,得到的string 对象中并不包含该换行符。】
{使用endl 可结束当前行并刷新显示缓冲区}
【string 的empty 和size 操作:empty 和size 均为string 类的成员函数
s.empty() 函数根据string 对象s 是否为空返回一个对应的布尔值。
s.size() 函数返回string 对象的长度,返回值类型为string::size_type 类型。(string 类及其他大多数标准库类型都定义了几种配套的类型,这些配套类型体现了标准库类型与机器无关的特性。)
string::size_type 是一个无符号类型的值且能足够存放下任何string 对象的大小。
如果在表达式中混用了带符号数和无符号数,可能导致带符号数类型转换成无符号数,并因此引发不期望的后果。比如在比较负的带符号数与无符号数时,负的带符号数会自动的转换成一个比较大的无符号数。】
【比较string 对象:
string 类定义了几种用于比较字符串的运算符,这些运算符均对大小写敏感。
相等性运算符(== 和 != )分别检验两个string 对象是否长度相同且是否包含的字符依次全都相同。
关系运算符(<, >, <=, >=)检验对象的规则如下:
如果两个string 对象在有字符的位置上的字符都依次相同,但长短不一,就说短者小于长者;
如果两个string 对象在有字符的位置上存在某些字符不一致,则比较的结果依第一对相异字符的(大小写敏感)字典顺序决定。】
【string 对象的加法运算:
两个string 对象相加得到一个新的string 对象,其内容是把左侧的运算对象与右侧的运算对象串接而成的新string 对象。
字面值与string 对象相加时,规则与两个string 对象相加相同,因为标准库允许在需要的时候将字符字面值和字符串字面值转换成string 对象。(当语句中有该种情形,必须保证每个+ 运算符两侧至少一侧是string 对象,因为c++ 没有定义两个字符串字面值的加法运算。)
】
3.2.2 处理string 对象中的字符(新标准)
{3.2.1 中介绍了将string 对象作为整体进行的一系列常用操作,本节将介绍单独处理string 对象的字符的操作方法。}
【cctype 头文件中定义的对单个字符进行判断或操作的函数:
isalnum(c) // 当c 是字母或数字时为真
isalpha(c) // 字母
islower(c) // 小写字母
isupper(c) // 大写字母
isdigit(c) // 数字
isxdigit(c) // 十六进制数字
ispunct(c) // 标点符号(不是控制字符、数字、字母、可打印空白)
iscntrl(c) // 控制字符
isprint(c) // 可打印字符(空格或具有可视形式)
isgraph(c) // 不是空格但可打印
isspace(c) // 空白符(空格、横纵制表、回车、换行、进纸里的一种)
tolower(c) // 若为大写字母,输出小写字母;否则原样输出
toupper(c) // 与上条相反
】
【基于范围的for 语句(c++ 新标准):
这种语句遍历给定序列中的每个元素并对序列中的每个值执行某种操作,形式如下
for (declaration : expression)
expression 部分是一个对象,表示一个序列;declaration 部分负责定义一个变量,每次迭代,该变量会被初始化为expression 部分的下一个元素值。
如果在基于范围的for 语句中确实改变了序列对象中的元素,则必须把循环变量定义成引用类型。
string s("Hello World!!!"); // 转换成全大写
for (auto &c : s)
c = toupper(c);
cout << s << endl; // 输出结果是HELLO WORLD!!!
】
【要处理string 对象中的单个字符有两种形式:一种是使用下标、另一种是使用迭代器(3.4 节和第9 章)
使用下标运算符[ ] 和for 语句:
下标运算符接收的是string::size_type 类型的值;string 对象的下标从0 计起,s[s.size() - 1] 是最后一个字符,能使用的有效string 的下标范围与其当前长度是对应的。
string s("abc");
// s[4] = 'd'; 报错,outrange
s[3] = 'd'; // 不报错
cout << s.size(); // 输出为3,可见第三行语句并没有改变s 的长度
cout << s; // 输出为"abc",可见string 输出时依长度输出
下标的值称为“下标”或“索引”,任何一个表达式只要它的值是一个整型值就能作为索引,不过如果索引是带符号类型将会自动转换成由string::size_type 表示的无符号类型。】