在这一章里面主要分几个部分命名空间using,标准库类型string,vector,迭代器的简单介绍,数组等
3.1命名空间的using声明
在c++中通常使用using namespace std
3.2标准库类型string
标准库类型string表示可变长的字符序列,使用string类型须包含strirng头文件
定义和初始化string对象
string s1; //默认初始化,s1是一个空串
string s2(s1); //直接初始化,s2是s1的副本
string s2=s1; //拷贝初始化,s2是s1的副本
string s3("value"); //直接初始化,s3是"value"的副本,除了最后的空字符
string s3="value"; //拷贝初始化
string s4(10,'c'); //直接初始化,s4初始化之后的内容是cccccccccc
string s5 = string(10,'c'); //拷贝初始化,s5的内容是cccccccccc
string的操作
内容 | 说明 |
---|---|
getline(is ,s) | 从is中读取一行赋值给s,返回is |
s.empty() | s为空为true,否则flase |
s.size() | 返回s中字符的个数 |
s[n] | 返回第n个字符的引用,位置从0开始 |
s1+s2 | 返回s1和s2连接的结果 |
s1=s2 | 用s2的副本代替s1中的内容 |
s1==s2 | s1和s2中字符完全一样则相等,对大小写敏感 |
s1!=s2 | 判断不相等,对大小写敏感 |
<,>,>=,<= | 字符在字典中的顺序进行比较,对大小写敏感 |
string注意点
其实这只是我自己的笔记
1.定义string时,string对象会自动忽略开头空白,并从第一个字符真正的字符开始读起,直到遇见下一个空白
2.getline是读取一整行,包括空白,遇到换行符为止,换行符也被读进来了,但是不保存到string对象中去
3.每个加法运算符的两侧运算对象至少有一个是string
string s1="hello";
string s2=s1+'world'; //正确:有一个string对象
string s5="hello"+"world"; //错误:两个运算对象都不是string
3.3标准库类型vector
标准库类型vector表示对象的集合,其中所有对象的类型都相同
定义和初始化vector对象
vector<T> v1; //v1是一个空vector,潜在的元素是T类型,默认初始化
vector<T> v2(v1); //v2中含有v1所有元素的副本
vector<T> v2=v1; //和v2(v1)等价
vector<T> v3(n,val); //v3中包含了个重复的元素,每个重复元素的值是val
vector<T> v4(n); //v4中包含了n个重复地执行了值初始化的对象
vector<T> v5{a,b,c...}; //列表初始化:v5包含了初始值个数的元素,每个元素被赋予相应的初始值
vector<T> v5={a,b,c...}; //和上面等价
vector是个类模板,编译器根据模板创建类或函数的过程称为实例化,当使用模板时,需要指出编译器应该把类或者函数实例化成什么类型。
如果用的圆括号可以说提供的值是用来构造对象,如果用的是花括号,可以表述成列表初始化,在无法列表初始化时也会进行其他初始化方式,如下:
vector<int> v1(10); //v1有10个元素,每个的值都是0
vector<int> v1{10}; //v2有一个元素,元素的值是10
vector<string> v3("hi"); //错误,不能用字符串构建vector对象
vector<string> v4{10,"hi"}; //v8中有10个值为"hi"的元素
vector的操作
内容 | 描述 |
---|---|
v.empty() | 如果v中不含有任何元素,返回真,否则假 |
v.size | 返回v中元素个数 |
v.push_back(t) | 向v的尾端添加一个值为t的元素 |
v.pop_back() | |
v.emplace_back() | 与v.push_back()类似,调用形式更加简洁 |
v[n] | 返回v中第n个位置上的引用 |
(1). 容量
向量大小: vec.size();
向量最大容量: vec.max_size();
更改向量大小: vec.resize();
向量真实大小: vec.capacity();
向量判空: vec.empty();
减少向量大小到满足元素所占存储空间的大小: vec.shrink_to_fit(); //shrink_to_fit
(2). 修改
多个元素赋值: vec.assign(); //类似于初始化时用数组进行赋值
末尾添加元素: vec.push_back();
末尾删除元素: vec.pop_back();
任意位置插入元素: vec.insert();
任意位置删除元素: vec.erase();
交换两个向量的元素: vec.swap();
清空向量元素: vec.clear();
(3)迭代器
开始指针:vec.begin();
末尾指针:vec.end(); //指向最后一个元素的下一个位置
指向常量的开始指针: vec.cbegin(); //意思就是不能通过这个指针来修改所指的内容,但还是可以通过其他方式修改的,而且指针也是可以移动的。
指向常量的末尾指针: vec.cend();
(4)元素的访问
下标访问: vec[1]; //并不会检查是否越界
at方法访问: vec.at(1); //以上两者的区别就是at会检查是否越界,是则抛出out of range异常
访问第一个元素: vec.front();
访问最后一个元素: vec.back();
返回一个指针: int* p = vec.data(); //可行的原因在于vector在内存中就是一个连续存储的数组,所以可以返回一个指针指向这个数组。这是是C++11的特性。
eg:
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
vector<int> array;
array.push_back(100); //在末尾添加数值
array.push_back(200);
array.push_back(200);
array.push_back(200);
array.push_back(200);
array.push_back(500);
vector<int>::iterator itor;
for (itor = array.begin(); itor != array.end(); itor++)
{
if (*itor == 200) //从array中删除元素,此时迭代器指向删除元素的下一个元素,所以删除元素的下一个元素在这个比较过程中被跳过了
itor = array.erase(itor);
}
for (itor = array.begin(); itor != array.end(); itor++)
cout << *itor << " ";
return 0;
}
//输出结果为
//100 200 200 500
迭代器介绍
在前面介绍的string和vector中可以用for循环处理每个字符,方式是: string str("hello"); for(auto c:str){....}
我们通过auto关键字,让编译器决定c的类型,这里c的类型是char,每次迭代,str的下一个字符被拷贝给c,注意这里是c++11的标准,使用GUN编译器是要加上-std=C++11。
迭代器的成员一般是用两个begin和end,其中begin成员负责返回指向第一个元素的迭代器,end成员返回指向容器的最后一个元素的下一位置,迭代器运算符包括*iter
iter->men
(*iter).men
++iter
--iter
iter1==iter2
iter1!=iter2
。
迭代器的类型是iterator
const_iterator
在现代c++程序中应该尽量用vector和迭代器,,避免使用内置数组和指针,应该尽量使用string,避免使用c风格的字符串
所以数组的知识这里就不介绍了
我个人比较感兴趣的是c++11数组也引入了begin和end,使用方法是将数组作为参数
int ia[]={0,1,2,3,4,5};
int *beg=begin(ia); //指向ia首元素的指针
int *last=end(ia); //指向arr尾元素的下一位置的指针