本章主要介绍了字符串和vector以及数组,但是vector和数组差不多甚至比数组更加强大,完全可以用vector来代替数组,所以尽管书中有介绍数组,但我也不过多记录,有兴趣的小伙伴可以自行查看原书。
3.1命名空间的using声明
我们使用的库函数基本上都属于命名空间std,每次使用对应的成员都需要在前面加上std:: 这样会比较繁琐,所以我们可以如下使用using声明,这是最安全的方法.
using namespace::name;
//例如
using std::cout;
cout<<"hello world"<<std::endl; //std::cout在前面声明过了,所以可以直接使用
每个成员都需要单独进行声明,可以在一行里全部声明完,但是需要用分号;进行区分.
头文件不应包含using声明.
3.2标准库类型string
标准库类型string表示可变长的字符序列.完整的类型写法为std::string
3.2.1定义和初始化string对象
其中最常用的(对我而言)是第1,3,5种方法.
如果使用等号初始化一个变量,也就是第三种和第五种方法,实际上执行的是拷贝初始化,编译器把等号右侧初始值拷贝到新创建的对象中.如果不使用等号,则是直接初始化.
3.2.2string对象上的操作
使用io操作费读取string会自动忽略开头的空白(空白符,换行符,制表符),然后从第一个有效字符开始,直到遇到下一处空白,例如:
#include <iostream>
using namespace std;
int main(){
string s;
cin >> s;
cout << s <<endl;
return 0;
}
//输入" helloWorld "
//输出"helloWorld"
我们可以看出来用io操作符来给string赋值是不包含空白的,如果我们非要,那么可以使用getline函数.
getline(输入流对象,string对象)
#include <iostream>
using namespace std;
int main(){
string s;
getline(cin,s);
cout << s <<endl;
return 0;
}
//输入" helloWorld "
//输出" helloWorld "
getline会一直读取直到遇到换行符,同时换行符也会被读取,但是string对象不保存换行符.
string对象包含函数size,可以获取string对象的长度,获取的长度类型为 string::size_type,记不住的话可以用auto来接收size函数的返回值,但是要记住,string::size_type是无符号类型,所以不能够将无符号和有符号的数据混用.
string s = "hello world";
auto LEN1 = s.size();
string::size_type LEN2=s.size():
string对象可以直接相加,然后赋值给新的string对象,也可以string和字面量相加,但是不能字面量和字面量相加.
"hello world" //这是字面量
string s = "hello world" //这是string对象
3.2.3处理string对象中的字符
C++标准库兼容C语言的标准库,例如C语言的标准库叫ctype.h,那么C++兼容的标准库则去掉.h后缀,然后在开头再加个c,例如cctype:
C++中的范围for(类似于Java的增强for)可以依次获取可迭代对象的元素.
for(adeclaration : expression){
//操作
}
string s = "hello world";
for ( char x : s ){
cout << x << ' ';
}
//输出 "hello world";
如果要修改迭代的结果,那么把循环变量的类型改成引用类型.
C++标准不要求编译器(但是好像有一些编译器会检测)检测下标是否合法,一旦下标越界那么会产生不可预测的结果.string对象的下标要求范围为[0,string.size())(左闭右开).
3.3标准库类型vector
可以把vector看作加强版数组.
vector属于类模板,可以包含大多数类型的对象作为其元素,但是不可以存放引用类型,因为引用不是对象.如果vector的元素类型还是vector,在C++11之前,必须在外层的vector对象的右尖括号和其元素类型直接添加一个空格,例如:
vector<vector<int> > //C++11之前
vector<vector<int>> //C++11
3.3.1定义和初始化vector对象
如果vector初始化的元素类型不支持默认初始化(例如int类型默认为0)那么则不能使用第五种方法,而必须提供初始化的元素值.
push_back(val)可以将元素添加至vector的尾部,但使用范围for的时候不能使用该函数.或者说所有可迭代对象在使用范围for的时候都不可以改变对象的大小.
3.3.3其他vector操作
vector对象可以使用下标运算符[]访问已存在的函数,但是不可以用下标运算符添加元素.保证下标合法的有效手段就是使用范围for语句!
3.4迭代器
所有标准库容器(包括vector在内,书的后面章节还会介绍更多.严格来说string不属于容器类型,但是string支持很多与容器类型相似的操作)都可以使用迭代器.简单来说迭代器就是指针.可以通过解引用迭代器来获取相应的数据.
但是和指针不一样的是,获取迭代器不是用取地址符&,而是用有迭代器的类型自带的函数:
vector<int> a(10,1);
auto b = a.begin(); //实际上类型为vector<int>::iterator,但是这里我们暂时用auto代替
auto e = a.end(); //但如果对象是常量,那么类型就是const_iterator
迭代器支持的运算符如下:
书中提醒,但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素.
3.4.2迭代器运算
两个迭代器相减得到的是两个迭代器之间的距离,类型为differece_type,记不住可以用auto来接收,只需要知道它是带符号的整型数.
3.5数组
C++中数组和C语言的基本上一致,并且推荐用vector来代替数组,这里我就不多介绍,感兴趣的可以自行去看原书.
3.6多维数组
关于多维数组,严格来说,C++并没有多维数组,通常我们说的多维数组其实是数组的嵌套,即数组的元素为数组,对于二维数组,通常把第一个维度称作行(row),第二维度成为列(col).