这一章节感觉挺重要的,刷leetcode的时候也经常会用到vector和string。感觉python处理起列表和字符串都更加方便,C++引入了string和vector容器,也方便了很多。
3.1 命名空间的using声明
我们用到的库函数基本上都属于命名空间std。
std::cin表示从标准输入中读取内容,使用命名空间std中的名字cin。::为域作用符,含义是编译器应从左侧名字所示的作用域中寻找右侧那个名字。
然而这种表达方式比较繁琐,所以使用using声明来简化。
using namespace::name;
注意:头文件不应包含using声明
因为头文件的内容会被拷贝到所有引用它的的文件中去,如果头文件里有某个using声明,那么每个使用了该头文件的文件都会有这个声明。可能会造成名字冲突。
3.2 标准库类型string
(1)定义和初始化string对象
初始化string对象的方式
string s1;//默认初始化,s1是一个空串
string s2(s1);//s2是s1的副本
string s2=s1;//和s2(s1)等价
string s3("value");//s3是字面值“value”的副本,除了字面值最后的那个空字符外
string s3="value";//与上等价
string s4(n,'c');//把s4初始化为由n个字符c组成的串
两种初始化方式:
直接初始化
拷贝初始化:使用等号,把编译器等号右边的初始值拷贝到新建的对象中去。
(2)string对象上的操作
- 读写string对象
- 使用getline读取一整行
把所读的内容存到line对象中,不存换行符getline(cin,line)
- string::size_type类型
size_type体现了标准库类型与机器无关的特性。通过作用域操作符来表明名字size_type是在类string中定义的
size函数返回的是一个无符号整型数,切勿和带符号数混合使用。
- 比较string对象
- 为string对象赋值
- 两个string对象相加
- 字面值和string对象相加
当string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个假发运算符(+)的两侧的运算对象至少有一个是string。
s1="hello",s2="world!";
string s6=s1+","+"world";//正确
string s7="hello"+","+s2;//错误:不能把字面值直接相加
练习3.2
一次读入一整行,使用getline(cin,line)函数
#include <iostream>
#include <string>
using namespace std;
void main()
{
string mystring;
while (getline(cin , mystring))
{
cout<<mystring<<endl;
}
}
一次读入一个词
#include <iostream>
#include <string>
using namespace std;
void main()
{
string mystring;
while (cin>>mystring)
{
cout<<mystring<<endl;
}
}
(3)处理string对象中的字符
c++11新标准提供了一种语句:范围for。
语法如下:
for(declaration:expression)
statement
expression部分是一个对象,用于表示一个序列。declaration是序列中的基础元素,每次迭代回味初始化expression部分的下一个元素值。
使用范围for语句改变字符串中的字符
如果想改变string对象中的字符的值,必须把循环变换定义成引用类型。
只处理一部分字符
两种方法:1、使用下标; 2、使用迭代器
3.3 标准库类型vector
标准库类型vector表示对象的集合,其中所有对象的类型都相同。想要使用vector,必须包含适当的头文件。
c++语言既有类模板又有函数模板,vector属于类模板。
模板本身不是类或函数。编译器根据模板创建类或函数的过程称为实例化。当使用模板时,需要指出编译器应把类或函数实例化何种类型。
我的理解是,模板就是一种通用类型。具体用到的时候我们自己来指定具体的数据类型。
vector能容纳绝大多数类型的对象作为其元素。
(1)定义和初始化vector对象。
vector<T> v1;
vector<T> v2(v1);
vector<T> v2=v1;
vector<T> v3(n,val);
vector<T> v4(n);
vector<T> v5{a,b,c...}
vector<T> v5={a,b,c...}
列表初始化vector对象,用{}而不是()。
创建指定数量的元素,vector<int> ivec(10,-1);
值初始化 只提供vector对象容纳的元素数量,库会创建一个值初始化的元素初值
(2)向vector对象中添加元素
范围for语句体内不应改变其所遍历序列的大小
(3)其他vector操作
不能用下标形式添加元素
3.4 迭代器介绍
在c++中,对for循环中更多的使用!=进行判断。因为所有标准容器库都定义了==和!=,但它们中大部分都没有定义<运算符。
迭代器类型
我们不知道string和vector的size_type成员到底是什么类型,一般来说我们也不知道迭代器的精确类型。一般使用iterator和const_iterator来表示迭代器的类型。
const_iterator只能读元素,不能写元素。如果vector和string对象是一个常量,只能使用const_iterator。
begin和end,对量是常量返回const_iterator,非常量返回iterator。
引入新的cbegin,cend不论vector对象本身是狗是常量,返回值都是const_iterator。
结合解引用和成员访问操作
解引用迭代可获得迭代器所指的对象。
(it).empty()//解引用it,然后调用结果对象的empty成员。
箭头运算符->把解引用和成员访问两个操作结合起来。it->mem相当于*(it).mem
两个迭代器相减得到的类型为difference_type带符号整数型。
3.5 数组
数组与vector结构相似,但数组的大小固定,在某些特殊的应用上性能较好,但也损失了一些灵活性。
数组声明形如a[d],d代表维度,必须为常量表达式。
字符数组特殊的初始化形式,可以使用字符串字面值,使用这种方式时,结尾还有一个空字符。
不允许拷贝和复制