C语言复习笔记(四)函数

今天呢,我们来一起复习函数部分,其实我感觉啊,函数是最简单的部分了,只要你前面有好好学,函数就是一小块一小块的,和写普通代码没什么两样,就是x^2+6-y 与f(x)的关系啦,如果多次使用到一个长长和函数表达式,这时就不妨用f(x)代替啦。

第四章 函数

上一章传送门:数组

下一章传送门:指针&结构体

先举个例子:

#include <stdio.h>
int main()
{	void print_star();			//声明print_star函数
	void print_message();		//声明print_message函数
	
	print_star();				//调用print_star函数
	print_message();			//print_message函数
	print_star();				//调用print_star函数
	return 0;
}

void print_star()				//定义print_star函数
{	printf("*******----*******\n");	//输出一行*号
}

void print_message()			//定义print_message函数
{	printf("Good morning!\n");	//输出一行文字信息
}

C语言复习笔记(四)函数_第1张图片
看到这个你可能会说,啊啊啊小编你个笨蛋,还不如我直接写的简单呢,用函数干嘛呢。但是,你想想,如果给你100个名字,让你给每人说一句早安,你还要一个一个打一遍吗,这就是一个简单的例子。

函数的定义:

(1) 指定函数的名字,以便以后按名调用。
(2) 指定函数的类型,即函数返回值的类型。
(3) 指定函数的参数的名字和类型,以便在调用函数时向它们传递数据。对无参函数不需要这项。
(4) 指定函数应当完成什么操作,也就是函数是做什么的,即函数的功能。这是最重要的,是在函数体中解决的。

函数有三种形式,分别为

1.定义无参函数

类型名  函数名(void)
{
	函数体
}

2.定义有参函数

类型名  函数名(形式参数表列)
{
	函数体
}

3.定义空函数

类型名  函数名()
{ }
//函数体为空,什么也不做。

第三个形式我们都很少见到,我也不知道做不做要求,但前两个必须熟记。

函数的调用

函数调用的形式为:
函数名(实参表列)

print_star();	//调用无参函数
c=max(a,b);	//调用有参函数

调用函数有以下三点:
1.函数调用语句
把函数调用单独作为一个语句。如printf_star();
这时不要求函数带回值,只要求函数完成一定的操作。
2. 函数表达式
函数调用出现在另一个表达式中,如c=max(a,b);
这时要求函数带回一个确定的值以参加表达式的运算。
3. 函数参数
函数调用作为另一个函数调用时的实参。如m=max(a,max(b,c));,又如:printf (″%d″, max (a,b));

实参和形参间的数据传递

例:输入两个整数,要求输出其中值较大者。要求用函数来找到大数。

#include <stdio.h>
int main()
{	int max(int x,int y);		//对max函数的声明
	int a,b,c;
	printf("please enter two integer numbers:");  //提示输入数据
	scanf("%d,%d",&a,&b);	//输入两个整数
	c=max(a,b);	//调用max函数,有两个实参。大数赋给变量c
	printf("max is %d\n",c);	//输出大数c
	return 0; 
	}
	
int max(int x,int y)	//定义max函数,有两个参数
{
	int z;		//定义临时变量z
	z=x>y?x:y;	//把x和y中大者赋给z
	return(z);		//把z作为max函数的值带回main函数
}

解析:
定义函数,名为max,函数类型为int。指定两个形参x和y,形参的类型为int。

主函数中包含了一个函数调用max(a,b)。max后面括号内的a和b是实参。a和b是在main函数中定义的变量,x和y是函数max的形式参数。通过函数调用,在两个函数之间发生数据传递,实参a和b的值传递给形参x和y,在max函数中把x和y中的大者赋给变量z,z的值作为函数值返回main函数,赋给变量c。
C语言复习笔记(四)函数_第2张图片C语言复习笔记(四)函数_第3张图片
实参可以是常量,变量或表达式
1.在定义函数中制定的形参,在没有出现函数调用时,它们不占内存中的存储单元。在发生函数调用时,函数的形参被临时分配内存单元
2.将实参的传递给形参。
3.在执行函数时,由于形参已经有值,可以用形参进行计算。
4.通过return语句将函数值带回到主函数,如果函数不需要返回值,则不需要return语句
5.调用结束后,形参被释放掉。实参仍保留原值,不发生改变。
注意:实参向形参的数据传递是“值传递”,单向传递只能实参传给形参,不能由形参传给实参
C语言中函数实参传递给形参,实参与形参是从右向左结合;
在调用函数过程中发生的实参与形参间的数据传递称为“虚实结合”。

函数的返回值

通常,希望通过函数调用使主调函数能得到一个确定的值,这就是函数值(函数的返回值)

(1) 函数的返回值是通过函数中的return语句获得的。一个函数中可以有一个以上的return语句,执行到哪一个return语句,哪一个return语句就起作用。return语句后面的括号可以不要,如“return z;”与“return(z);”等价。return后面的值可以是一个表达式。
(2) 函数值的类型。函数值的类型在定义函数时指定
(3) 在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致。
如果函数值的类型和return语句中表达式的值不一致,则以函数类型为准。对数值型数据,可以自动进行类型转换。即函数类型决定返回值的类型
(4) 对于不带回值的函数,应当用定义函数为“void类型”(或称“空类型”)。这样,系统就保证不使函数带回任何值,即禁止在调用函数中使用被调用函数的返回值。此时在函数体中不得出现return语句

int max (float x,float y)	//函数值为整型
char letter (char c1,char c2)	//函数值为字符型
double min (int x,int y)	//函数值为双精度型

对被调用函数的声明和函数原型

例:输入两个实数,用一个函数求出它们之和。

#include <stdio.h>
int main()
{	float add(float x, float y);		//对add函数作声明
	float a,b,c;
	printf("Please enter a and b:");	//提示输入
	scanf("%f%f",&a,&b);			//输入两个实数
	c=add(a,b); 					//调用add函数
	printf("sum is %f\n",c);			//输出两数之和
	return 0;
}

float add(float x,float y)		//定义add函数
{	float z;
	z=x+y;
	return(z); 			//把变量z的值作为函数值返回
}

解析:
函数的声明和函数定义中的第1行(函数首部)基本上是相同的,只差一个分号(函数声明比函数定义中的首行多一个分号)。
函数的首行(即函数首部)称为函数原型(function prototype)。
因为在函数的首部包含了检查调用函数是否合法的基本信息(它包括了函数名、函数值类型、参数个数、参数类型和参数顺序),因此,在函数调用时检查函数原型是否与函数声明一致。这样就能保证函数的正确调用。
C语言复习笔记(四)函数_第4张图片

函数的嵌套调用

例:输入4个整数,找出其中最大的数。用函数的嵌套调用来处理。

#include <stdio.h>
int main()
{	int max4(int a,int b,int c,int d);	//对max4的函数声明
	int a,b,c,d,max;
	printf("Please enter 4 interger numbers:");	//提示输入4个数
	scanf("%d %d %d %d",&a,&b,&c,&d);		//输入4个数
	max=max4(a,b,c,d); //调用max4函数,得到4个数中的最大者
	printf("max=%d \n",max);	//输出4个数中的最大者
	return 0;
}


int max4(int a,int b,int c,int d)	//定义max4函数 
{	int max2(int a,int b);		//对max2的函数声明
	int m;
	m=max2(a,b);	//调用max2函数,得到a和b中的大者,放在m中
	m=max2(m,c);//调用max2函数,得到a,b,c中的大者,放在m中
	m=max2(m,d);//调用max2函数,得到a,b,c,d中的大者,放在m中
	return(m);	//把m作为函数值带回main函数
}

int max2(int a,int b)	//定义max2函数 
{	if(a>=b)
		return a;		//若a≥b,将a作为函数返回值 
	else
		return b;		//若a
}

解析:
在主函数中要调用max4函数,因此在主函数的开头要对max4函数作声明。在max4函数中3次调用max2函数,因此在max4函数的开头要对max2函数作声明。由于在主函数中没有直接调用max2函数,因此在主函数中不必对max2函数作声明,只须在max4函数中作声明即可。
max4函数执行过程: 第1次调用max2函数得到的函数值是a和b中的大者,把它赋给变量m,第2次调用max2得到m和c中的大者,也就是a,b,c中的最大者,再把它赋给变量m。第3次调用max2得到m和d中的大者,也就是a,b,c,d中的最大者,再把它赋给变量m。这是一种递推方法,先求出2个数的大者;再以此为基础求出3个数的大者;再以此为基础求出4个数的大者。m的值一次一次地变化,直到实现最终要求。
C语言复习笔记(四)函数_第5张图片

程序改进

(1) 可以将max2函数的函数体改为只用一个return语句,返回一个条件表达式的值:

int max2(int a,int b)	//定义max2函数 
{return(a>=b?a:b);}	//返回条件表达式的值,即a和b中的大者

(2) 在max4函数中,3个调用max2的语句可以用以下一行代替:

m=max2(max2(max2(a,b),c),d);	//把函数调用作为函数参数

甚至可以取消变量m,max4函数可写成

int max4(int a,int b,int c,int d) 
{	int max2(int a,int b);		//对max2的函数声明
	return max2(max2(max2(a,b),c),d);
}

先调用“max2(a,b)”,得到a和b中的大者。再调用“max2(max2(a,b),c)”(其中max2(a,b)为已知),得到a,b,c三者中的大者。最后由“max2(max2(max2(a,b),c),d)”求得a,b,c,d四者中的大者。

函数的递归调用

所谓递归调用,就是:在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。

int f(int x)
{
	int y,z;
	z=f(y);	//在执行f函数的过程中又要调用f函数
	return (2*z);
}
递归调用又分为直接调用和间接调用,如下形式

C语言复习笔记(四)函数_第6张图片
程序中不应出现无终止的递归调用,而只应出现有限次数的、有终止的递归调用,这可以用if语句来控制,只有在某一条件成立时才继续执行递归调用;否则就不再继续

例:有5个学生坐在一起,问第5个学生多少岁,他说比第4个学生大2岁。问第4个学生岁数,他说比第3个学生大2岁。问第3个学生,又说比第2个学生大2岁。问第2个学生,说比第1个学生大2岁。最后问第1个学生,他说是10岁。请问第5个学生多大。
C语言复习笔记(四)函数_第7张图片

#include <stdio.h>
int main()
{	int age(int n);					//对age函数的声明
	printf("NO.5,age:%d\n",age(5)); 	//输出第5个学生的年龄
	return 0;
} 
//注意分析递归的终止条件。
int age(int n) 						//定义递归函数
{	int c; 						//c用作存放函数的返回值的变量
	if(n==1) 						//如果n等于1
		c=10;					//年龄为10
	else 							//如果n不等于1
		c=age(n-1)+2;			//年龄是前一个学生的年龄加2(如第4个学生年龄是第3个学生年龄加2)
	return(c); 					//返回年龄
}

该函数执行的过程如下:
C语言复习笔记(四)函数_第8张图片C语言复习笔记(四)函数_第9张图片
再举一个例子:用递归方法求n!
在这里插入图片描述

#include <stdio.h>
int main()
{	int fac(int n);		//fac函数声明
	int n;
	int y;
	printf("input an integer number:");
	scanf("%d",&n);	//输入要求阶乘的数
	y=fac(n);
	printf("%d!=%d\n",n,y);
	return 0;
}
//注意分析递归的终止条件
int fac(int n) 				//定义fac函数
{
	int f;
	if(n<0)				//n不能小于0
		printf("n<0,data error!");
	else if(n==0||n==1)	//n=0或,1时n!=1
		f=1;				//递归终止条件
	else
		f=fac(n-1)*n;	 //n>1时,n!=n*(n-1)
	return(f);
}

C语言复习笔记(四)函数_第10张图片
注意:
程序中的变量是int型,如果用Visual C++、GCC以及多数C编译系统为int型数据分配4个字节,能表示的最大数为2 147 483 647,当n=12时,运行正常,输出为479 001 600。如果输入13,企图求13!,是得不到预期结果的,因为求出的结果超过了int型数据的最大值。可将f,y和fac函数定义为float或double型。

一维数组名作函数参数

例:有两个班级,分别有35和30名学生,调用average函数,分别求这两个班的学生的平均成绩。

#include <stdio.h>
int main()
{	float average(float array[],int n);
	float score1[5]={98.5,97,91.5,60,55};	//定义长度为5的数组
	float score2[10]={67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5};
	//定义长度为10的数组
	printf("The average of class A is %6.2f\n",average(score1,5));
	//用数组名score1和5作实参
	printf("The average of class B is %6.2f\n",average(score2,10));
	//用数组名score2和10作实参
	return 0;
}

float average(float array[],int n) //定义average函数,未指定形参数组长度
{	int i;
	float aver,sum=array[0];
	for(i=1;i<n;i++)
		sum=sum+array[i];	    //累加n个学生成绩
	aver=sum/n;
	return(aver);
}

注意:
用数组名作函数实参时,不是把数组元素的值传递给形参,而是把实参数组的首元素的地址传递给形参数组,这样两个数组就共占同一段内存单元。
在这里插入图片描述
C语言复习笔记(四)函数_第11张图片

多维数组名作函数参数

例:有一个3×4的矩阵,求所有元素中的最大值。

#include <stdio.h>
int main()
{	int max_value(int array[][4]);		//函数声明
	int a[3][4]={{1,3,5,7},{2,4,6,8},{15,17,34,12}};	 //对数组元素赋初值
	printf("Max value is %d\n",max_value(a));
	//max_value(a)为函数调用
	return 0;
}

int max_value(int array[][4])	//函数定义
{	int i,j,max;
	max=array[0][0];
	for(i=0;i<3;i++)
		for(j=0;j<4;j++)
			if(array[i][j]>max) max=array[i][j];	//把大者放在max中
	return(max);
}

解析:
形参数组array第1维的大小省略,第2维大小不能省略,而且要和实参数组a的第2维的大小相同。在主函数调用max_value函数时,把实参二维数组a的第1行的起始地址传递给形参数组array,因此array数组第1行的起始地址与a数组的第1行的起始地址相同。由于两个数组的列数相同,因此array数组第2行的起始地址与a数组的第2行的起始地址相同。a[i][j]与array[i][j]同占一个存储单元,它们具有同一个值。实际上,array[i][j]就是a[i][j],在函数中对array[i][j]的操作就是对a[i][j]的操作。
C语言复习笔记(四)函数_第12张图片
ok函数的复习到这里就结束了,明天是最后一天了喔,哈哈哈,终于要去复习完了,坚持就是胜利呀。

明天我们复习第五章 结构体&指针

你可能感兴趣的:(笔记)