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

/*
* 为什么要用函数:
*   提前设计好函数用来实现不同的功能,编写程序过程中就可以直接调用这些函数,避免重复编写
*   函数就是功能,每一个函数用来实现一个特定的功能,函数的名字应该反应期望代表的功能
*   1、一个c程序由一个或者多个程序模块组成,每一个程序模块作为一个源程序文件,一个源程序文件可以为多个c程序公用
*   2、一个源程序文件是一个编译单位,程序编译时以一个源程序为编译单位,而不是一个函数为单位。
*   3、c程序的执行都是从main函数开始的,也从main函数结束
*   4、函数之间可以互相调用,但是不可以调用主函数,main函数是被操作系统调用的
*   5、从用户的角度看,函数一共由两种,库函数和自己定义的函数
*      库函数:系统提供,用户不必自己定义,可以直接使用他们,不同编译系统提供的库函数可能有所不同,但许多基本函数还是共同的
*      用户自己定义的函数,他用来解决用户需要的函数
*   6、从函数形式上看,函数一共分为两种无参函数和有参函数
*      无参函数:main函数不需要给调用函数传递参数数据,一般用来执行指定的一组操作
*      有参函数:调用函数时,向调用函数传递数据,一般执行点用函数后会得到一个函数值返回到主函数中使用,此时有参函数应该定义为与返回值同一个类型
* 怎样定义函数:
*            1、指定函数的名字,便于调用
*            2、指定函数的类型,即函数返回值的类型
*            3、指定函数的参数的名字和类型,调用函数时方便向他们传递数据,无参函数不需要
*            4、指定函数应该完成什么操作,也就是函数的功能,这是最重要的
*      定义函数的方法:
*            定义无参函数:  类型名 函数名()//或者 类型名  函数名(void)//void表示空
*                            {
*                                 函数体//包括声明部分和语句部分
*                                            }
*            定义有参函数:   类型名  函数名(形式参数列表)
*                            {
*                                 函数体//包括声明部分和语句部分
*                                        }
*            定义空函数:    类型名   函数名()
*                               {
*                                           }
* 调用函数:
*      调用函数的形式:函数名(实参表列)
*          1、函数调用语句:
*             把调用函数单独作为一个语句,这时函数不要求带回值,只要求函数完成一定操作
*             max(a,b);
*          2、函数表达式:
*             函数调用出现在另外一个表达式中,要求函数带回一个确定的值来参加表达式的运算
*             c=2*max(a,b);
*          3、函数参数
*             函数调用,作为另一个函数的实参;
*             m=max(a,max(b,c));
*      调用函数时的数据传递:
*          1、形式参数和实际参数(两者类型相同或者兼容)//单向传递
*             定义函数时()里的变量名称为形式参数;
*             调用函数时()里的是实际参数;可以是常量,变量,表达式,但是必须要有固定的值
*          2、形式参数和实际参数之间的数据传递
*             系统会自动把实际参数的值传递给形式参数,这个值在哈桑农户调用期间有效,并且参与运算;
*      调用函数的过程:
*          1、在定义哈桑农户中的形参时,在未出现函数调用时,他们并不占用内存中的储存单元,在函数发生调用时,才分配内存空间
*          2、将实参的值传递给对应形参;
*          3、执行调用函数时,形参已经有值,所以可以直接运算
*          4、通过return,把函数值带回主调函数,返回值类型因该与函数类型一致;如果函数不需要返回值,函数类型应该定义为void类型
*          5、调用结束形参单元被释放(实参仍然保持原值,形参的值改变不会影响到实参的值);
*      函数的返回值:
*          通常,希望通过一个函数调用使主函数得到一个确定的值,这就是函数返回值。
*          函数返回值通过return语句获取,不需要返回值可以没有return语句
*          可以有一个以上的return语句,执行到哪一个就返回哪一个函数值;
*      函数值的类型:(与调用函数的类型相同)
*          int a(float a,float b)//返回值为整型
*          char b(char a,char b)//返回值为字符型
*          double a(int x,int y)//返回值为双进度型
*      定义函数时,return语句中表达式的类型应该和调用函数的类型相同
*      对于不带返回值的函数,定义为void类型
*  对被调用函数的声明和函数原型:
*      在一个函数中调用另一个函数需要具备以下条件:
*        1、函数必须是已经定义的函数;
*        2、库函数必须引用头文件
*        3、使用自己定义的函数,如果调用函数在主函数之后,在主函数中要进行声明
*           (使用函数原型做声明是C语言的一个重要特点)形参名可写可不写,是什么都无所谓
*            在主函数之前做了声明,在各函数调用中不用重复声明
* 函数的镶套调用:
*         调用函数内不能定义另外一个函数但是可以引用
* 数组作为函数参数:
*    数组元素作为实参
*    一维数组名作为参数:除了数组元素外,还可以用数组名作为函数参数(包括实参和形参)
*                        数组元素做实参传递的是数组元素的值,数组名做函数实参,传递的是数组首元素的地址
*                        实参类型与形参类型应该保持一致
*                        形参首元素地址和实参首元素地址具有同一地址,指同一个单元
*                        形参数组可以不指定大小:int arr[];
*                        因为实参和形参首地址相同,所以可以通过改变形参来改变实参;
*   多维数组名做函数参数:多维数组元素可以作为函数参数
*                         在调用函数中,对形参定义时可以只定义一维的大小
*                         int brr[3][10];或int brr[][10];
* 局部变量和全局变量:
*    局部变量:一个在函数内部定义的变量只在函数范围内有效,只有能在函数内部才能引用他们,在此函数外不能使用这些变量;
*              在复合语句内定义的变量只能在复合语句中使用,在复合语句({多个语句})外不能使用这些变量;
*              定义变量的三种情况:
*                              在函数开头定义;
*                              在函数内的复合语句定义;
*                              在函数外部定义;
*              主函数中定义的变量只在主函数中有效,不能因为是在主函数中定义就在整个文件中有效;
*              不同函数可以使用同名的变量,两者之间互不干扰;
*              形式参数也是局部变量;
*              在函数内部,复合语句中也可以定义变量,这些变量只在本复合语句中有效;
*    全局变量:在函数之外定义的变量是外部变量,是全局变量,全局变量,可以为本文件其他函数共用,有效范围是定义变量开始到本源文件结束;
*              在函数内定义的是局部变量,在函数外定义的是全局变量;
*              增加了函数之间的联系,相当于各个函数之间有了直接的传输通道,由于函数调用只能带回一个返回值,因此可以使用全局变量来增加函数之间的联系渠道
*              不建议使用
*              原因:1、全局变量在程序执行过程中都要占用存储单元,而不是在需要时开辟单元;
*                    2、通用性降低,函数中如果引用了全局变量,那么执行情况会受到有关外部变量的影响,函数如果转移到另外一个文件中,有关全局变量也要转移
*                       可能会出现与其他变量重名的情况,降低了程序的可靠性和通用性,通常要求模块功能要单一,与外界相互联系尽量少,通过实参,形参的形式和外界联系
*                       这样的程序可读性强,移植性好。
*                    3、全局变量过多会降低函数的清晰性,各个函数执行时都有可能改变全局变量的值,程序容易出错
*              全局变量和局部变量同名,在局部变量作用范围内,局部变量有效,全局变量被屏蔽,不起作用。
*变量的储存方式和生存周期:
*   动态存储方式和静态存储方式
*              静态:在程序运行期间由系统分配的固定的存储空间的方式
*              动态:在程序运行期间,根据需要进行动态的分配存储空间的方式
*              内存中供用户使用的存储空间的情况:
*               1、程序区
*               2、静态存储区
*               3、动态存储区
*              全局变量存放在静态存储区,在程序开始时分配,程序结束释放
*              动态存储区存放以下内容:
*              1、函数的形式参数:在调用函数时给形参分配存储空间
*              2、在函数定义中没有用到关键字static声明的变量,即自动变量
*              3、函数调用时现场保护和返回地址等
*              每一个变量和函数都有两个属性:数据 类型和数据的存储类别;
*              C语言的数据存储类别:
*              自动的,静态的,寄存器的,外部的
*              根据变量的存储类别可以知道变量的作用域和生存周期;
*   局部变量的存储类别
*              1、自动变量(auto):动态存储区
*                         函数中的局部变量如果不声明是static存储类别,都动态的分配存储空间,函数的形参和函数定义的局部变量都是,调用函数时分配空间,调用结束,释放空间,这一类局部变量称为自动变量
*              2、静态局部变量(static):静态存储区
*                         函数调用结束后不消失,保留原值,占用的存储单元不释放,下一次调用时,变量已经有值,这时指定该局部变量为静态局部变量(static)
*              3、寄存器变量(rigister):cpu的寄存器
*                         如果一些变量使用频繁,则允许将变量的值存放在寄存器中,可以提高执行效率
*   全局变量的存储类别:(静态存储区)
*              1、在文件内扩展外部变量的作用域
*                 exterm,将外部变量的作用域扩展到此位置
*                 可以不指定类型,因为不是定义,是引用
*              2、将外部作用域扩张到其他文件
*                extern 两个文件都要使用同一个外部变量时,在其中一个定义,另外一个用extern引用
*              3、将全局变量作用域限制在本文件中
*                用static定义外部变量,在另一个文件用extern中引用,不能成功,被限制在本文件中
*       static 声明一个变量的作用:
*              1、对局部变量,把他分配在静态存储区域,在程序执行期间,分配空间不释放,始终存在。
*              2、对全局变量,该变量的作用域限制在本文件。
*   存储类别小结:
*       对一个数据的定义需要两方面:数据类型,存储类别
* 关于变量的声明和定义:
*                     把建立存储空间的声明叫做定义,把不需要建立存储空间的叫做声明。
* 内部函数和外部函数:
*                     函数的本质上是全局的,定义一个函数的目的就是为了方便调用,不添加声明,则表示函数可以被本文件的函数调用也可以被其他文件调用
*                     根据函数是否能被其他源文件调用分为两个:外部函数和内部函数。
*            内部函数:函数只能被本文件中的函数调用。(静态函数)
*                      static 类型名 函数名
*                      优点:使函数局部化,其他文件包含能引用,提高了可靠性。
*            外部函数:定义函数时在最左端加关键字extern,则是外部函数,可以供其他文件调用
*                      extern 类型名 函数名
*/
 

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<math.h>
#include<string.h>
//在主函数之前做了声明,在各函数调用中不用重复声明
int max1(int x, int y);
int max2(float x, float y);
void xingxing();
void aini();
float sum(float x, float y);

//int main()
//{
//	char c[] = "asdfghjj";
//	for (int i = 0; i < 4; i++)
//	{
//		scanf("%c", &c[i]);
//
//	}
//	printf("%s", c);
//}


//递归求n!
int jiecheng(int x)//三种情况,>0;<0;=0;
{
	if (x < 0)
	{
		return 0;
	}
	else if (x == 0)
	{
		return 1;
	}
	else
	{
		return jiecheng(x - 1) * x;
	}
}
//第一个学生10岁,每个比前一个大2岁,求第五个学生多大
int wu(int x)
{
	return x += 2;

}

//输入两个小数比较较大者,输出整数;
int max2(float x, float y)
{
	return x > y ? x : y;
}

//输出特定文字
void xingxing()
{
	printf("************************\n");
}
void aini()
{
	printf("i love you\n");
}

//输出两个整数,要求输出其中值较大者
int max1(int x, int y)
{
	int z;
	z = x > y ? x : y;
	return z;
	
	//return x > y ? x : y;
}
//找出两个数中最小的
int min(int x, int y)
{
	return x < y ? x : y;
}
//有一个3*4的矩阵,求所有元素的最大值
int shuzuzuida(int a[][4])
{
	int max = a[0][0];
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			if (max < a[i][j])
			{
				max = a[i][j];
			}

		}
	}
	return max;
}

//有一个一维数组,内存放10个学生的成绩,写一个函数,当主函数调用后能求出平均分,最高分,和最低分
//定义全局变量
float max=0;
float min1=0;
//有一维数组score内存放10个学生的成绩,求平均成绩
//两次调用数组长度不同
float pingjun(float arr[], int x)
{
	float sum = 0;
	float k;
	max = arr[0];
	min1 = arr[0];
	for (int i = 0; i < x; i++)
	{
		sum += arr[i];
		if (max < arr[i])
		{
			max = arr[i];
		}
		if (min1 > arr[i])
		{
			min1 = arr[i];
		}
	}
	k = sum / x;
	return k;
}
//考察静态局部变量的值
int f(int a)
{
	int b = 0;
	static int c = 3;//c的值不发生改变,存储单元不释放;
	b = b + 1;
	c = c + 1;
	return (a + b + c);
}
//输出1-5的阶乘
int jie(int x)
{
	static int n=1;//n不释放,避免调用重新赋值
	n *= x;
	return n;
}

int main()//主函数调用函数
{
	//输出1-5的阶乘
	for (int i = 1; i < 6; i++)
	{
		printf("%d ", jie(i));
	}
	//考察静态局部变量的值
	int a = 2;
	for (int i = 0; i < 3; i++)
	{
		printf("%d\n", f(a));
	}
	//有一个一维数组,内存放10个学生的成绩,写一个函数,当主函数调用后能求出平均分,最高分,和最低分,
	float d[10];
	for (int i = 0; i < 10; i++)
	{
		scanf("%f", &d[i]);
	}
	pingjun(d,10);
	printf("%f %f %f", min1, max, pingjun(d, 10));
	//有一个3*4的矩阵,求所有元素的最大值
	int c[3][4] = { {1,2,3},{9,8,7},{6,7,5} };
	printf("%d", shuzuzuida(c));
	//输出两个整数,要求输出其中值较小者
	int a, b;
	scanf("%d %d", &a, &b);
	printf("%d ", min(a, b));
	//用选择法对数组中的十个整数按照由小到大进行排序
	int brr[10];
	for (int i = 0; i < 10; i++)
	{
		scanf("%d", &brr[i]);
	}
	
	for (int i = 0; i < 10; i++)
	{
		for (int j = i+1 ; j < 10; j++)
		{
			if (min(brr[i],brr[j])<brr[i])
			{
				int tmp;
				tmp = brr[i];
				brr[i] = brr[j];
				brr[j] = tmp;
			}
			
		}
		printf("%d  ", brr[i]);
	}

	//有两个班级,分别有35 30个人,分别求平均成绩
	float score1[35];
	int n1 = 35;
	int n2 = 30;
	float score2[30];
	printf("一班成绩");
	for (int i = 0; i < n1; i++)
	{
		scanf("%f", &score1[i]);
	}
	printf("二班成绩");
	for (int i = 0; i < n2; i++)
	{
		scanf("%f", &score2[i]);
	}
	printf("%5.2f\n", pingjun(score1, n1));

	printf("%5.2f", pingjun(score2, n2));
	//有一维数组score内存放10个学生的成绩,求平均成绩
	float score[10];
	for (int i = 0; i < 10; i++)
	{
		scanf("%f", &score[i]);
	}
	printf("%f", pingjun(score));

 //输入10个数,要求输出其中最大值元素和在第几个
    int  a[10];
	for (int i = 0; i < 10; i++)
	{
		scanf("%d", &a[i]);

	}
	printf("\n");
	int m;
	int k=a[0];
	for (int i3 = 0; i3 < 10; i3++)
	{
		if (max1(a[i3], a[i3 + 1])>k )
		{
			k = max1(a[i3], a[i3 + 1]);
		}
	}
	  printf("%d\n", k);

	//递归求n!
	int n;
	scanf("%d", &n);
	printf("%d", jiecheng(n));
	//第一个学生10岁,每个比前一个大2岁,求第五个学生多大
	int i2=10;
	for (int i1 = 1; i1 < 5; i1++)
	{
		i2=wu(i2);
	}
	printf("%d", wu(i2));
	//输入四个整数,找出其中最大的数
	int a1,a2,a3,a4;
	scanf("%d %d %d %d", &a1, &a2,&a3,&a4);
	printf("%d", max1(a1,max1(a2,max1(a3,a4)) ));
	//输入两个小数比较较大者,输出整数;
	float sum(float x, float y);//sum()函数在主函数后,要在主函数中进行声明
	float sum(float  , float  );//声明中只写类型不写形参名也是正确的,写什么都可以
	float c ,d;
	scanf("%f %f", &c, &d);
	printf("%d",max2(c,d));
	// 输出两个实数之和
    printf("%f", sum(c, d));
    //输出两个整数,要求输出其中值较大者
	int  a, b;
	scanf("%d %d", &a, &b);
    printf("%d", max1(a, b));
	//输出特定文字
	xingxing();
	aini();
	xingxing();
	
	
	return 0;
}
//输入两个实数,用函数求他们之和
float sum(float x, float y)
{
	return x + y;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值