3.2.1 定义和初始化string对象
string s1;//默认初始化,s1是一个空字符创
string s2 = s1;//s2是s1的副本
string s3="hiya";//s3是该字符串字面量的副本
string s4(10, 'c');//s4的内容是cccccccccc
如果提供提供一个字符串字面值,则该字面值中除了最后那个空字符以外其他所有的字符都被拷贝到新创建的string对象中去。
如果使用等号初始化一个变量,实际上执行的是拷贝初始化,编译器把等号右侧的初始值拷贝到新创建的对象中去。与之相反,如果不使用等号,则执行的是直接初始化。
3.2.2 string对象上的操作
os<<s 将s写到输出流os中,返回os
is>>s 从is中读取字符串赋给s,字符串以空白符分隔,返回is
getline(is, s) 从is中读取一行赋给s,返回is
s.empty() s为空返回true,否则返回false
s.size() 返回s中字符的个数
s[n] 返回s中第n个字符的引用,位置n从0计起
s1 + s2 返回s1和s2连接后的结果
s1=s2 用s2的副本代替s1中原来的字符
s1==s2 如果s1和s2中所含的字符完全一样,则它们相等
s1!=s2
<,>,<=,>= 利用字符在字典中的顺序进行比较
在执行读取操作时,string对象会自动忽略开头的空白(即空格符、换行符、制表符)并从第一个真正的字符开始读起,直到遇见下一处空白为止。
使用getline读取一整行
getline函数的参数是一个输入流和一个string对象,函数从给定的输入流中读入内容,直到遇到换行符为止(注意换行符也被读经来了),然后把所读内容存入到那个string对象中去(注意不存在换行符)。触发getline函数返回的那个换行符实际上被丢弃掉了,得到的string对象中实际上并不包含该换行符。
string::size_type类型
size函数返回的是一个string::size_type类型的值。它是一个无符号类型的值,而且能足够存放下任何string对象的大小。所有用于存放string类的size函数返回值的变量,都应该是string::size_type类型的。
比较string对象
1.如果两个string对象的长度不同,而且较短string对象的每个字符都与较长string对象对应位置上的字符相同,就说较短string对象小于较长string对象。
2.如果两个string对象在某些对应的位置上不一致,则string对象比较的结果其实是string对象中第一对相异字符比较的结果。
字面值和string对象相加
string s4 = s1 +',';//正确:把一个string对象和一个字面值相加
string s5 = "hello" + ',';//错误:两个运算对象都不是string
string s6 = ("hello" + ",") + s2;//错误:不能把字面量直接相加
因为某些历史原因,也为了与C兼容,所以C++语言中的字符串字面值并不是标准库类型string对象。切记,字符串字面值与string是不同的类型。
处理每个字符?使用基于范围的for语句
for(declaration:expression)
statement
其中,expression部分是一个对象,用于表示一个序列。declaration部分负责定义一个变量,该变量将被用于访问序列中的基础元素。每次迭代,declaration部分的变量会被初始化为expression部分的下一个元素值。
string str("some string");
//每行输出str中的一个字符
for (auto c : str)//对于str中的每个字符
cout<< c <<endl;//输出当前字符,后面紧跟一个换行符
如果想改变string对象中字符的值,必须把循环变量定义成引用类型
3.3 标准库类型vector
标准库类型vector表示对象的集合,其中所有对象的类型都相同。集合中的每个对象都有一个与之对应的索引,索引用于访问对象。因为vector容纳着其他对象,所以它也常被称作容器。
C++语言既有类模板,也有函数模板,其中vector是一个类模板。编译器根据模板创建类或函数的过程称为实例化,当使用模板时,需要指出编译器应把类或函数实例化成何种类型。提供信息的方式总是这样:即在模板名字后面跟一对尖括号,在括号内放上信息。
vector<int> ivec;//ivec保存int类型的对象
vector<vector<string>> file;//该向量的元素是vector对象
某些编译器可能仍需以老式的声明语句来处理元素为vector的vector对象,必须在外层vector对象的右尖括号和其他元素类型之间添加一个空格。
3.3.2 向vector对象中添加元素
先创建一个空vector,然后在运行时再利用vector的成员函数push_back向其中添加元素。push_back负责把一个值当成vector对象的尾元素“压到(push)”vector对象的“尾端(back)"。
C++标准要求vector应该能在运行时搞笑快速地添加元素。因此既然vector对象能高效地增长,那么定义vector对象的时候设定其大小也就没有什么必要了,事实上如果这么做性能可能更差。
如果循环体内含有向vector对象添加元素的语句,则不能使用范围for循环,范围for语句体内不应改变其所遍历序列的大小。
3.3.3 其他vector操作
v.empty() 如果v不含有任何元素,则返回真;否则返回假
v.size() 返回v中元素的个数
v.push_back(t) 向v的尾端添加一个值为t的元素
v[n] 返回v中第n个位置上元素的引用
v1 = v2 用v2中元素的拷贝替换v1中的元素
v1 = {a,b,c...} 用列表中的元素拷贝替换v1中的元素
v1==v2 v2和v1相等当且仅当它们的元素数量相同且对应位置的元素值都相同
<,>,<=,>= 顾名思义,以字典顺序进行比较
3.4 迭代器
所有标准库容器都可以使用迭代器,但是其中只有少数几种才同时支持下表运算符。类似于指针,迭代器也体用了对对象的间接访问。(和指针的使用很类似)
//由编译器决定b和e的类型;
//b表示v的第一个元素,e表示v尾元素的下一个位置
auto b = v.begin(),e = v.end(); // b和e的类型相同
end成员则负责指向容器尾元素的下一位置的迭代器,end成员返回的迭代器常被称作尾后迭代器或者简称为尾迭代器。特殊情况下如果容器为空,则begin和end返回的是同一个迭代器。
迭代器类型
拥有迭代器的标准库类型使用iterator和const_iterator来表示迭代器的类型:
vector<int>::iterator it;//it能读写vector<int>的元素
string::iterator it2;//it2能读写string对象中的字符
vector<int>::const_iterator it3;//it3只能读元素,不能写元素
string::const_itetator it4;//it4只能读元素,不能写元素