10.16
配置Fedora虚拟机:系统部署
L1、部署Linux系统.ppt
dnf install gcc-c++
dnf install gedit
dnf install vim
ssh远程登陆
•Linux端启动SSH服务
systemctl is-enabled sshd //查询SSH服务是否开启
chkconfig sshd on //超级用户下启动SSH服务
使用 ifconfig 获取linux 系统的ip地址
•终端采用MobaXterm软件,用ssh协议创建面向Linux系统连接
操作步骤
shell命令:
L2、shell命令.ppt
Linux系统没有盘符概念,只有文件概念,文件都是有位置的,从根目录开始分层管理,各级目录用“/”分割,不同文件存放不同类型是内容,例如
/bin 存放普通级的可执行二进制文件,如ls、cp、mkdir等
/sbin 存放系统级的可执行二进制文件,如fdisk等
/boot 启动文件
/dev 设备驱动文件
/home 存放普通用户的主目录
/root 超级用户的主目录
/etc 存放配置参数
/temp 存放临时变量
/mnt 存放U盘或者共享文件等的映射文件
/usr/bin 用户安装的程序的可执行二进制文件
/usr/lib 用户安装的程序的对应库
/usr/include 用户安装的程序的C语言调用头文件
/usr/local 用户手动编译安装的文件放在该目录下
cd 变换目录
cd … 进入当前目录的父目录
cd …/a 进入到当前目录的父目录下的a目录
cd / 进入到根目录
cd ~ 进入到当前目录的主目录
cd /usr/local 进入到/usr/local目录
pwd 显示当前目录
pwd 返回当前目录的绝对路径
mkdir 建立一个新目录
mkdir a 在当前目录下创建一个目录名字为a
mkdir ~/b 在当前用户工作主目录下创建一个目录名字为b
mkdir …/c 在当前目录的父目录下创建一个目录名字为c
mkdir /home/nameyniu/d 在/home/nameyniu下创建一个目录名字为d
rmdir 删除一个内容为空的空目录
rmdir a 删除当前目录下的名字为a的目录
rmdir ~/b 删除当前用户工作主目录下名字为b的目录
rmdir …/c 删除当前目录的父目录下名字为c的目录
rmdir /home/nameyniu/d 删除/home/nameyniu名字为d的目录
clear 清理屏幕
ls命令
切换超级用户:
创建目录删除文件:
关机重启:
查看文件内容:
链接文件:
解压缩文件:
tar -cvf a.tar a 将a压缩成a.tar
tar -xvf a.tar 将a.tar解压缩到a
ls的用法
kill杀死进程:
日历时间:
cal 日历信息
参数 -1 显示一个月的月历
-3 显示系统前一个月,当前月,下一个月的月历
-s 显示星期天为一个星期的第一天,默认的格式
-m 显示星期一为一个星期的第一天
-j 显示在当年中的第几天(一年日期按天算,从1月1号算起,默认显示当前月在一年中的天数)
-y 显示当前年份的日历
date 时间及日期信息
参数 -d<字符串>:显示字符串所指的日期与时间,字符串前后必须加上双引号
-s<字符串>:根据字符串来设置日期与时间,字符串前后必须加上双引号
-u:显示GMT(格林威治标准时间)
用户密码:
useradd abc 默认添加一个用户abc
userdel -r abc 删除账号abc,连同其相关文件一并删除
passwd 用户自己修改密码
passwd abc 超级用户修改abc用户的密码
passwd root 修改root超级用户密码
网络:
查看网卡信息
返回系统环境变量值
10.17
vim文本编辑工具使用
L3、vi_vim文本编辑工具使用.ppt
在命令模式下按下:(英文冒号)就进入了底线命令模式
底线命令模式可以输入单个或多个字符的命令,Enter按键执行命令,可用的命令非常多,在底线命令模式中,基本的命令有
:e b.c 打开或者重新创建一个名字为b.c的文件
:set nu 显示行号(:set number)
:set nonu 不显示行号(:set nonumber)
:nu 当前光标停留处的行号
:5 定位到第5行
:set cursorline 显示下划线
:set nocursorline去掉显示下划线
:set spell 开启拼写检查功能
:set nospell 关闭拼写检查功能
:/a 匹配关键字a,正向搜索,并高亮显示,按n匹配下一个,按N匹配上一个(:?a反向搜索)
:w 保存文件
:w d.c 保存文件名为d.c
:q 退出程序
底线命令模式按ESC键可随时切换到命令模式
:wq! 保持文件并强行退出vim,回到shell
打开文件:
显示行号:
匹配关键字:
定位行数:
命令方式(移动光标)
按ctrl+b 屏幕往"后"移动一页,按键PgDn
按ctrl+f 屏幕往"前"移动一页,按键PgUp
按0 移动到光标所在行的"行首" (^)
按$ 移动到光标所在行的"行尾"
按G 移动到文章的最后
按gg 移动到文章的开头
按5l 光标移到所在位置后的第5个位置,如:5l,56l
命令方式(删除文字)
x 每按一次,删除光标所在位置的"后面"一个字符。
dd 删除光标所在行。
d$ 删除光标至行尾(D)
dG 删除光标至文件尾
d1G 删除光标至文件头(dgg)
复制粘贴:
yy 复制光标所在行到缓冲区
y^ 将光标所在之处到行首的字符复制到缓冲区中
6yy 例如,6yy表示拷贝从光标所在的该行"往下数"6行文字
p 将缓冲区内的字符贴到光标所在位置后边
P 将缓冲区内的字符贴到光标所在位置前边
注意:所有与"y"有关的复制命令,都必须与"p"或者"P"配合才能完成复制与粘贴功能
命令方式(撤销):
u 如果您误执行一个命令,可以马上按下u,回返到上一个操作,按多次"u"可以执行多次回复
ctrl + r 反撤消
编译文件:
file 查看文件
strip 去除可调制信息
c与c++:
扩充语法:
动态内存的申请和释放:
C语言(calloc、malloc、realloc、free):
c++ new delete
函数重载:
几个同名函数共存,调用时系统自动根据参数的数量和类型不同,自动以最佳匹配方式判断决定具体调用哪一个,重载函数不以参数名称不用和返回不同来区分,仅以参数的数量和类型来区分,如:
int add(intx,int y);
float add(float x,float y);
float add(float x,float y,float z);
函数模板:
c++系统函数:
标准C++语言函数很多从标准C语言函数继承而来,前边加c字符,为了与语言兼容C语言,也可以用.h后缀的头文件,例子数学库如:
#include
#include <math.h>
类和对象:
2、类与对象.ppt
•将具体问题加以概括,将共性抽象为数据成员和代码成员,并将二者形成一个整体,封装成一个新的数据类型,即类,用class来声明
•类只是一种根据需要建立起来的一种数据结构,并没有申请实质的空间,要使用必须实例化,即用其定义一个具体的类变量,即对象
class Clock
{
public:
Clock(int NewH=0,int NewM=0,int NewS=0)
{
Hour=NewH; //函数的实现放在类定义的内部,函数没有声明为内联函数,但为隐式声明
Minute=NewM;
Second=NewS;
}
Clock(Clock &C);
~Clock();
void SetClock(int NewH,int NewM,int NewS);
void ShowClock();
private:
int Hour; //类的成员变量,私有访问属性
int Minute;
int Second;
};
#include "Clock.h"
#include <iostream>
using namespace std;
Clock::Clock(Clock &C)
{
Hour=C.Hour; //C为Clock类已经存在的对象,用其时间数据初始化新的对象,“.”类的对象获取自己的变量
Minute=C.Minute;
Second=C.Second;
cout<<"Clock(Clock &C)"<<endl;
}
Clock::~Clock()
{
cout<<"~Clock()"<<endl;
}
void Clock::SetClock(int NewH,int NewM,int NewS)
{
Hour = NewH;
Minute = NewM;
Second = NewS;
cout<<"SetClock()"<<endl;
}
void Clock::ShowClock()
{
cout<<"Clock-->"<<Hour<<":"<<Minute<<":"<<Second<<endl;
}
#include "Clock.h"
#include <iostream>
using namespace std;
int main(void)
{
Clock MyClock1;
MyClock1.ShowClock();
MyClock1.SetClock(15,32,41);
MyClock1.ShowClock();
cout<<endl<<endl;
Clock MyClock2(12,13,14);
MyClock2.ShowClock();
MyClock2.SetClock(18,21,19);
MyClock2.ShowClock();
cout<<endl<<endl;
Clock MyClock3(MyClock2);
MyClock3.ShowClock();
MyClock3.SetClock(21,43,28);
MyClock3.ShowClock();
cout<<endl<<endl;
return 0;
}
运行结果:
cgdb使用:
类的内嵌实例:
#include <iosteam>
class MyPoint
{
public:
MyPoint(float NewX=0.0,float NewY=0.0)
{
x=NewX;
y=NewY;
}
MyPoint(MyPoint &p)
{
x=p.x;
y=p.y;
}
float GetX(){return x;}
float GetY(){return y;}
private:
float x,y;
};
class MyDistance
{
public:
MyDistance(MyPoint P1,MyPoint P2);
float GetDist(){return Dist;}
private:
MyPoint p1,p2;
float Dist;
};
#include "distance.h"
#include <cmath>
MyDistance::MyDistance(MyPoint P1,MyPoint P2):p1(P1),p2(P2)
{
float dx,dy;
dx=p1.GetX-p2.GetX;
dy=p1.GetY-p2.GetY;
Dist= squrt(dx*dx+dy*dy);
}
#include "distance.h"
#include <iostream.h>
int main(void)
{
MyPoint p1(3.0,4.0);
MyPoint p2(-2.0,6.0);
MyDistance d(p1,p2);
float L=d.GetDist();
cout<<"L="<<L<<endl;
return 0;
}
g++ -g -o a main.cpp distance.cpp
OBJS = main.o distance.o
BIN = a
CXX ?= g++ #c -> cc
CXXFLAG = -g
RM = rm -rf
$(BIN):$(OBJS)
$(CXX) $(CXXFLAG) $^ -o $@
%.o:%.cpp
$(CXX) -c $< -o $@
clean:
$(RM) *.o $(BIN)
友元:
3、友元.ppt
•通过friend修饰,可以是普通函数也可以是其它类的成员函数,但不是本类的成员函数,在其函数体中可以通过对象名访问类的私有和保护成员
•如果A类为B类的友元类,则A类所有的成员函数都是B类的友元函数,都可以访问B类的私有成员和保护成员
•友元关系不传递,友元关系单向
•友元关系通过对象名直接访问私有隐藏数据,达到高效协调工作目的,但打破封装类对私有成员的保护,绕过成员函数直接对成员数据进行访问,与类的初始定义相违背,使用中注意
友元函数:
class MyPoint
{
public:
MyPoint(float NewX=0.0,float NewY=0.0)
{
x=NewX;
y=NewY;
}
MyPoint(MyPoint &p)
{
x=p.x;
y=p.y;
}
~MyPoint(){}
float GetX();
float GetY();
friend float MyDistF(MyPoint &p1,MyPoint &p2); //声明友元函数
private:
float x,y;
};
#include "point.h"
#include <cmath>
float MyPoint::GetX()
{
return x;
}
float MyPoint::GetY()
{
return y;
}
float MyDist(MyPoint &p1,MyPoint &p2)
{
float dx,dy,L;
dx=p1.GetX()-p2.GetX(); //函数通过参数所属的类提供的共有访问属性的成员函数获取其私有成员变量的数值
dy=p1.GetY()-p2.GetY();
L=sqrt(dx*dx+dy*dy);
return L;
}
float MyDistF(MyPoint &p1,MyPoint &p2)
{
float dx,dy,L;
dx=p1.x-p2.x; //函数被声明为参数所属类的友元函数,可以直接通过类的对象获取私有数据
dy=p1.y-p2.y;
L=sqrt(dx*dx+dy*dy);
return L;
}
#include "point.h"
#include <iostream>
using namespace std;
extern float MyDistF(MyPoint &p1,MyPoint &p2);
int main(void)
{
MyPoint p1(4.0,8.0);
MyPoint p2(-12.0,-10.0);
float L=MyDistF(p1,p2);
cout<<"L="<<L<<endl;
return 0;
}
友元类:
#include <cmath>
class MyPoint
{
public:
MyPoint(float NewX=0.0,float NewY=0.0)
{
x=NewX;
y=NewY;
}
MyPoint(MyPoint &p)
{
x=p.x;
y=p.y;
}
~MyPoint(){}
float GetX(){return x;}
float GetY(){return y;}
friend class MyDistance;
private:
float x,y;
};
class MyDistance
{
public:
MyDistance(MyPoint &x,MyPoint &y):a(x),b(y){}
~MyDistance(){}
float Dist()
{
float dx,dy,L;
dx=a.GetX()-b.GetX();
dy=a.GetY()-b.GetY();
L=sqrt(dx*dx+dy*dy);
return L;
}
float DistF()
{
float dx,dy,FL;
dx=a.x-b.x;//通过MyPoint类的对象直接获取MyPoint类的对象的私有数据(友元类-友元函数)
dy=a.y-b.y;
FL=sqrt(dx*dx+dy*dy);
return FL;
}
private:
MyPoint a,b;
};
#include "distance.h"
#include <iostream>
using namespace std;
int main(void)
{
MyPoint p1(21.0,-33.0); //给出参数
MyPoint p2; //采用默认参数
MyDistance MyDist(p1,p2);
float D=MyDist.Dist();
cout<<"D="<<D<<endl;
float DL=MyDist.DistF();
cout<<"DL="<<DL<<endl;
return 0;
}
动态内存分配:
4、动态内存分配.ppt
C语言(动态内存分配与释放)
#include <stdlib.h>
void *malloc(size_t size); //分配size数量字节的内存空间
void calloc(size_tnmemb,size_t size); //分配nmembsize个字节数量的内存空间
void *realloc(void *ptr,size_t size); //size为重新分配好的动态内存空间大小,按字节算
void free(void *ptr); //释放ptr指向的动态分配的空间
malloc calloc realloc free的使用
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student
{
char name[20];
char sex;
int age;
float avrage;
};
int main(void)
{
/*
char *pt=NULL;
pt=(char *)malloc(16);
for(int i=0;i<=16;i++)
{
pt[i]=i;
}
for(int i=0;i<16;i++)
{
printf("%d",pt[i]);
}
printf("\n");
free(pt);
*/
//********************************************************
struct student *pt=NULL;
pt=(struct student *)calloc(sizeof(struct student),5);
memcpy(pt[0].name,"狗狗",sizeof("狗狗"));
pt[0].sex='F';
pt[0].age=21;
pt[0].avrage=78.32;
memcpy(pt[1].name,"Cat",sizeof("Cat"));
pt[1].sex='M';
pt[1].age=19;
pt[1].avrage=83.26;
memcpy(pt[2].name,"Bear",sizeof("Bear"));
pt[2].sex='M';
pt[2].age=24;
pt[2].avrage=91.00;
for(int i=0;i<3;i++)
{
printf("%s %c %d %.2f\n",pt[i].name,pt[i].sex,pt[i].age,pt[i].avrage);
}
// free(pt);
printf("\n\n");
struct student *pd=NULL;
pd=(struct student *)realloc(pt,sizeof(struct student) * 4);
memcpy(pd[0].name,"板凳",sizeof("板凳"));
pd[0].sex='M';
pd[0].age=22;
pd[0].avrage=89.00;
memcpy(pd[1].name,"老狼",sizeof("老狼"));
pd[1].sex='F';
pd[1].age=26;
pd[1].avrage=73.36;
memcpy(pd[2].name,"耗子",sizeof("耗子"));
pd[2].sex='F';
pd[2].age=24;
pd[2].avrage=97.68;
memcpy(pd[3].name,"豁嘴",sizeof("豁嘴"));
pd[3].sex='M';
pd[3].age=20;
pd[3].avrage=91.00;
for(int i=0;i<4;i++)
{
printf("%s %c %d %.2f\n",pd[i].name,pd[i].sex,pd[i].age,pd[i].avrage);
}
free(pd);
return 0;
}
new与delete
class MyPoint
{
public:
MyPoint(float X=0.0,float Y=0.0){x=X;y=Y;}
MyPoint(MyPoint &p){x=p.x;y=p.y;}
float GetX(){return x;}
float GetY(){return y;}
private:
float x,y;
};
#include "point.h"
#include <cmath>
#include <iostream>
using namespace std;
float Dist(MyPoint &p1,MyPoint &p2)
{
float dx,dy,L;
dx=p1.GetX()-p2.GetX();
dy=p1.GetY()-p2.GetY();
L=sqrt(dx*dx+dy*dy);
return L;
}
int main()
{
MyPoint *pt=new MyPoint(3.0,3.4);
MyPoint *pd=new MyPoint(-20.0,32.0);
float NL=Dist(*pt,*pd);
cout<<"NL="<<NL<<endl;
delete pd;
delete pt;
return 0;
}
#include <iostream>
using namespace std;
int main()
{
//申请基本类型
float *pf=NULL;
pf = new float;
*pf=3.12;
cout<<"*pf:"<<*pf<<endl<<endl;
delete pf;
int *pi=new int(064);//0x64十六进制,064八进制
cout<<"*pi:"<<*pi<<endl<<endl;
delete pi;
//申请数组
int *pc=new int[5]{3,6,9,88,56};
for(int i=0;i<5;i++)
{
cout<<pc[i]<<" ";
}
cout<<endl;
delete []pc;
return 0;
}
继承与派生:
三种方式:public、protect、private
**public共有继承:**基类中的共有和保护成员在子类中保持不变,私有数据子类对象不可访问
**protect保护继承:**基类中的共有和保护成员以保护成员出现在子类中,私有数据子类对象不可访问
**private私有继承:**基类中的共有和保护成员以私有成员出现在子类中,私有数据子类对象不可访问
多态性:
6、多态性.ppt
•同样的消息被不同类型对象接受时导致不同行为,消息即指对类的成员函数的调用,不同行为指不同实现,也就是说调用了不同的函数
•重载多态、强制多态-----专用多态
包含多态、参数多态-----通用多态
运算符重载:
#include <iostream>
using namespace std;
class complex
{
public:
complex(float nreal=0.0,float nimage=0.0) {real=nreal;image=nimage;}
complex(complex &c){real=c.real;image=c.image;}
~complex(){}
void show();
friend complex operator +(complex &a,complex &b);
private:
float real,image;
};
void complex::show(){cout<<real<<"+"<<image<<"i"<<endl;}
complex operator +(complex &a,complex &b)
{
complex temp;
temp.real=a.real+b.real;
temp.image=a.image+b.image;
return temp;
}
#include <iostream>
#include "operator.h"
extern complex operator+(complex &a,complex &b);
int main()
{
complex x(5,9);
complex y(10,-36);
complex v;
v=x+y;
v.show();
return 0;
}
虚函数:
•virtual 函数类型函数名(形参表);
•只能出现在类定义中的函数原型声明中,一般不声明为内连函数,调用需要动态绑定
•经过继承,在派生类中同名覆盖基类中的同名虚函数,实现具体功能
•虚函数的继承是永久性的,也就是说父类声明某个函数为虚函数,在其子类,孙类,孙类的子类一直往下都能被继承,可以实现动态多态,根据实际指向的类型来选择执行的方法
•虚函数由成员函数调用或者是通过指针、引用来访问虚函数,实现的是动态多态,而函数重载和模板函数实现的事静态多态
•不能声明虚构造函数,可以声明虚析构函数:virtual ~函数名();
•虚析构函数的声明能够保证使用基类类型的指针就可以调用适当的析构函数对不同的对象进行清理工作,避免内存泄漏
#include <iostream>
using namespace std;
class base1
{
public:
virtual void display();//虚函数派生类中对其覆盖
};
void base1::display()
{
cout<<"base1::display()!!!!"<<endl;
}
/**********************************************************/
class base2:public base1
{
public:
void display();//与父类中虚函数同名,进行函数体同名覆盖
};
void base2::display()
{
cout<<"dispaly2!!!!"<<endl;
}
/**************************************************************/
class base3:public base2
{
public:
void display();//与父类的父类虚函数同名,进行函数体同名覆盖
};
void base3::display()
{
cout<<"dispaly3!!!!"<<endl;
}
void fun(base1 *ptr)
{ptr->display();}
#include <iostream>
#include "base.h"
int main()
{
base1 b1;
base2 b2;
base3 b3;
fun(&b1);
fun(&b2);
fun(&b3);
return 0;
}
纯虚函数:
•在基类中声明的虚函数,基类中不需要给出其具体的操作内容,要求在各派生类根据实际需要给出各种的定义
•包含纯虚函数的类是抽象类,抽象类不能实例化
•virtual 函数类型函数名(参数表)=0;
#include <cmath>
class base1 //包含纯虚函数,抽象类,无法生成对象
{
public:
virtual void cals()=0;//纯虚函数
};
/*************************************************/
class triangle: public base1
{
public:
triangle(float nx,float ny,float nz)
{x=nx;y=ny;z=nz;}
float gets(){return s;}
virtual void cals();//子类中对父类的同名函数进行覆盖,并实现具体过程(三角形)
private:
float x,y,z;
float s;
};
void triangle::cals()
{
float p;
p=(x+y+z)/2;
s=sqrt(p*(p-x)*(p-y)*(p-z));
}
/***************************************************/
//圆形
class circle:public base1
{
public:
circle(float nr){r=nr;}
float gets(){return s;}
virtual void cals();
private:
float r;
float s;
};
void circle::cals()
{
s=3.14*r*r;
}
#include "line.h"
#include <iostream>
using namespace std;
int main(void)
{
triangle T(3.0,4.0,5.0);
circle C(213.0);
T.cals();
cout<<"ts="<<T.gets()<<endl;
C.cals();
cout<<"cs="<<C.gets()<<endl;
return 0;
}
异常:
7、异常处理.ppt
•throw -> 如果某段程序发现自己不能处理的异常,用throw表达式抛掷该异常给调用者,操作数表示的异常类型语法上与return类似,如果有多个异常要抛掷,则当用不用的操作数以相互区别,
用法:throw 表达式
•try -> try字句后的复合语句是代码保护段,如果预料某段代码或者对某函数的调用有可能发生 异常,将其放在try字句之后,运行时遇到异常,其中的throw表达式会抛掷出该异常
用法:try 复合语句
catch(异常声明) 复合语句
catch(异常声明) 复合语句
•catch -> catch子句后的复合语句是异常处理程序,捕获由throw表达式抛掷的异常。异常声明指明了子句处理异常的类型和异常参数的名称,与函数参数类似,可以是某类型的数值,也可以是引用。当异常被抛掷后,catch子句便以此被检查,执行子句异常声明与抛掷的异常一致的复合语句的异常处理程序。如果异常类型声明为省略号(…)则处理所有类型的异常,该部分在最后一段处理程序。catch异常匹配执行处理后,后边的异常匹配处理将被忽略
#include <iostream>
using namespace std;
float div(int x,int y)
{
if(y==0)
throw y;
return (x/y);
}
int main(void)
{
try{
cout<<"8/9="<<div(5,2)<<endl;
cout<<"99/0"<<div(99,0)<<endl;
cout<<"56/23"<<div(56,23)<<endl;
}catch(int e)
{
cout<<e<<"is error"<<endl;
}
cout<<"okkkkkkkk!!!!"<<endl;
return 0;
}
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
class myException
{
public:
myException(string &nMessage):message(nMessage){}
~myException(){}
string getmyexception(){return message;}
private:
string message;
};
float fun(float a,float b,float c)throw(myException)
{
if(a+b<=c || b+c<=a || a+c<=b)
{
string str="无法构成三角形!!!!!!!!!";
throw myException(str);
}
float p,s;
p=(a+b+c);
s=sqrt(p*(p-a)*(p-b)*(p-c));
return s;
}
int main(void)
{
float a,b,c;
while(true)
{
cout<<"请输入a b c:"<<endl;
cin>>a>>b>>c;
try{
cout<<"s="<<fun(a,b,c)<<endl;
}catch(myException &e)
{
cout<<a<<" "<<b<<" "<<c<<" "<<e.getmyexception()<<endl;
}
cout<<"okkkkkkkkk!!!!!!!!!"<<endl;
}
return 0;
}
字符串string类:
8、字符串string类.ppt
构造函数:
string(); //默认构造函数,建立长度为0的串
string(const string &rts); //复制构造函数
string(const char *s); //用指针s所指的字符串常量初始化string类对象
string(const string &rts,unsigned int pos,unsigned int n); //对象rts中从位置pos开始取n个字符,来初始化string类对象
string(const char *s,unsigned int n); //用指针s所指的字符串前n个字符来初始化string类对象
string(unsigned int n,char c); //将参数c中的字符重复n次,来初始化string类对象
直接接收字符串赋值初始化:
string str=”hello”;
string str1("diaioahdaoidwh");
cout<<"str1:"<<str1<<endl;
string str2(str1);//字符串类的拷贝构造函数
cout<<"str2:"<<str2<<endl;
string str3("1234567890qwertyuiop");
string str4(str3,11,3);//对象rts中从位置pos开始取n个字符,来初始化string类对象
cout<<"str4:"<<str4<<endl;
char pt[]="asdfghjklmnbvcxz";
string str5(pt,8);//用指针所指的前n个字符来初始化string对象
cout<<"str5:"<<str5<<endl;
string str6(6,'S');//将参数c中的字符重复 n次来初始化string
cout<<"str6:"<<str6<<endl;
string str7(6,0x69);
cout<<"str7:"<<str7<<endl;
string str8("123456");
string str9("abcdefg");
str8 +=str9;
cout<<"str8:"<<str8<<endl;
string str10;
str10=str8+str10;
cout<<"str10:"<<str10<<endl;
string str11;
string str12("qwerasd");
str11="wuiyersajbndkjs";
cout<<"str11:"<<str11<<endl;
str11=str12;
cout<<"str11:"<<str11<<endl;
string str13("1234567890qwertyuiop");
cout<<"str13[11]"<<str13[11]<<endl;
string str17("123456zxc");
string str18("123456zx");
bool status1 = (str17>str18);
cout <<"status1="<<status1<<endl;
bool status5 =(str17<str18);
cout<<"status5:"<<status5<<endl;
流类库:
字符串流:
#include <iostream>
#include <iostringstream>//针对字符串的输入输出流
using namespace std;
template <class T>//模板
void to_string(string &s,T &t)
{
ostringstream oss;
oss<<t;//先入
s=oss.str();//再出
}
int main(void)
{
int a=123;
string str1;
to_string(str1,a);
cout<<"str1:"<<str1<<endl;
float f=135.678;
string str2;
to_string(str2,f);
cout<<"str2:"<<str2<<endl;
return 0;
}
宽字符、宽字符串、宽流
问题:每个汉字占用两个字,一个相同汉字在不同编码下有不同的表示,按字节计的string类实际数量与汉字数量不一致,造成处理和观感都带来不便
解决:引入宽字符与宽字符串
C++宽字符关键字为wchar_t,仍然需要用单引号包含,但第一个单引号前需要加大写字母L,例如:wchar_t c=L’人’;
wstring表示宽字符串类型,除了元素是wchar_t类型为,用法与string完全相同,例如:wstring s=L”你好world”;
#include <iostream>
#include <string>
using namespace std;
int main()
{
wchar_t a=L'宣';
wstring b=L"河南原神大学";//宽串
string c("河南原神大学123");
char d[]="河南原神大学123";
cout<<"a:"<<sizeof(a)<<endl;
cout<<"b:"<<b.length()<<endl;
cout<<"c:"<<c.length()<<endl;
cout<<"a:"<<sizeof(d)<<endl;
return 0;
}
容器与模板:
c++模板和容器:
C++重要特点为代码的可重用性
编写的代码独立于任何特定类型的数据,即编写出的代码可以处理任意类型的数据,是为泛型编程
模板为泛型编程基础,有构建不同类型数据对象的类模板、统一处理不同类型数据的函数模板
容器为容纳不同单一数据类型的容器是类模板,实例化后就成为容器类,用容器类定义的对象称为容器对象
#include <iostream>
#include <string>
using namespace std;
template <typename T>
T &max(T &a,T &b)
{
return (a>b?a:b);
}
int main(void)
{
int i=13,j=14;
cout<<"max(13,14):"<<max(i,j)<<endl;
float fi=3.2,fk=3.9;
cout<<"max(3.2,3.9)"<<max(fi,f)<<endl;
string si("abcd");
string sj("ABCD");
cout<<"max(abcd,ABCD)"<<max(si,sj)<<endl;
return 0;
}
#include <iostream>
#include <vector>
#include <string>
using namespace std;
//容器
template <class T>
class Mystack
{
private:
vector<T> elems;
public:
void push(T &elm);
void pop();
T top();
bool empty();
};
//实现功能
template <class T>
void Mystack<T>::push(T &elm)
{
elems.push_back(elm);
}
template <class T>
void Mystack<T>::pop()
{
elems.pop_back();
}
template <class T>
T Mystack<T>::top()
{
return elems.back();
}
template <class T>
bool Mystack<T>::empty()
{
return elems.empty();
}
int main()
{
Mystack<int>intMystack;
Mystack<string>stringMystack;
int a[]={0,1,2,3,4,5};
intMystack.push(a[0]);
intMystack.push(a[1]);
intMystack.push(a[2]);
intMystack.push(a[3]);
intMystack.push(a[4]);
intMystack.push(a[5]);
int temp1=intMystack.top();
cout<<"temp1:"<<temp1<<endl;
intMystack.pop();
intMystack.pop();
intMystack.pop();
int temp2=intMystack.top();
cout<<"temp2:"<<temp2<<endl;
string str0("貂蝉");
stringMystack.push(str0);
string str1("李白");
stringMystack.push(str1);
string str2("孙尚香");
stringMystack.push(str2);
string str3("后裔");
stringMystack.push(str3);
string str4("韩信");
stringMystack.push(str4);
string stemp1=stringMystack.top();
cout<<"stemp1:"<<stemp1<<endl;
stringMystack.pop();
stringMystack.pop();
string status1=stringMystack.top();
cout<<"status1:"<<status1<<endl;
string stemp2=stringMystack.top();
cout<<"stemp2:"<<stemp2<<endl;
stringMystack.pop();
stringMystack.pop();
bool status2=stringMystack.empty();
cout<<"status2:"<<status2<<endl;
return 0;
}
迭代器:
•迭代器是泛化的指针,STL算法利用迭代器对存储在容器中的元素序列进行遍历访问,提供了访问容器中每一个元素的方法
•指针是一种迭代器,但迭代器却不仅仅是指针,迭代器更为抽象,指向容器的一个位置,不需要关心这个位置对应的真正物理地址,只需要通过迭代器访问这个位置的元素
•迭代器是算法和容器的中间人
•STL中容器是封装起来的类模板,内部结构无从知晓,只能通过接口来使用容器,算法函数可以访问容器中指定位置的元素,无需关心元素的具体类型。
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
vector<int> a(10,666);
for(int i=0;i<10;i++)
{
cout<<"a["<<i<<"]="<<a[i]<<endl;
}
cout<<"size0:"<<a.size()<<endl;
a.push_back(77);
a.push_back(7);
a.push_back(8);
for(int i=0;i<13;i++)
{
cout<<a[i]<<endl;
}
cout<<"front:"<<a.front()<<endl;
cout<<"back:"<<a.back()<<endl;
cout<<"size1:"<<a.size()<<endl;
a.push_back(7);
a.push_back(8);
vector<int>::iterator it;//迭代器访问
for(it=a.begin();it!=a.end();++it)
{
cout<<*it<<endl;
}
return 0;
}
OBJS = main.o
BIN = a
CXX ?= g++
CXXFLAS = -g
RM = rm -rf
$(BIN):$(OBJS)
$(CXX) $(CXXFLAS) -o $@ $^
%.o:%.cpp
$(CXX) -o $@ -c $< -std=c++11
clean:
$(RM) *.o $(BIN)
deque容器:
#include <iostream>
using namespace std;
int main(void)
{
deque<string> a;
deque<string> b{"456","asd","@#$"};
deque<string> c(2);
cout<<"a.size:"<<a.size()<<endl;
cout<<"b.size:"<<b.size()<<endl;
cout<<"c.size:"<<c.size()<<endl;
a.push_front("李白");
a.push_front("百里守约");
a.push_front("吕布");
a.push_back("孙策");
a.push_back("大乔");
a.push_back("刘备");
for(int i=0;i<a.size();i++)
{
cout<<"a["<<i<<"]"<<a[i]<<" ";
}
cout<<endl;
a.pop_back();
for(int i=0;i<a.size();i++)
{
cout<<"a["<<i<<"]"<<a[i]<<" ";
}
cout<<endl;
deque<string>::iterator iter;
for(iter=a.begin();iter!=a.end();++iter)
{
cout<<*iter<<endl;
}
return 0;
}
插入:
弹出:
迭代器访问:
map容器:
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main(void)
{
map<char,string> a;
a['1']="xuanxuaxn";
a['r']="后裔";
a['s']="猴子";
a['2']="西施";
map<char,string>::iterator it;
for(it=a.begin();it!=a.end();++it)
{
cout<<it->first<<":"<<it->second<<endl;
}
return 0;
}
泛型编程:
9、泛型编程与标准模板库.ppt
•1、容器(container),容纳包含一组元素的对象,7种基本容器,不同的容器需要包括不同的头文件,例如顺序数组向量
•2、迭代器(iterator),提供顺序访问容器中元素的方法,指针为一种迭代器,使用独立于STL容器的迭代器,需要包含头文件
•3、函数对象(function object),为行为类似函数的对象,可以如同函数一样进行调用,函数对象是泛化的函数,任何普通的函数和重载了括号运算符的类的对象都可以作为函数对象使用,包含头文件,例如negate()为函数对象,negate为类的模板,重载了()运算符,接收一个参数,返回该参数的相反数,int表示negate的()运算符接受和返回参数的类型
•4、算法(algorithm),STL有70多个算法,涵盖很大的应用领域,诸如查找、排序、比较、变换等应有尽有,具有统一性,可以广泛应用于不同的对象和内置数据类型,包含头文件,例如transform为遍历算法
#include <vector>
#include <iterator>
#include <iostream>
using namespace std;
int main(void)
{
vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.push_back(4);
a.push_back(5);
a.push_back(6);
a.push_back(7);
a.push_back(8);
a.push_back(9);
a.push_back(10);
a.push_back(11);
vector<int>::iterator it;
for(it=a.begin();it!=a.end();++it)
{
cout<<*it<<endl;
}
cout<<endl;
vector<int>::reverse_iterator rit;
for(rit=a.rbegin();rit!=a.rend();rit++)
{
cout<<*rit<<endl;
}
return 0;
}
#include <iostream>
#include <numeric>
using namespace std;
int mul(int x,int y)
{
return x*y;
}
int main(void)
{
int a[]={1,2,3,4,5,6,7,8,9};
cout<<accumulate(a,a+8,1,mul)<<endl;
return 0;
}
#include <iostream>
#include <numeric>
using namespace std;
class mulclass
{
public:
int operator()(int x,int y){return x*y;}
};
int main(void)
{
int a[]={1,2,3,4,5,6,7,8};
cout<<accumulate(a,a+8,1,mulclass())<<endl;
return 0;
}
#include <iostream>
#include <numeric>
#include <functional>
using namespace std;
int main(void)
{
int a[]={1,2,3,4,5,6,7,8};
cout<<accumulate(a,a+8,1,multiplies<int>())<<endl;
return 0;
}
算法:
(实例)
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <iterator>
using namespace std;
int main(void)
{
vector<int> a{10,21,33,3,4,654,63,67,534,12};
copy(a.begin(),a.end(),ostream_iterator<int>(cout," "));
cout<<endl;
sort(a.begin(),a.end(),greater<int>());
copy(a.begin(),a.end(),ostream_iterator<int>(cout," "));
cout<<endl;
return 0;
}
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <iterator>
using namespace std;
int main(void)
{
vector<int> a{10,21,33,3,4,654,63,67,534,12};
copy(a.begin(),a.end(),ostream_iterator<int>(cout," "));
cout<<endl;
vector<int>::iterator p=find_if(a.begin(),a.end(),bind2nd(greater<>(int),35));
if(p==a.end())
{
cout<<"没有找到大于35的数字"<<endl;
}else
{
cout<<"大于35的数字为:"<<*
}
cout<<endl;
return 0;
}
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
void print_001(int x)
{
cout<<x<<" ";
}
struct print_002
{
void operator()(int x)
{
cout<<x<<" ";
}
};
int main(void)
{
vector<int> a{1,2,3,4,5,6,7,8,9};
for_each(a.begin(),a.end(),print_001);
cout<<endl;
for_each(a.begin(),a.end(),print_002());
cout<<endl;
for_each(a.begin(),a.end(),print_002());
cout<<endl;
return 0;
}
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
void print_001(int x)
{
cout<<x<<" ";
}
struct print_002
{
void operator()(int x)
{
cout<<x<<" ";
}
};
struct TransText
{
int operator()(int x){return (3*x);}
};
int main(void)
{
vector<int> s{1,2,3,4,5,6,7,8,9,10,11};
vector<int> t;
t.resize(s.size());
vector<int>::iterator si=transform(s.begin(),s.end(),t.begin(),TransText());
for_each(s.begin(),s.end(),print_001);
cout<<endl;
for_each(t.begin(),t.end(),print_002());
cout<<endl;
return 0;
}
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
template<class OutType,class InType>
OutType Convert(InType &T)
{
stringstream stream;
stream<<T;
OutType result;
stream>>result;
return result;
}
int main(void)
{
char f[]="12345.6789";
float ft;
ft=Convert<float>(f);
cout<<"ft:"<<ft<<endl;
int a=123387423;
double da;
da=Convert<double>(a);
cout<<"da:"<<da<<endl;
int b=798842;
string str;
str=Convert<string>(b);
cout<<"str:"<<str<<endl;
return 0;
}