文章目录
C语言参考学习网址:http://c.biancheng.net/cpp/u/jiaocheng/
C++参考学习网址:http://c.biancheng.net/cpp/biancheng/cpp/rumen/
一,数据
1.变量
2.数组
3.指针
4.结构体
5.C++容器
5.1. victor容器(类似于数组)
用法:
#include<vector>
//1.初始化
vector<int> vec; //声明一个int型向量
vector<int> vec(5); //声明一个初始大小为5的int向量
vector<int> vec(10, 1); //声明一个初始大小为10且值都是1的向量
vector<int> vec(tmp); //声明并用tmp向量初始化vec向量
vector<int> tmp(vec.begin(), vec.begin() + 3); //用向量vec的第0个到第2个值初始化tmp
int arr[5] = {1, 2, 3, 4, 5};
vector<int> vec(arr, arr + 5); //将arr数组的元素用于初始化vec向量
//说明:当然不包括arr[4]元素,末尾指针都是指结束元素的下一个元素,
//这个主要是为了和vec.end()指针统一。
vector<int> vec(&arr[1], &arr[4]); //将arr[1]~arr[4]范围内的元素作为vec的初始值
//2. 元素排序
#include <algorithm>
sort(vec.begin(), vec.end()); //采用的是从小到大的排序
//如果想从大到小排序,可以采用上面反转函数,也可以采用下面方法:
bool Comp(const int& a, const int& b) {
return a > b;
}
sort(vec.begin(), vec.end(), Comp);
//3.元素翻转
#include <algorithm>
reverse(vec.begin(), vec.end());
//4.遍历元素
vector<int>::iterator it;
for (it = vec.begin(); it != vec.end(); it++)
cout << *it << endl;
//或者
for (size_t i = 0; i < vec.size(); i++) {
cout << vec.at(i) << endl;
}
vector基本操作
(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的特性。
5.2.deque容器(类似于队列)
deque的使用:
//1.插入数值到deque
//c.insert(pos,num)在pos位置插入元素num
//c.insert(pos,n,num)在pos位置插入n个元素num
//c.insert(pos,beg,end)在pos位置插入区间为[beg,end)的元素
deque<int> d {1,2,3,4,5};
deque<int>::iterator it;
cout << "insert before:" ;
for(it=d.begin();it!=d.end();it++){
cout << *it << " ";
}
cout << endl;
d.insert(d.end(),22);
d.insert(d.end(), 3,88);
int a[5] = {1,2,3,4,5};
d.insert(d.begin(),a,a+3);
cout << "insert after:" ;
for(it=d.begin();it!=d.end();it++){
cout << *it << " ";
}
cout << endl;
//2.删除deque中的元素
//c.erase(pos)删除pos位置的元素
//c.erase(beg,end)删除区间为[beg,end)之间的元素
deque<int> d {1,2,3,4,5};
d.erase(d.begin());
deque<int>::iterator it;
cout << "erase(pos) after:" ;
for(it=d.begin();it!=d.end();it++){
cout << *it << " ";
}
cout << endl;
d.erase(d.begin(), d.begin()+3);
cout << "erase(beg,end) after:" ;
for(it=d.begin();it!=d.end();it++){
cout << *it << " ";
}
cout << endl;
//c.push_back(num)在末尾位置插入元素
//c.pop_back()删除末尾位置的元素
//c.push_front(num)在开头位置插入元素
//c.pop_front()删除开头位置的元素
deque<int> d {1,2,3,4,5};
d.push_back(10);
deque<int>::iterator it;
cout << "push_back(num):" ;
for(it=d.begin();it!=d.end();it++){
cout << *it << " ";
}
cout << endl;
d.pop_back();
cout << "pop_back(num):" ;
for(it=d.begin();it!=d.end();it++){
cout << *it << " ";
}
cout << endl;
d.push_front(10);
cout << "push_front(num):" ;
for(it=d.begin();it!=d.end();it++){
cout << *it << " ";
}
cout << endl;
d.pop_front();
cout << "pop_front(num):" ;
for(it=d.begin();it!=d.end();it++){
cout << *it << " ";
}
cout << endl;
return 0;
//3.迭代器遍历
deque<int> d {1,2,3,4,5};
deque<int>::iterator it;
for(it=d.begin();it!=d.end();it++){
cout << *it << " ";
}
cout << endl;
//反向迭代器(从尾部向头部向尾部迭代)
//c.rbegin()返回指向反向队列的第一个元素的迭代器(即原队列的最后一个元素)
//c.rend()返回指向反向队列的最后一个元素的下一个位置(即原队列的第一个元素的前一个位置)
deque<int> d {1,2,3,4,5};
deque<int>::reverse_iterator it;
for(it=d.rbegin();it!=d.rend();it++){
cout << *it << " ";
}
cout << endl;
构造函数
deque c 创建一个空的deque
deque c1(c2) 复制一个deque。
deque c(n) 创建一个deque,含有n个数据,数据均已缺省构造产生。
deque c(n, elem) 创建一个含有n个elem拷贝的deque。
deque c(beg,end) 创建一个以[beg;end)区间的deque。
~deque() 销毁所有数据,释放内存。
成员函数
迭代器:
c.begin()返回指向第一个元素的迭代器
c.end()返回指向最后一个元素下一个位置的迭代器
c.rbegin()返回指向反向队列的第一个元素的迭代器(即原队列的最后一个元素)
c.rend()返回指向反向队列的最后一个元素的下一个位置(即原队列的第一个元素的前一个位置)
operator=赋值运算符重载
c.assign(n,num)将n个num拷贝复制到容器c
c.assign(beg,end)将[beg,end)区间的数据拷贝复制到容器c
c.operator[]下标运算符重载
c.empty()判断c容器是否为空
c.front()返回c容器的第一个元素
c.back()返回c容器的最后一个元素
c.size()返回c容器中实际拥有的元素个数
c.max_size()返回c容器可能存放元素的最大数量
c.clear()清除c容器中拥有的所有元素
c.resize(num)从新定义容器的大小
c1.swap(c2)交换容器c1,c2;
5.3.map容器(key———valu)
map的使用:
//1.用insert函数插入pair数据
//数据的插入--第一种:用insert函数插入pair数据
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
map<int, string> mapStudent;
mapStudent.insert(pair<int, string>(1, "student_one"));
mapStudent.insert(pair<int, string>(2, "student_two"));
mapStudent.insert(pair<int, string>(3, "student_three"));
}
//2.用数组方式插入数据
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
map<int, string> mapStudent;
mapStudent[1] = "student_one";
mapStudent[2] = "student_two";
mapStudent[3] = "student_three";
//区别:
//map<int, string> iter 是 声明一个map容器
//map<int, string>::iterator iter 是声明一个 迭代器
map<int, string>::iterator iter;
}
//数据的删除
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
map<int, string> mapStudent;
mapStudent.insert(pair<int, string>(1, "student_one"));
mapStudent.insert(pair<int, string>(2, "student_two"));
mapStudent.insert(pair<int, string>(3, "student_three"));
//如果你要演示输出效果,请选择以下的一种,你看到的效果会比较好
//如果要删除1,用迭代器删除
map<int, string>::iterator iter;
iter = mapStudent.find(1);
mapStudent.erase(iter);
//如果要删除1,用关键字删除
int n = mapStudent.erase(1);//如果删除了会返回1,否则返回0
//用迭代器,成片的删除
//一下代码把整个map清空
mapStudent.erase( mapStudent.begin(), mapStudent.end() );
//成片删除要注意的是,也是STL的特性,删除区间是一个前闭后开的集合
//自个加上遍历代码,打印输出吧
}
// 数据的遍历
//3.用数组方式,程序说明如下
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
map<int, string> mapStudent;
mapStudent.insert(pair<int, string>(1, "student_one"));
mapStudent.insert(pair<int, string>(2, "student_two"));
mapStudent.insert(pair<int, string>(3, "student_three"));
int nSize = mapStudent.size();
//此处应注意,应该是 for(int nindex = 1; nindex <= nSize; nindex++)
//而不是 for(int nindex = 0; nindex < nSize; nindex++)
for(int nindex = 1; nindex <= nSize; nindex++)
cout<<mapStudent[nindex]<<endl;
}
使用map:
map对象是模板类,需要关键字和存储对象两个模板参数:std:map<int,string> personnel;
map的构造函数: map<int, string> mapStudent;
数据的插入:1.用insert函数插入pair数据 2.用数组方式插入数据
map的大小:在往map里面插入了数据,我们怎么知道当前已经插入了多少数据呢,可以用size函数
Int nSize = mapStudent.size();
从map中删除元素
移除某个map中某个条目用erase()
该成员方法的定义如下:
iterator erase(iterator it);//通过一个条目对象删除
iterator erase(iterator first,iterator last)//删除一个范围
size_type erase(const Key&key);//通过关键字删除
clear()就相当于enumMap.erase(enumMap.begin(),enumMap.end());
这里要用到erase函数,它有三个重载了的函数
//_______________________________________________________________________________
查找并获取map中的元素(包括判定这个关键字是否在map中出现)
在这里我们将体会,map在数据插入时保证有序的好处。
要判定一个数据(关键字)是否在map中出现的方法比较多,这里标题虽然是数据的查找,在这里将穿插着大量的map基本用法。
这里给出三种数据查找方法
第一种:用count函数来判定关键字是否出现,其缺点是无法定位数据出现位置,由于map的特性,一对一的映射关系,就决定了count函数的返回值只有两个,要么是0,要么是1,出现的情况,当然是返回1了
第二种:用find函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器。
查找map中是否包含某个关键字条目用find()方法,传入的参数是要查找的key,在这里需要提到的是begin()和end()两个成员,
分别代表map对象中第一个条目和最后一个条目,这两个数据的类型是iterator.
//查找并获取map中的元素
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
map<int, string> mapStudent;
mapStudent.insert(pair<int, string>(1, "student_one"));
mapStudent.insert(pair<int, string>(2, "student_two"));
mapStudent.insert(pair<int, string>(3, "student_three"));
map<int, string>::iterator iter;
iter = mapStudent.find(1);
if(iter != mapStudent.end())
cout<<"Find, the value is "<<iter->second<<endl;
else
cout<<"Do not Find"<<endl;
return 0;
}
二,选择/循环语句
三,函数
函数逻辑组成:
函数逻辑块 | 功能 |
---|---|
if语句 | 判断对应条件下的对应情况 |
switch语句 | 判断对应条件下的对应情况 |
————— | ———————————————— |
for循环语句 | 进行大量初始化 |
while循环语句 | 进行大量初始化 |
函数分类:
函数类型 | 作用 |
---|---|
内联函数 | 编译时,函数调用处被函数体替换(提高效率) |
函数模板 | 参数个数相同,类型不同(提高函数参数的通用性,同一参数可以定义为多种类型) |
函数重载 | 参数类型,顺序,个数不相同(提高函数名的通用性,同一函数名可以有多种用途) |
虚函数 | 纯虚函数没有函数体,只有函数声明(派生类按需求实现纯虚函数) |
—————————————————————————————————————
四,C++类
虚函数:父类中提供虚函数并实现。(目的是“运行时多态”,为子类提供默认的函数实现。)
纯虚函数:纯虚函数在类中只提供声明,不提供实现,实现由子类去完成。(目的是为了实现“运行时的多态”。)
函数模板:用于函数的变量类型
类模板:用于类的函数变量类型+类成员的类型
c++异常及异常处理
程序的错误大致可以分为三种,分别是:
①语法错误(语法错误在编译和链接阶段就能发现)
②逻辑错误( 逻辑错误是编写的代码思路有问题,可以通过调试来解决)
③运行时错误(运行时错误是指程序在运行期间发生的错误,可以通过C++ 异常机制解决)
(运行时错误eg:除数为 0、内存分配失败、数组越界、文件不存在等。)
try catch异常处理
捕获异常的语法为:
try{
// 可能抛出异常的语句
}catch(exceptionType variable){
// 处理异常的语句
}
exceptionType是异常类型,异常类型可以是 int、char、float、bool 等基本类型,也可以是指针、数组、字符串、结构体、类等聚合类型。
variable是一个变量,用来接收异常信息。当程序抛出异常时,会创建一份数据,这份数据包含了错误信息。
C++ 语言本身以及标准库中的函数抛出的异常,都是 exception 类或其子类的异常。也就是说,抛出异常时,会创建一个 exception 类或其子类的对象。
抛出异常
抛出(Throw)–> 检测(Try) --> 捕获(Catch)
// throw 关键字来显式地抛出异常的用法为:
throw exceptionData;
//exceptionData 是“异常数据”的意思,它可以包含任意的信息,完全有程序员决定。
//exceptionData 可以是 int、float、bool 等基本类型,也可以是指针、数组、字符串、结构体、类等聚合类型。
多级 catch
try{
//可能抛出异常的语句
}catch (exception_type_1 e){
//处理异常的语句
}catch (exception_type_2 e){
//处理异常的语句
}
//其他的catch
catch (exception_type_n e){
//处理异常的语句
}
eg:
#include <iostream>
#include <string>
using namespace std;
class Base{ };
class Derived: public Base{ };
int main(){
try{
throw Derived(); //抛出自己的异常类型,实际上是创建一个Derived类型的匿名对象
cout<<"This statement will not be executed."<<endl;
}catch(int){
cout<<"Exception type: int"<<endl;
}catch(char *){
cout<<"Exception type: cahr *"<<endl;
}catch(Base){ //匹配成功(向上转型)
cout<<"Exception type: Base"<<endl;
}catch(Derived){
cout<<"Exception type: Derived"<<endl;
}
return 0;
}