程序控制结构
预处理命令
所有的预处理命令在程序中都是以 “ # ” 开头,每一条预处理命令单独占一行,不用分号结束。预处理命令可以出现在程序中任何位置。
宏定义命令
C语言中用#define命令将一个指定的标识符(宏名)来代表一个字符串
#define 标识符 命令串
比如:#define PI 3.14
C++中,增加了const语句来定义符号常量
const 数据类型 变量名 = 常量;
const double PI = 3.14;
C++中,一般推荐用const语句来定义。
define除了可以定义常量之外,还可以用来定义语句,其格式如下:
#define ADD(a,b) ((a) + (b))
计算a+b
#include<cstdio>
#define ADD(a,b) ((a) + (b))
int main()
{
int num1 = 3;
int num2 = 4;
printf("%d",ADD(num1,num2));
return 0;
}
输出结果:7
参考于: const和符号常量define的区别
语句
表达式语句
空语句
仅由一个分号(;)的语句,是一种不做任何操作的语句。
作用:程序中,语法上需要一个语句,但逻辑上并不需要,此时就可以用空语句。
例如,
for(i=1,s=0;i<=10;s+=i,i++);
//求1+2+...+10
最后的分号代表一条空语句,表示循环体不需要执行任何操作。
C++的9种控制语句
① if( )else (条件语句)
② for( )~ (循环语句)
③ while( )~ (循环语句)
④ do~while( ) (循环语句)
⑤ continue (结束本次循环语句)
⑥ break(中止执行switch或循环语句)
⑦ switch (多分支选择语句)
⑧ goto (转向语句)
⑨ return (从函数返回语句)
C语言讲过,简单看看就行。
数组
C++与C语言在数组上,无太大区别。因此就简单复习一下冒泡排序和选择排序算法。
冒泡排序
#include <iostream>
using namespace std;
int main()
{
const int N = 5;
int a[N]={5,6,8,1,4};
int i,j,k,temp;
for(i=0;i<N-1;i++) //N个数字比较N-1次
{
for(j=0;j<N-i-1;j++) //相邻的数字相比较
{
if(a[j]>a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(i=0;i<N;i++)
{
cout<<a[i]<<" "<<endl;
}
}
选择排序
#include <iostream>
using namespace std;
int main()
{
const int N=5;
int a[N]={2,6,1,8,4};
int i,j,k,temp;
for(i=0;i<N-1;i++)
{
k=i;
for(j=i+1;j<N;j++)
{
if(a[k]>a[j])
{
k=j;
}
}
temp=a[k];a[k]=a[i];a[i]=temp;
}
for(i=0;i<N;i++)
{
cout<<a[i]<<" "<<endl;
}
return 0;
}
函数
函数的定义
函数定义的一般形式
[static]
返回值类型 函数名(形参表)
[extern]
{
函数体
}
关键字
关键字“static”表明该函数为静态函数,这类函数仅限文件内使用。
关键字“extern”表明该函数为外部函数,这类函数也可以提供给程序内其他文件的函数进行调用。
返回值类型
"返回类型“可以是char、int、double等,在这些情况下,函数体内必须有return语句;如果函数没有返回值,返回类型应为void,此时,函数体内可以无return语句,或者return语句后什么也不写。
函数名
定义函数名与定义变量名规则一样,尽量避免用下划线开头,因为编译器常常定义一些下划线开头的变量或函数名。尽量做到”望文生义“,
例如:StudentNum(学生学号)采用驼峰式命名
主函数的函数名必须是main()。
形参表
形参(函数形式参数)
对应着,还有无参函数,形参表没有参数。
函数体
花括号里的语句称为函数体。
//设计一个函数,可以计算任意数的阶乘
long fac(int n) //任意数n
{
long f=1;
for(int i=1;i<=n;i++)
f*=i;
retutn f;
}
函数的说明和调用
函数定义和声明不是同一件事情
函数定义是指对函数功能的确立,包括指定函数名、函数类型、形参及其类型、函数体等,它是一个完整的、独立的函数单位。
函数声明的作用则是把函数的名字、函数类型以及形参的个数、类型和顺序(注意,不包括函数体)通知编译系统,以便在对包含函数调用的语句进行编译时,据此对其进行对照检查(例如函数名是否正确,实参与形参的类型和个数是否一致)。
函数调用的格式
常用的函数调用有两种方式:
对于有返回值的函数
变量名 = 函数名(实参表);
对于无返回值的函数
函数名(实参表);
//计算1到10阶乘倒数的和
#include <iostream>
using namespace std;
long fac(int n);
int main()
{
double sum=0.0;
for(int i=1;i<=10;i++)
sum=sum + 1.0/fac(i);
cout<<"sum="<<sum;
return 0;
}
//阶乘函数
long fac(int n)
{
long f=1;
for(int i=1;i<=n;i++)
f*=i;
return f;
}
编写时可以发现,函数可以在后面,但是前面使用时需要先声明。比如long fac(int n)对应着主函数中的sum=sum+1.0/fac(i)。
也可以发现,函数其实挺好用的,写一个函数,调用10次。
函数参数特点
函数形参:在函数未被调用的时候形参不占内存单元。
函数实参:实参必须要有类型,可以是常量,也可以是变量或表达式。
C++要求:函数调用时,函数的实参和形参个数相等,对应类型一致。
函数调用机制
①函数调用前,形参不占用内存单元,函数调用启动时,才临时给形参分配内存单元。
②将实参的值一一对应地传递给形参后,执行被调函数的函数体。
③系统释放形参所占内存单元。
④返回主调函数的调用点。
C++中,函数调用方式有两种,一是传值调用,二是引用调用。
传值调用
(实参传数给形参,形参获得实参的数值),改变形参不改变原先的实参,因为两者在获得值之后没有任何关系。
引用调用
(实参传地址给形参,形参获得实参的地址),改变形参会反映在存储单元中,实参会被改变。
注意:
只有实参传值或者地址给形参!没有形参穿值或者地址给实参的说法!
形参没有确定的值,只能是变量。实参可以是常量、变量、表达式、函数。实参可以是表达式, 但不是“任意”,表达式计算结果的 类型 必须与 形参一致。当然数值不能超界溢出。
一般变量作为函数参数
例题:已知x=3,y=4,用公式d=根号(x^2 + y^2),求d的值。
#include <iostream>
#include <Cmath>
using namespace std;
double f(double x,double y)
{
double z;
x=x*x;
y=y*y;
z=sqrt(x+y);
return z;
}
int main()
{
double f(double x,double y);
double a,b,d;
a=3.0;
b=4.0;
d=f(a,b);
cout<<"a="<<a<<endl;
cout<<"b="<<b<<endl;
cout<<"d="<<d<<endl;
}
运行结果:
a=3
b=4
d=5
可以看出,传值调用的特点是形参值的改变不影响实参。
指针与函数
指针用作参数
指针用作函数有两个特点:
①对于复杂类型,节省时间和空间,提高运行效率。
②方便实现函数之间的效率。
示例:
#include <iostream>
using namespace std;
int fun(int,int*);
int main()
{
int x=5,y=9;
cout<<x<<'\t'<<y<<endl;
fun(x,&y); //注意此处&y取址
cout<<x<<'\t'<<y<<endl;
}
int fun(int a,int *p)
{
a=a*a;
*p/=*p;
cout<<a<<'\t'<<*p<<endl;
}
运行结果:
5 9 //输出x,y的值
25 1 //将x,y的值代入fun()函数中
5 1 //在主函数中输出x,y,可以发现y已经被改变。
在fun()函数中,形参p为指针,调用时,获得将实参y的地址值&y,使得形参指针指向实参变量y,这样,可以通过改变形参指针所指向的实参变量值间接改变实参值,从而实现函数之间的信息传递。
引用作为函数参数
引用定义的语法形式:
类型&引用名(变量名);
或
类型&引用名=变量名;
一般情况下,定义引用时必须初始化,同时引用的类型与变量的类型一致,例如:
int a=3;
int &m=a; //或int &m(a)
此时,m是一个引用,m是变量a的别名。
m就像我们自己都有一个小名,代表的也是我们自己。
例如:m=m+1; //此命令实质上就是a+1
所有在引用上进行的操作,实质上就是在被引用者上的操作。
指向函数的指针和指针函数
main()函数带参数
函数性质
默认函数值
C++中,允许在函数说明或定义时给一个或多个参数指定默认值。
设定规则如下:
①默认参数值的设置是在“函数说明”时进行的。
②默认参数值的设置遵循“靠后有值”原则。即当某个参数有默认值时,其后的参数必有默认值。
例如:
int fun(int a,int b=2,int c=5)
int fun(int a,int b=2,int c)
第二行就是错的,没有遵循靠后有值的原则。
感觉没啥意思,代码写规范点可以避免的,就做做考题吧。
函数设置默认的参数值示例:
#include <iostream>
using namespace std;
int fun(int a=1,int b=3,int c=5)
{
cout<<a<<'\t'<<b<<'\t'<<c<<endl;
}
int main()
{
fun();
fun(4);
fun(4,6);
fun(4,6,8);
}
输出结果:
1 3 5
4 3 5
4 6 5
4 6 8
编译器按照从左到右的顺序将实参和形参结合,当实参的数目不足时,编译器将按同样顺序使用定义中的默认值来补足所缺少的实参。
一句话总结就是:从左至右,有就改,没就默认值。
内联函数
函数重复调用有利于提升开发效率,但是一旦函数调用频率过高,或者对于一些函数体比较小、比较简单的,多次调用,明显开销变大,效率就会降低。
因此为了节省这些开销,就引入了内联函数,在编译时将函数体嵌入调用处。
语法格式
inline 返回值类型 函数名(形参表)
{
函数体
}
使用时注意的问题
①内联函数体不宜过大(5行左右),且要结构简单。不允许出现循环语句和开关语句,也不能出现递归。
②内联函数的定义必须出现在第一次被调用之前。(这个和函数不太一样)
③对内联函数不能进行异常接口声明。
④内联函数适合被频繁调用的小函数。
示例:
求5个数的最大值。要求编写并调用一函数实现2个数的较大值。
#include <iostream>
using namespace std;
inline int max(int x,int y)
{
if(x>y)
return x;
else
return y;
}
int main()
{
int a=34,b=56,c=22,d=100,e=88,m;
m=max(a,b);
m=max(m,c);
m=max(m,d);
m=max(m,e);
cout<<"max="<<m<<endl;
}
运行结果:
max=100
函数重载
赋予同一函数名称多个含义
最常见但是又不容易发现的,可能思维定势吧
例如:<<和>>,C语言学的时候明明就是按位与和按位或的符号,一个移位符号;而在C++中,它们却代表着输出和输入的符号。这就是运算符的重载,这里暂时不多说,有兴趣自行百度学习。
定义重载函数时,要求同名函数的参数表必须有差异,而对返回值的类型没有要求。重载函数的参数表差异有:参数的个数不同,或者至少有一个参数的类型不同。调用函数时,系统会根据实参与形参的个数和类型进行匹配,自动确定调用哪个函数。
函数的重载也称为多态函数。函数的重载一般出现在功能相近的函数之间。
递归函数
递归函数又叫自调用函数,其特点就是在函数内部直接或间接地自己调用自己。
递归调用分为直接调用和间接调用两种方式。
直接递归调用是指在一个函数中实现调用自身的过程。
间接递归调用则是指在一个函数中调用其他函数,而在其他函数中又调用了本函数。
利用函数的递归调用,可以实现将复杂问题简单划,让计算机去执行简单问题的多次调用。
示例:用递归来算算这个
斐波那契数列:前两项数据均为1,以后的每项都是前两项之和。
#include <iostream>
using namespace std;
long F(unsigned n)
{
if(n==0||n==1)
return 1;
else
return F(n-1)+F(n-2);
}
int main()
{
cout<<F(8)<<endl;
}
运行结果:
34
标识符的作用域
存储类
ps:还有点东西没时间写,赶着6级。为复习而用,比较粗糙。如有错误,欢迎指正!