C/C++培训
达内IT学院
400-996-5531
大家都知道C++有两种成功的学习方式,一种是直接从高强度的编程实践入手,另一种是从基本要素入手,但是殊途同归。本文主要从实践入手同时也会穿插一些理论知识来帮助大家备考C++期末考试。由于文章篇幅有限,小编就只能帮大家梳理下主干知识了。当然本文也可以为没有接触过C++的同学提供一些入门的方法,接下来小编就按照先C语言再C++附带小技巧和C++学习意义的顺序带你进入美妙的编程之旅,期末复习助攻来了!
C语言第一讲
像汉语英语中的疑问句陈述句一样,C语言也有它的基本语句(顺序语句此处略)。
1.if条件语句用法:if(条件){怎么怎么样;}else if(条件){怎么怎么样;}else{怎么怎么样;}根据问题的需要,你可以多次使用或不使用if,else if,else语句。
2.for循环语句用法:for(变量初始值;循环条件;该次循环后变量的变化){怎么怎么样;}意为:当变量的初始值满足循环条件时执行循环,完成该次循环后变量变化,若变化后的变量仍满足循环条件,继续循环,直到变量不满足循环条件。
3.while循环语句用法:while(循环条件){怎么怎么样;},该语句可理解为简化的for语句。
4.do-while循环语句用法:do{怎么怎么样;}while(循环条件);意为:先执行循环(至少会执行一次),再判断循环条件,若满足继续循环,若不满足跳出循环。
5.continue语句用法:放入循环语句中,跳过其后未执行的语句。
6.switch语句用法:C语言还提供了另一种用于多分支选择的switch语句, 其一般形式为:switch(表达式){case 常量表达式1:语句1;case 常量表达式2:语句2; …;case 常量表达式n:语句n;default:语句n+1;}意为:先计算表达式的值。 并逐个与其后的常量表达式值相比较,当表达式的值与某个常量表达式的值相等时, 即执行其后的语句,然后不再进行判断,继续执行后面所有case后的语句(如果你在该语句后面加了“break;”那如果满足判断条件后,除该语句其他语句就不再执行)。如表达式的值与所有case后的常量表达式均不相同时,则执行default后的语句。
7.break语句用法:在switch语句中用来跳出switch执行其后的语句,在循环语句中则是用来跳出所在的封闭循环。
8.goto语句用法:它可以将程序的运行引流到事先用标识符标识的程序段。goto因为降低了程序的可读性不被大家熟知,不过有时候它能比break更快捷的跳出循环,举例如下。输出两个小于十并且乘积为64的自然数:…for(int i=1;i<10;i++){for(int j=1;j<10;j++)if(i*j)=64} goto End;}End:cout<<i<<””<<j;…其中End就为标识符。
C语言第二讲
接下来讲函数,有数学基础函数还是好学的,函数原型和参数什么的大家都耳熟能详了,下面讲一下函数部分的常考点。
1.递归函数的使用(比如求斐波那契数列前几项和)和递归函数非递归化都是常考的。就以斐波那契数列的C++实现为例:…int fb(int ){if(n<0){return -1;}if(n==0||n==1){return 1;}return fb(n-1)+f(n-2);},以下是该程序段的非递归化:int fb(int n){if(n<0){return -1;}if(n==0||n==1){return 1;}int a=1;int b=1;int c;for(int i=2;i<=n;i++){c=a+b;a=b;b=c;}return c;}…
2.内联函数的使用,内联函数用类似宏定义(优于宏定义)的作用减少了函数的调用,提高程序执行的效率(缺点是仅适用于少部分的而且以代码膨胀来换取速度)比如:…inline int max(int m,int n){return m>n? m:n;}…编译器看到inline后为这个短小的max函数创建一段代码,之后max的每次调用都用该段代码来替换(注意而不是调用)。名词解释,宏定义:C语言提供的三种预处理功能之一,比如# define N 6(放在主函数前)意为N用6替代。
3.重载函数的使用。C语言的函数如果在返回类型,参数类型,参数个数,参数顺序上有不同,则认为函数就不同,这样就可以在函数的返回类型,参数类型,参数个数,参数顺序上动动手脚,这样你就可以把一些函数名字都取成一样的,多省事。
C语言第三讲
第三讲是数组,数组也有下列几个常考点。
1.冒泡排序(从小到大排序)。为了帮助大家掌握,下面给出详细的实现及注释。
void bubble(int a[],int size)
{int i, t;
for (int round=1;
round<size;round++)//size为实现初始化好的数组a含有的元素个数,共比较size-1回合(比如说只有两个元素只需比较一个回合)
{for (i = 0; i<size - round; i++)//比较一回合
if (a[i + 1] < a[i]){ //如果第二个元素比第一个元素小,交换两元素位置
t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;}}
for (i = 0; i < size; i++)//比较一次后两元素谁小就先输出谁
cout << a[i] << endl;
2.插入排序。为了帮助大家掌握,下面给出详细的实现及注释。
void isort (int a[],int size){//size是你要排序的元素个数,存在于事先初始化好的数组a中
int inserter,index;//inserter是插入元素,index是每个元素的下标
for(int i=1;i<size;i++){
inserter=a[i];
index=i-1;
while(index>=0&&inserter<a[index])
{a[index+1]=a[index];//如果元素比插入元素大则后挪一个位置
Index--;}
a[index+1]=inserter;// 两层含义:1. 如果元素比插入元素大,则元素后挪一个位置之后,插入元素前挪一个位置。2.如果元素比插入元素小则把插入元素挪到元素后面
//如此循环直至这i+1个数按照升序排好
for(int j=0;j<size;j++){比较一轮就把所有元素输出一次
cout<<a[j]<<”,”;
if(j==i)//排序过后的数与未排序的以“|”分界
cout<<’|’;}
cout<<endl;}}
3.接下来讲容易被忽略的二维数组,二维数组与一维数组最大的不同在于它的每一个元素都需要两个下标才能标识。这里以用二维数组实现矩阵的乘法为例:
for(int i=0;i<arow;i++)//arow为数组a的行数
for(int j=0;j<bcol;i++)//bcol为数组b的列数
{c[i][j]=0;
for(intn=0;n<acol;n++) //acol为数组a的列数或数组b的行数c[i][j]+=a[i][n]*b[n][i];}
其中a和b都是事先初始化好的数组,比如int a[2][3]={{1,2},{4}}意为:1,2,0初始化了a[0][0],a[0][1],a[0][2,],4,0,0初始化了a[1][0],a[1][1],a[1][2]。
C语言第四讲
接下来第四讲,指针和结构
本来打算数组那里再讲一下Josephus问题的,因为指针和结构内容不多,就把指针,结构,Josephus问题和动态内存分配一块讲了。Josephus问题(报数出圈问题)的一个实现如下:
struct jose//这是一个结构,它抽象了一个小孩,一个“小孩”里面有三个变量来描述这个小孩,code是这个小孩的编号,*next是这个小孩用来指向下一个小孩的指针,*pre是这个小孩用来指向上一个小孩的指针
{int code;
jose*next;// 这里的*next就是一个名叫next的指针,它的类型是jose(只要是结构都得 。就像贸大的地址是北京市朝阳区惠新东街十号一样,*next可以理解为一个地址,可以说是一个“门牌号”,这个“门牌号”就是“*next”指针。有了指针,编译器就能按照指针这个“门牌号”在内存空间上找到对应的变量,数组,函数等。
jose*pre;};//同上
int main(){//赋初值
int numOfBoys, interval;
cout << "please input the number of boys,\n" //numOfBoys为小孩数
<< "interval of counting:\n";//报数报到interval的出圈
cin >> numOfBoys >> interval;
//下列建立小孩结构数组
jose*pJose = new jose[numOfBoys];//这就是动态内存分配,通过new(新建)这个函数,在堆上新建了一个数组,与一般新建数组不同的是,动态内存分配一定要配备一个delete[]函数来释放内存,见本程序段末尾。
jose*pCurrent = pJose;//当前节点指针
初始化结构数组:构成环链,小孩编号,输出编号
int itemsInLine = 0;//输出项数,为了避免每一行输出的数字太多,可不加
for (int i = 1; i <= numOfBoys; i++){
pCurrent->next = pJose + i%numOfBoys;//链到下一个元素
pCurrent->code = i;//小孩编号
pCurrent = pCurrent->next;//改变当前位置
if (itemsInLine++ % 10 == 0)
cout << endl;
cout << setw(4) << i;}//pCurrent此时等于pJose
itemsInLine = 0;
jose*pivot = NULL;//链表哨兵
pCurrent = &pJose[numOfBoys - 1];//下一个就是数组的第一个元素pJose[0]
while (pCurrent->next != pCurrent){//处理未获胜的所有小孩
for (int j = 0; j < interval; j++)//数interval个数
{pivot = pCurrent;
pCurrent = pivot->next;}
if (itemsInLine++ % 10 == 0)//输出小孩
cout << endl;
cout << setw(4) << pCurrent->code;
pivot->next = pCurrent->next;//小孩脱链
/*pCurrent = pivot;*/}
cout << "\n\nthe winner is " << pCurrent->code << endl;//输出获胜者
delete[]pJose;//释放堆空间内存
system("pause");//防止DOS窗口一闪而过的函数,后面会说到的}
//细心的读者已经发现,上面也包括了单向链表的知识嘻嘻
问题补充:有的同学问了,为什么要有delete[]函数?先说下程序的内存区域。一个程序将操作系统分配给其运行的内存块分为四个区域:1.代码区2.全局数据区3.堆区4.栈区,栈区存放局部变量,在函数退出后,其中的局部变量随之消失,而堆区中存放的全局变量就不同,为了保证足够内存,就要用到该函数释放内存(这和析构函数一个道理)。
C语言第五讲
C语言第五讲,文件读取与写入
文件读取与写入方法很多,下面提供小编经常接触的一种。
1.读取文件:
fstreaminput;//定义一个input对象,fstream是类名,随后讲到
string str[c];定义一个c个元素的数组
input.open(“…”);//括号内为要读取的文件位置,比如“D:\\uibe\\sales.txt”。
while (!input.eof()){
getline(input, str[i],',');//将文本的内容以逗号为间隔全部读入数组
i++;//记录行数
}input.close();//读取文件以后一定要把文件关闭
2.写入文件:
ofstream stat(“…”); //定义一个stat对象,括号内为要写入东西的文件位置
stat <<“…”<<…//“<<”后的就为你写入该文件的东西,你可以写字符串(字符串加“”号)或者是数据等
好的!C语言的部分就结束啦!小编喝口茶先~
其实小编讲C语言的时候用的仍然是I/O流,为此在这里附上printf函数和scanf函数的使用方法,便于大家掌握原始C语言的输入输出。
一、printf()函数
printf()函数的调用格式为:printf("格式化字符串", 输出项1,输出项2,…);
其中格式化字符串包括正常字符(这些字符将按原样输出)和格式化规定字符(以"%"开始, 后跟一个或几个规定字符,用来确定输出内容格式)
1.格式化规定符
符号作用
%d十进制有符号整数
%u十进制无符号整数
%f浮点数
%s字符串
%c单个字符
%p指针的值
%e指数形式的浮点数
%x, %X无符号以十六进制表示的整数
0%无符号以八进制表示的整数
%g自动选择合适的表示法
温馨提示
(1). 可以在"%"和字母之间插进数字表示最大长宽。
例如: %3d表示输出3位整型数, 不够3位右对齐。%9.2f 表示输出场宽为9的浮点数, 其中小数位为2, 整数位为6,小数点占一位, 不够9位右对齐。%8s表示输出8个字符的字符串,不够8个字符右对齐。另外,若想在输出值前加一些0, 就应在长宽项前加个0。例如%04d表示在输出一个小于4位的数值时,将在前面补0使其总宽度为4位。如果用浮点数表示字符或整型量的输出格式,小数点后的数字代表最大宽度,小数点前的数字代表最小宽度。例如%6.9s表示显示一个长度不小于6且不大于9的字符串。若大于9,则第9个字符以后的内容将被删除。
(2). 可以在"%"和字母之间加小写字母l,表示输出的是长型数。
例如:%ld表示输出long整数%lf表示输出double浮点数。
(3). 可以控制输出左对齐或右对齐,即在"%"和字母之间加入一个"-" 号可说明输出为左对齐,否则为右对齐。
例如:%-7d 表示输出7位整数左对齐,%-10s 表示输出10个字符左对齐。
2. 一些特殊规定字符
字符作用
\n换行
\f清屏并换页
\r回车
\tTab符
\xhh表示一个ASCII码用16进表示(其中hh是1到2个16进制数)
二、scanf()函数
scanf()函数是格式化输入函数, 它从标准输入设备(键盘) 读取输入的信息。
其调用格式为:scanf("格式化字符串",地址1,地址2,…);
格式化字符串包括以下三类不同的字符:
1.格式化说明符: 格式化说明符与printf()函数中的格式说明符基本相同。
2.空白字符: 空白字符会使scanf()函数在读操作中略去输入中的一个或多个空白字符。
3.非空白字符: 一个非空白字符会使scanf()函数在读入时剔除掉与这个非空白字符相同的字符。地址表是需要读入的所有变量的地址, 不是变量本身。这与printf()函数完全不同, 要特别注意。各个变量的地址之间同","分开。
温馨提示
(1). 对于字符串数组或字符串指针变量, 由于数组名和指针变量名本身就是地址, 因此使用scanf()函数时, 不需要在它们前面加上"&"操作符。
例1:
mian(){
char *p, str[20];
scanf("%s", p);//从健盘输入字符串
scanf("%s", str);
printf("%s\n", p);//向屏幕输出字符串
printf("%s\n", str);}
(2). 可以在格式化字符串中的"%"各格式化规定符之间加入一个整数, 表示任何读操作中的最大位数。
例1中若规定只能输入10字符给字符串指针p,则第一条scanf() 函数语句变为scanf("%10s", p);程序运行时一旦输入字符个数大于10, p就不再继续读入, 而后面的一个读入函数即scanf("%s", str)就会从第11个字符开始读入。 注意,在使用上述两个函数时要记得加上头文件stdio.h哦。
接下来就是C++的面向对象的程序设计部分,小编觉得C++讲的就是C没有的,大家觉得呢?
说类得先说对象,所谓对象就是类的实例,而所谓类就是一种抽象,比如上面讲到的Josephus问题,其中的小孩就被抽象成了只有编号code,该小孩用来指向下一个小孩的指针*next和该小孩用来指向上一个小孩的指针*pre三个元素的“小孩”类,类的实例比如这群被抽象了的小孩中的每一个小孩,小孩1,小孩2…就是对象,下面通过具体的编程帮助大家更好地理解类。
C++第一讲
基于对象的程序设计(为啥不是面向对象?请往后看)该讲小编用经典的复数类同时讲解类,运算符重载,友元函数和拷贝构造函数。
//以下是类的声明:
#ifndef _COMPLEX_INCLUDE_ //#ifndef…#define……#endif是C++的一种预处理,可以防止程序被多次编译
#define _COMPLEX_INCLUDE_
#include <iostream>
class ComplexNumber{ //ComplexNumber就是一个类,它是复数类,它被抽象成了两部分:实部和虚部,下文的ComplexNumber c1(1,2),ComplexNumber c2(3,4)就是复数类的实例,也就是对象
private: //私有成员定义,一个类包含私有成员和公有成员(有的还有保护成员)
double real;//实部
double imaginary;//虚部
public: //公有成员定义
ComplexNumber():real(0),imaginary(0){}//构造函数,无返回值,初始化复数
ComplexNumber(double r,double i):real(r),imaginary(i){}//构造函数,给复数赋值
ComplexNumber(const ComplexNumber& c);//拷贝构造函数:在C++中,当一个对象需要通过另外一个对象进行初始化时,利用拷贝构造函数不但复制了对象从而初始化另外一个对象,也复制了对象的堆内存空间,对象们各有各的空间,内存资源管理好,程序也就不会出现错误(如下图)
void Print();//输出复数
friend ComplexNumber operator+(ComplexNumber &c1,ComplexNumber &c2);//这里有两个考点:
1.运算符重载(这里重载了加号):运算符是函数,但是重载运算符时除了不能更改运算顺序和优先级以外,参数和返回类型都可以重新定义,即重载。重载的形式为:返回类型 operator 运算符(参数表);
2.友元函数:注意到该函数是一个友元函数,它可以访问类的私有(或保护)数据成员,这里是 double real(实部),double imaginary(虚部),进而提高了程序的效率。延伸出去还可以把一个类定义成友元类哦
#endif
//以下是复数类的实现
#include "Complex.h" //包含头文件
ComplexNumber::ComplexNumber(const ComplexNumber &c){
std::cout<<"Copying......"<<std::endl;
this->real = c.real;
this->imaginary = c.imaginary; }
void ComplexNumber::Print(){
std::cout<<real
<<(imaginary>=0?"+":"")
<<imaginary<<"i"<<std::endl;}
ComplexNumber operator+(ComplexNumber &c1,ComplexNumber &c2){
std::cout<<"operator +"<<std::endl;
ComplexNumber temp;
temp.real = c1.real+c2.real;
temp.imaginary=c1.imaginary+c2.imaginary;
return temp;}
//以下是复数类的调用
#include <iostream>
#include "Complex.h"
using namespace std;
int main1(){
cout<<"Hello Operator!"<<endl;
ComplexNumber c1(1,2);
ComplexNumber c2(3,4);
c1.Print();
c2.Print();
ComplexNumber c3 = c1+c2;//友元函数实现操作符重载
c3.Print();
return 0;}
C++第二讲
面向对象的程序设计,类的继承,虚函数(覆盖),和多态性
#include <iostream>
using namespace std;
class Shape{//这是一个抽象类图形类,即包含纯虚函数的类,不能创建抽象类的对象protected://保护成员
double x,y;//坐标
public://公有成员
Shape(double x, double y){//初始化坐标
this->x = x;
this->y = y;}
virtual double GetArea()=0;//这是一个纯虚函数,纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”
virtual ~Shape(){}//“~ 类名”即为析构函数,原理同C语言中的delete[],同时它也是一个纯虚函数
};
class Circle: public Shape//这就是类的继承:老爸是Shape图形类,儿子是Circle圆形类,public代表公有继承,即儿子可以访问老爸的公有,保护成员但是不能访问老爸的私有成员
private:
double radius;//半径
public:
Circle(double x, double y, double r) :Shape(x,y),radius(r){}
virtual double GetArea(){//纯虚函数在子类中的实现,这就叫覆盖(override)
return 3.14*radius*radius;
virtual ~Circle(){}//纯虚析构函数在子类中的实现,纯虚函数在子类中的实现就实现了C++的多态性,多态性是C++的核心,一句话说的好“若语言不支持多态,则不能成为面向对象的。只能成为基于对象”。
………
………
有同学可能想知道除公有继承以外的继承,在这里贴上类继承方式表格:
继承方式父类的public成员父类的protected成员父类的private成员
private继承变为private成员变为private成员子类不可访问
protected继承变为protected成员变为protected成员子类不可访问
public继承变为public成员变为protected成员子类不可访问
C++第三讲
C++常考点第三讲,模板。首先用模板函数引入模板这个概念。
#include <iostream>
using namespace std;
//以下是实现输出两个字符或数值变量最大值的模板函数
template <typename T> T max2(T a, T b){//这就是模板函数,此时该函数的返回类型是模板型,参数表也是模板变量(变量前加“T”)。如果你想让一个函数的返回值或者一个变量是多种类型比如数值或字符,但是又不能同时定义一个既是字符又是数值的变量,你就可以把它定义为模板变量,此时函数必须定义为模板函数(前加“template <typename T1,typename T2…>”)
return a>b? a:b;}//这里的a,b就是模板变量,他们可以是字符,也可以是数值(整型,浮点型等)
template <typename T1,typename T2> void Print(T1 v1, T2 v2){
cout<<v1<<" "<<v2<<endl;
}
int main(){
cout<<"Hello template!"<<endl;
cout<<max2(100,200)<<endl;//这时模板变量是整型的,函数返回值也是整型
cout<<max2(100.55,200.66)<<endl;//这时模板变量是浮点型的,函数返回值也是浮点型
cout<<max2('A','a')<<endl;//这时模板变量是字符型的,函数返回值也是字符型
Print(3.14, 100); //<double, int> 同理,print()函数同时输出了浮点型和整型,模板是不是很方便?
Print('A',5.6); //<char, double>
return 0; }
了解模板的用法后,把它迁移到类上,你就会使用模板类了。
噗!本文一共一万一千一百三十七个字符!小编已吐血!!本来想着再写一下多重继承,FILE指针的,静态成员,双向链表blablabla……但小编觉着能把以上内容看懂个大概,其他知识点什么的都是浮云了嘻嘻。
温馨提示
C++常用小技巧:
1.有时候编译程序DOS窗口会一闪而过,这时你可以在主程序最末加上system(“pause”)(如果有return 0,加在return 0之前)。
2.为了最大限度保证编译通过,main()函数最好写成int main(int argc,char*argv[])。
3.每次使用一个函数时,不光要知道它的用法,还要记得查它要求的头文件。
4.一个语句或者一个程序段结束后记得加上分号“;”(至于“{}”编译器会自动生成),细节决定成败。
5.对知识永远要保持一颗敬畏,若渴的心态。
最后问下大家,学习了C语言你可以干什么?或者说你为什么要学C语言?
小编觉得学C++还是收益良多的,首先编程就像魔术一般酷,学好了你不仅有个好成绩,妹子们遇到难题的时候你还可以挺身而出,学到一定程度你还可以用MFC制作并发布一些windows程序比如制作贷款计算器、小游戏并分享给其他人,如果你需要运营微信平台的话,这时你还可以选择开发者模式,让你的微信平台更出类拔萃,更深入一些你可以考个C++编程二级证书,这对你将来的发展有好处。C++作为一门用途广泛的编程语言,学会之后还能让你在学习其他计算机语言或者使用软件是提供便利,比如java编程,swift编程,matlab使用等。如果可能的话,你甚至可以像facebook创始人扎克伯格一样制作出一个受万人追捧的程序。
填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!
Copyright © 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有
Tedu.cn All Rights Reserved