一.需要掌握的知识点
函数的分类(三个标准:库函数和用户自定义函数;有参和无参;/*如果函数没有参数,那么也不能省略括号,其实最好的是写成(void)*/;有返回值和无返回值)
函数的声明和定义
注意:函数不可以嵌套定义
函数的定义:
int fun(int a)
{
return a++;
}
则他的声明就是
int fun(int);//注意那个分号
注意:这里的形参变量名是可以省略的,做题时有时还会认为加上变量名是错的,同时注意如果我们在编程的时候声明语句中的参数有变量名,这个变量名可以与定义的时候的变量名不同
注意:一般的规范格式是声明在主函数前或者主函数中,定义在主函数后面,我们在编程序的时候如果把定义写在主函数前面也可以不要声明
函数的参数
形参(函数定义时在括号里的参数)和实参(代入括号中的参数)
参数的传递分为:值传递(不改变实参的值,实参只是把值赋值给形参,是一个单向传递的过程)和地址传递
关于分配内存:形参时虚拟的,不占用储存单元,形参只在函数内部有效,如果是值传递那么就重新分配一个储存单元,函数返回后占用的空间被释放,如果是地址传递那么就与实参占用同样的储存单元,注意,可以保存下来的是函数中对地址中的那个数据进行的操作
例如
void exchange(int *p1,int *p2)
{
int *t;
t=p1;
p1=p2;
p2=t;//这个地方是对地址进行交换
}
然后再在主函数中答应p1,p2地址中储存的数据,发现并没有调换
注意:实参和形参的数据类型必须兼容,并且以形参的数据类型为主
实参的求值顺序是不确定的,所以尽量在传入的时候避免使用带副作用的运算符(例如++)
函数的返回值
写法:return x ;或者return (x),如果是void类型只能写成return 或者不写
返回的类型:以函数的类型为准
函数只能有一个返回值,并且如果一个函数非void类型,但是在编写的时候没有写return ,那么就会返回一个随机数
函数的调用方式:在函数内部调用另一个函数叫做嵌套,在函数内部直接或间接调用该函数叫递归
外部函数(extern)和内部函数(static),在定义和声明的时候都要加上extern,但是有些编译器在定义函数的时候可以省略extern
常见的例题和常用的函数
计算公因数
int gcd(int a,int b)
{
int re;
if(a%b==0)re=b;
else re=gcd(b,a%b);
return abs(re);
}//辗转相除+递归
还可以用循环
int gcd(int a,int b)
{
int i=1,k;
for(i=1;i<=abs(b)&&i<=abs(a);i++)
{
if(a%i==0&&b%i==0)k=i;
}
return k;
}
计算公倍数
a*b/公约数
判断一个数是不是质数
int prime(int a)
{
int f=1;
int i;
if(a==2)f=1;
else
{
for(i=2;i<=sqrt(a);i++)
if(a%i==0)
{f=0;break;}
}
return f;
}
注意:递归的关键在于将函数表达式写出来,以及推出n=1的结果和第n和第n-1的关系,n-1是精髓
汉诺塔(补充:移动次数为2^n-1)
void hanoi(int n,char from,char temp,char to)
{
if(n==1)movement(n,from,to);
else
{
hanoi(n-1,from,to,temp);/*以C为中介,将A挪到B上*/
movement(n,from,to);/*将第n个盘子从A拿到C上*/
hanoi(n-1;temp,from,to);/*以A为中介,B到C*/
}
void movement(int n,char from ,char to)
{
printf("%d:%c-->%c-->",n,from,to);/*这个函数用来输出*/
}
int main()
{
int n;//表示盘子的总数
hanoi(n,'A','B','C');
}
斐波那契数列
#include<stdio.h>
int main()
{
int n,i,f1=1,f2=1,t;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
if(i>1)
printf(",");//记住这种表示方式,
if(i<3)
printf("%d",f1);
if(i>=3)
{
t=f1+f2;//设置一个变量t 作为这个数列输出的数
f1=f2;//将f2的值赋值给f1,使得下一次循环加数可随着变化
f2=t;//同上
printf("%d",t);
}
}
return 0;
}
以上是不用迭代的方法
如果用到迭代
int fibonacci(int n)
{
int re;
if(n==1||n==2)re=1;
else re=fibbonacci(n-1)+fibonacci(n-2)
return re;
}
利用递归计算阶乘
int jiecheng(int n)
{
int re;
if(n==1||n==0)re=1;
else
re=n*jiecheng(n-1)
}
拆分一个数的约数
void fun(int n,int a[])//定义一个数组来存放所有的约数
{
int k,r;//k表示除数,r 表示约数
for(k=2;k<=sqrt(n);k++)
{
r=n%k;
while(r==0)
{
n/=k;
r=n%k;
}
关于变量
1.变量的属性:包含数据类型和存储属性(生存期和作用域)
2.变量的储存类型:
静态或者动态:区分:定义时修饰语句
static(这个如果修饰全局变量那么这个全局变量只能在该文件中起作用)
在函数中定义static 变量,那么这个函数对这个变量的操作就会保存下来一直到程序结束,形参不可以被定义为static 形式
或者auto(自动储存类别,一般默认的就是这个类型)
局部或者全局:区分:定义的位置
register 寄存器变量,属于动态变量
extern可以用来修饰全局变量,也称外部变量:主要起拓展作用域的作用
3.关于声明和定义:对于外部变量声明的过程中,不可以初始化,除非声明起到定义作用时,(即在函数的外部声明)才可以被初始化
4.变量的性质
变量的生存期(寿命):表示变量占空间的范围,全局变量和静态变量都是从程序开始到程序结束
变量的作用域(可见性):取决于定义变量的位置,并且全局变量的作用于不一定大于局部变量
在函数的复合语句(即())中也可以定义变量,但是其作用域只在复合语句中(我猜想动态局部变量的生存期与作用域相同)
易错知识点
变量被赋初值的阶段:编译,运行;
全局变量或者静态变量在没有被赋初值的时候系统自动为其赋值为0
外部变量虽然属于静态存储方式,但不一定是静态变量
静态局部变量依旧是局部变量,他的生存期是整个程序,但是他的作用域只在这个函数中
auto和register只有在使用时才分配内存
函数的参数是从右到左计算的,
int a=0;
printf("%d,%d",++a,a++);
输出的结果是2,0