标准库类型string表示可变长的字符序列,使用string类型必须首先包含string头文件。作为标准库中的一部分,string定义在命名空间std中。
C++标准一方面对库的类型所提供的操作做了详细的规定,另一方面也对库的实现者做出一些性能上的需求。因此,标准库类型对于一般应用场合来说有足够的效率。
定义和初始化string对象:下面是常见的一些方式:
string s1;
string s2=s1;//s2是s1的副本
string s3=“hiya”;s3是字符串字面值的副本
string s4(10,‘c’);s4的内容是:10个c
string s1 | 默认初始化 |
string s2(s1) | s2是s1的副本 |
string s3(“value”) | s3是value的副本 |
string s4(n,'c') | 连续n个c字符 |
直接初始化和拷贝初始化:
C++有几种不同的初始化方式,通过string我们可以清楚地看到在这些初始化方式之间到底有什么区别和联系。
如果使用等号(=)初始化一个变量,实际上执行的就是拷贝初始化,与之相反如果不使用等号(=)就是直接初始化。
string对象上的操作:
一个类除了要规定初始化其对象的方式外,还要定义对象上所能执行的操作。其中,类即能定义通过函数名调用的操作,就像sales_item类的isbn函数那样,也能定义<<,++等各种运算符在该类对象上的新含义。
string的操作:
os<<s | 将s写到os当中,返回os |
is>>s | 从is中读取字符串赋给s,返回is |
s.empty() | s为空返回true |
s.size() | 返回s中字符的个数 |
s[n] | 返回s中第n个字符的引用,位置n从0记起。 |
s1+s2 |
返回s1和s2连接后的结果 |
读写string对象:
可以使用输入输出io操作符读写string对象;
读取未知数量的string对象:
1
2
3
4
|
while (cin>>word) { cout<<word<<endl; } |
每次读入一整行,直至文件末尾。由于line中不包含换行符所以我们手动的添加上换行符。endl结束当前行并刷新显示缓冲区。
触发的getline函数返回的那个换行符实际上被丢弃了,得到的身体日那个、对象中并不包含该换行符。
string的empty和size操作:
1
2
3
4
5
6
7
|
while (getline(cin,line)) { if (!line.empty()) { cout<<line<<endl; } } |
if语句的条件部分使用了逻辑非运算符!,它返回与其运算对象相反的结果。此例中如果str不为空则返回真。
1
2
3
4
5
6
7
8
|
string line; while (getline(cin.line)) { if (line.size()> 80 ) { cout<<line<<endl; } } |
每次读取一整行,输出其中超过80个字符的行。
string::size_type类型:
尽管我们不知道string::size_type类型的细节,但有一点是肯定的,它是一个无符号类型的值而且能够存放下任何string类型对象的大小。所有用于存放string类的size函数返回值的变量,都应该是string::size_type类型的。
在C++11中,允许编译器通过auto或者decltype来推断变量类型。
1
|
auto len=line.size(); //len的类型是string::size_tyoe |
由于size函数返回的是一个无符号整型数,因此在表达式中混用了有符号,无符号将可能产生意料之外的结果哦。
如果一个表达式中已经有了size()函数,就不要在使用int
了,这样可以避免混用int和unsigned可能带来的问题。
比较string对象:
(==)和(!=)分别检验两个string对象相等或不相等,string对象相等意味着他们的长度相同而且字符也全部相同。
1、如果两个string对象的长度不同,而且较短string对象的每个字符都与较长string对象对应位置上的字符相同,就说较短string对象小于较长string对象。
2、如果两个string对象在某些位置上不同,则string对象比较的结果其实是string对象中第一对相异字符比较的结果。
为string对象赋值:
一般来说,在设计标准库类型时都力求在易用性上向内置类型看齐,因此大多数库类型都支持赋值操作。对于string类而言,允许把一个对象的值赋值给另外一个对象。
两个string值相加:
把左右两侧的string对象串接起来
处理string对象中的字符:
在cctype头文件中定义了一组便准库来处理这部分工作。
isalnum | Check if character(字母) is alphanumeric(字母或者数字) (function) |
isalpha | Check if character is alphabetic(字母) (function) |
iscntrl | Check if character is a control character(控制字符) (function) |
isdigit | Check if character is decimal (数字)digit (function) |
isgraph | Check if character has graphical (不是空格但可打印时为真)representation (function) |
islower | Check if character is lowercase(小写字母) letter (function) |
isprint | Check if character is printable(可打印的) (function) |
ispunct | Check if character is a punctuation (标点符号)character (function) |
isspace | Check if character is a white-space(空白) (function) |
isupper | Check if character is uppercase(大写) letter (function) |
isxdigit | Check if character is hexadecimal(16进制数字) digit (function) |
And secondly, two functions to convert between letter cases:
tolower | Convert uppercase letter to lowercase (function)(大写换成小写) |
toupper | Convert uppercase letter to uppercase (function)(小写换成大写) |
翻译,如下:
函数名称 |
返回值 |
isalnum() | 如果参数是字母数字, 即字母或数字, 该函数返回 true |
isalpha() | 如果参数是字母, 该函数返回 true |
isblank() | 如果参数是空格或水平制表符, 该函数返回 true |
iscntrl() | 如果参数是控制字符, 该函数返回 true |
isdigit() | 如果参数是数字 (0~9), 该函数返回 true |
isgraph() | 如果参数是除空格之外的打印字符, 该函数返回 true |
isprint() | 如果参数是打印字符 (包括空格), 该函数返回 true |
ispunct() | 如果参数是标点符号, 该函数返回 true |
isspace() | 如果参数是标准空白字符, 如空格、进纸、换行符、回车、水平制表符或垂直制表符, 该函数返回 true |
islower() | 如果参数是小写字母, 该函数返回 true |
isupper() | 如果参数是大写字母, 该函数返回 true |
isxidgit() | 如果参数是十六进制的数字, 即 0~9, a~f 或 A~F, 该函数返回 true |
C++标准中除了定义C++语言特有的功能之外,也兼容了C语言的标准库。C语言的头文件形如:name.h,C++则将这些文件命名为Cname。也就是去掉了.h后缀,而在文件名name之前添加了首字母c,这里的c表示这是一个属于c语言标准库的头文件。
一般来说,C++程序因该使用名为cname的头文件而不使用name.h的形式,标准库中的名字总能在命名空间std中找到。如果使用.h形式的头文件,程序员就不得不时刻牢记哪些是从C语言那里继承过来的,哪些优势C++语言所独有的。
处理每个字符?使用基于范围的for语句
1
2
3
4
5
|
string str( "some string" ); for (auto c:str) { std::cout<<c<<std::endl; } |
for循环把变量c和str联系起来,其中我们定义循环变量的方式与定义任意一个普通变量是一样的。此例中,使用auto关键字让编译器来决定变量c的类型。
适用范围for语句改变字符串中的字符:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# include <iostream> # include <cctype> # include <cstring> using namespace std; int main() { string name= "wang shuai" ; for (auto &c:name) { c=toupper(c); } cout<<name<<endl; } |
只处理一部分字符?
如果要处理string对象中的每一个字符,使用范围for语句是个好主意。然而我们有时只是需要访问其中一个字符,或者访问多个字符遇到某个条件就要停下来。例如:同样是将字符改写为大写形式,不过新的要求不再是对整个字符串都这样做,而仅仅是把string对象中的第一个字母或者第一个单词大写化。
想访问string对象中的单个字符有两个方式:(1)使用下标(2)使用迭代器
下标运算符【】接受的输入类型是string ::size_type类型的值,返回值是该字符在该位置上的引用。
使用下标进行迭代。