2017.11.13 在C语言中是否能用函数实现模块化程序设计

第七章 用函数实现模块化程序设计

(1)为什么要用函数?
@function既是函数也是功能。函数就是用来完成一定功能的的(函数就是功能),函数名就是给这个功能起一个名字,一个C程序可由一个主函数和若干个其他函数构成。

所有的函数都是平行的,即在函数定义时是分别进行,是互相独立。

例题://输出以下结果,用过调用函数实现 
/*
***********
How are you!
*********** 
*/
 
#include<stdio.h>
int main()
{
	void print_star();		//声明void print_star()函数 
	void print_message();	//声明void print_message函数 
	print_star();			//调用print_star函数 
	print_message();		//调用print_message函数 
	print_star();		   //用print_star函数 
	return 0;
 } 
 void print_star()      //定义void print_star函数,这里后面不能有";"符号 
 {
 	printf("****************\n");
 }
 void print_message()	//定义void print_message函数		
 {
 	printf("How are you!\n");   //输出一行文字信息 
 }

(2)怎样定义函数
@在程序中若用到数学函数【如:sqrt、fabs、sin cos等】必须在文本开头写上(#include<math.h>)

函数的定义包括以下几个内容
1.指定函数的名字,以便以后按名调用。
2.指定函数类型,即函数值返回类型。
3.指定函数的名字和类型,在调用时向他们传递数据。
4.指定函数应当完成什么操作,也就是函数应该做什么,就是函数的功能。

定义函数的方法:

1.定义无参函数:
一般形式为:   
	类型名  函数名()         类型名   函数名(void)
	{                       {
		函数体       或            函数体     //包括声明部分和语句部分
	}                       }
函数名后面括号内的void表示“空”即函数没有参数


2.定义有参函数:
一般形式为:								例如:定义max函数
类型名     函数名(形式参数表列)				int max(int x,int y);
{											{   int z;
	函数体                                      z=x>y?x:y;
												return (z);
}                                           }


3.定义空函数(先占用一个位置,后面在编写好的程序放上去)
一般形式为:
类型名  函数名()
{}
 例如:  void dummy()
 {}
 
 【merge():合并 ; matproduct():矩阵相乘 ;  concatenate():字符串连接; shell(): 希尔排序】

(3)调用函数

1.一般形式为:
     函数名(实参表列)//若是无参函数,则实参表列可以没有,但是括号不能省
        例如:  print_star();        //调用无参函数
               c=max(a,b)//调用有参函数

2.    3种函数调用方式
	函数调用语句 、函数表达式、函数参数	

3.函数调用时的数据传递
	形式参数和实际参数、实参和形参间的数据传递。
	
4.函数的调用过程
5函数的返回值
   它是通过return语句获得
   函数值的类型
   再定义函数时指定的函数类型一般应该和return语句中的表达式类型一致
   **(如果函数值的类型和return语句中表达式的值不一样,以函数类型为准)

(4)对被调用函数的声明和函数原型:
*函数的首行(即函数的首部)成为函数的原型,使用函数原型作声明是C语言的一个重要特点。
*函数的定义是指对函数功能的确立,包括函数名,函数值类型、形参及其类型以及函数体等,他是一个完整的、独立的函数单位。

函数声明有两种:
1.函数类型   函数名(参数类型1   参数名1,参数类型2  参数名2.....);
2.函数类型   函数名(参数类型1,参数类型2,.....);

(5)函数的嵌套使用:
@C语言的函数定义是相互平行的、独立的,也就是说,在定义函数时,一个函数不能再定义另一个函数就是不能嵌套定义,但可以嵌套使用。

例题1://输入4个整数,找出其中最大的数。用函数嵌套调用来处理。
//方法一:
#include<stdio.h>
int main()
{
	int max(int r,int x,int y,int z);
	int a,b,c,d,e;
	printf("请输入4个整数:");
	scanf("%d,%d,%d,%d",&a,&b,&c,&d);
	e=max(a,b,c,d);
	printf("最大的数为:%d\n",e);
	return 0;
 } 
 int max(int r,int x,int y,int z)
 {
 	int m,n,l;
 		m=r>x?r:x;
	    n=m>y?m:y;
	    l=n>z?n:z;
		return (l);
 }

//方法二:
/* 
#include<stdio.h>
int main()
{
	int max4(int a,int b,int c,int d);//对max4函数的声明 
	int a;
	int b;
	int c;
	int d;
	int max;
	
	printf("请输入4个整数:");
	scanf("%d,%d,%d,%d",&a,&b,&c,&d);
	
	max=max4(a,b,c,d);       //调用max4函数,得到4个数中的最大者 
	printf("最大的数为:%d\n",max);
	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=max2(m,d);
	return (m);
 }
 int max2(int a,int b)
 {
 	if(a>=b)
 	return a;
 	else
 	return b;
 }
 */ 

(6)函数的递归调用
在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。运用递归调用必须有一个递归结束条件

例如1:直接调用本函数举例
int f(int x)
{
	int y,z;
	z=f(y);//在执行f函数的过程中又要调用f函数
	return (2*z);
}

例题2:/*有五个学生坐在一起,
问第五个学生多少岁,他说比第四个学生大两岁。
问第四个学生岁数,他说比第三个大两岁。
问第三个学生,又说比第二个大两岁。
问第二个学生,他说比第一个大两岁。
最后问第一个学生,他说他十岁。
请问第五个学生多少岁? 
*/

//递归过程 
/*
int age(int n)
{
	int c;
	if(n==1)
		c=10;
	else
		c=age(n-1)+2;
	return(c);
}
*/

#include <stdio.h>
int main()
{
	int age(int n);
	printf("NO.5,age:%d\n",age(5));  //输出 
	return 0;
}

int age(int n)		//定义递归函数 
{
	int c;
	if(n==1)		//n=1时,年龄为10 
		c=10;
	else
		c=age(n-1)+2;		//n!=1时,年龄是前一个学生的年龄加2 
	return (c);
}
//递归调用4次,
例题3://利用递归算法求n!

#include<stdio.h> 
int main()
{
	int fac(int n); //fac 函数声明 
	int n;
	int y;
	printf("input 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;
	return (f);
}

(7)数组作为函数参数
调用有参函数,需要提供实参。可以是常量、变量或着表达式。数组元素也可以作为函数实参。
【数据传递方向是从实参到形参,单向传递。】

1.数组元素作为函数实参,不能作为形参。
例题1://输入 10个数,要求输出其中值最大的元素和该数是第几个数。
 
#include<stdio.h> 
int main()
{
	int max(int x,int y);
	int a[10];
	int m;
	int n;
	int i;
	printf("enter 10 integer numbers:");
	for(i=0;i<10;i++)
	scanf("%d",&a[i]);
	printf("\n");
	for(i=1,m=a[0],n=0;i<10;i++)
	{
		if(max(m,a[i])>m)
		{
			m=max(m,a[i]);
			n=i;
		}
	}
	printf("The largest number is %d\n it is the %dth number.\n",m,n+1);
}
int max(int x,int y)
{
	return (x>y?x:y);
}


2.数组名作函数参数
【用数组元素做实参时,向形参变量传递是数组元素的值,而用数组名作函数实参时,向形参传递的是数组首元素的地址】
例题2://有一个一维数组score,内放10个学生成绩,求平均成绩
 
#include<stdio.h>
int main()
{
	float average(float array[10]);   //函数声明 
	float score[10];
	float aver;
	int i;
	printf("enter 10 scores:\n");
	for(i=0;i<10;i++)
		scanf("%f",&score[i]);
	printf("\n");
	aver=average(score);				//调用average函数 
	printf("average score is %5.2f\n",aver);
	return 0;
 } 
 float average(float array[10])   //定义average函数 
 {
 	int i;
 	float aver,sum=array[0];
 	for(i=1;i<10;i++)
 		sum=sum+array[i];   //累加学生成绩 
 	aver=sum/10;
 	return(aver);
  } 

例题3://有两个班级,分别有35名和30名学生,调用一个average函数,分别求这两个班级的学生的平均成绩。
//为了简化,分别设着两个班的人数为5和10 

#include<stdio.h>
int main()
{
	float average(float array[],int n);
	float score1[5]={98.5,97,91,60,55};
	float score2[10]={67,88,99,69,77,89,76,54,60,99};
	printf("The average of class A is %6.2f\n",average(score1,5));
	printf("The average of class B is %6.2f\n",average(score2,10));//用数组名score1和5做实参
	return 0; 
 }
 
 float average(float array[],int n)
 {
 	int i;
 	float aver,sum=array[0];
 	for(i=1;i<n;i++)
 	sum=sum+array[i];
 	aver=sum/n;
 	return(aver);
  }
   
3.多维数组名做函数参数
在被调用函数中对形参数组定义时可以制定每一维大小,也可以省略第一维的大小说明
例题://有一个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;
 	int j;
 	int 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];
 	return (max);
 }

(8)局部变量和全局变量
从变量的作用域来(从空间)看可分为全局变量和局部变量。

局部变量:在复合语句内定义的,复和语句不能在外面用的就是局部变量。形式参数也是局部变量。
全局变量:在函数之外定义的外部变量是全局变量。

(9)变量的存储方式和生存期
变量的存储方式分为两类:

1.动态存储方式:是在程序运行期间需要进行动态的分配存储空间的方式【形式参数、自动变量、现场保护和返回地址】
2.静态存储方式:在程序运行期间有系统分配固定的存储空间的方式。【全局变量全部放在这里】

3.存储空间又分为三类:程序区、静态存储区和动态存储区【存放数据】。

*变量的存在时间称之为生存期。
*【每一个C语言都包含的属性有:数据的类型、数据存储类别。】

1.存储类别指的是数据在内存中存储的方式(如静态存储方式和动态存储方式)
2.c的存储类别分为四种:自动的auto 、静态的static、寄存器的 register、外部的 extern
局部变量的存储类别(auto static)
1.在调用该函数时,系统会给这些变量分配存储空间,在函数调用结束时会自动释放这些存储空间,这就是自动变量。auto可以隐藏不写;它存储在动态存储区中
2.局部变量的值在函数调用结束后不消失而继续保留原值,及其占用的存储单元不释放,就是静态存储变量。
3.将局部变量的值存储在CPU的寄存器中,需要用时直接从寄存器中取出参加运算
posted @ 2017-11-13 22:48  LegendQi  阅读(766)  评论(0编辑  收藏  举报