C语言函数

目录

函数引入:

函数的三要素:

定义无参数函数:

定义有参数有返回值的函数:

 函数调用注意事项:

 形式参数和实际参数:

 局部变量:

 函数的调用过程:

函数调用的条件:

 函数的嵌套:

 函数的递归:

 二维数组作为函数的参数:

 全局变量:

 作业 :

① 要求输入10个数,找出最大数以及最大数的下标

 ② 封装冒泡排序的函数

 ③ 封装选择排序的函数


函数引入:

函数要先定义再使用,和变量一个道理。

函数的三要素:

  1. 函数名(体现功能);
  2. 参数列表(比如y=f(x)中, x就是参数;y=f(x,y), x,y就是参数;参数的个数可以根据用户需求定义);
  3. 返回值(比如y=f(x)中y就是函数根据x的值和f的功能执行后的结果)。

函数体:执行什么样的功能,涉及的处理代码叫函数体。

定义无参数函数:

 编程练习:

#include <stdio.h>

void PrintWelcome()
{
	printf("=============\n");
	printf("欢迎来C的世界\n");
	printf("=============\n");
}

int main()
{
	
	PrintWelcome();
	
	return 0;
}

定义有参数有返回值的函数:

编程练习:

#include <stdio.h>
//函数三要素:返回值、参数列表、功能
int Add(int data1,int data2)	//函数类型
{
	int result ;
	
	result = data1 + data2;
	
	return result;
} 

int main()
{
	int x;
	int y;
	int result;
	int result1;
	
	
	printf("请输入两个整数\n");
	scanf("%d%d",&x,&y);
	
	result = Add(x,y);
	result1 = Add(x,y)+100;
	
	printf("两个数的和为:%d\n",result);
	printf("函数当作表达式:%d\n",result1);
	printf("函数当作被调用的函数:%d\n",Add(x,y)+100);
	
	return 0;
}

 函数调用注意事项:

  1. 定义空函数:程序设计,模块设计(先定义空函数然后封装);
  2. 带返回值类型:例如 int add(2,3);
  3. 形参带类型:add(int a,int b);
  4. 函数见怪不怪的表达方法:① 函数可以当作表达式:result1 = Add(x,y)+100; ② 函数调用当做其他函数调用的参数 : printf("函数当作被调用的函数:%d\n",Add(x,y)+100)。

 形式参数和实际参数:

 传递参数,传递的是,形参和实参值相同,但是地址空间不同

代码验证:

#include <stdio.h>

int PrintResult(int data1,int data2)
{
	int result;
	result = data1 + data2;
	
	printf("形参data1=%d,地址为%p\n",data1,&data1);
	printf("形参data2=%d,地址为%p\n",data2,&data2);
	
	return result;
}

int main()
{
	int data1 = 10;
	int data2 = 20;
	int result;
	
	result = PrintResult(data1,data2);
	
	printf("实参data1=%d,地址为%p\n",data1,&data1);
	printf("实参data2=%d,地址为%p\n",data2,&data2);
	printf("result = %d\n",result);

	return 0;
}

 局部变量:

顾名思义,变量作用的范围有限。

 编程练习:

①:输入两个整数,要求输出其较大值,用函数实现

/*
	输入两个整数,要求输出其较大值,用函数实现
*/
#include <stdio.h>

int GetBigOneFrom(int data1,int data2)
{
	int max;
	
	max = data1>data2 ? data1:data2;		//作用和下边一样
	
	/*if(data1>data2)
	{
		max = data1;
	}
	else
	{
		max = data2;
	}*/
	
	return max;
}

int main()
{
	int data1;
	int data2;
	int max;
	
	printf("请输入两个整数\n");
	scanf("%d%d",&data1,&data2);
	
	max = GetBigOneFrom(data1,data2);
	
	printf("两个数中较大值为:max = %d\n",max);
	
	return 0;
}

 ②:输入两个小数,要求输出其较大值,用函数实现

/*
	输入两个小数,要求输出其较大值,用函数实现
*/
#include <stdio.h>

float GetBigOneFrom(float data1,float data2)
{
	float max;
	
	max = data1>data2 ? data1:data2;		//作用和下边一样
	
	/*if(data1>data2)
	{
		max = data1;
	}
	else
	{
		max = data2;
	}*/
	
	return max;
}

int main()
{
	float data1;
	float data2;
	float max;
	
	printf("请输入两个小数\n");
	scanf("%f%f",&data1,&data2);
	
	max = GetBigOneFrom(data1,data2);
	
	printf("两个小数中较大值为:max = %.4f\n",max);
	
	return 0;
}

③:输入两个字符,要求输出其较大字符,用函数实现

/*
	输入两个字符,要求输出其较大字符,用函数实现
*/
#include <stdio.h>

char GetBigOneFrom(char data1,char data2)
{
	char bigger;
	
	bigger = data1>data2 ? data1:data2;		//作用和下边一样
	
	/*if(data1>data2)
	{
		bigger = data1;
	}
	else
	{
		bigger = data2;
	}*/
	
	return bigger;
}

int main()
{
	char data1;
	char data2;
	char bigger;
	
	printf("请输入两个字符\n");
	scanf("%c%c",&data1,&data2);        //输入的时候不要敲空格或者回车等字符!!!
	
	bigger = GetBigOneFrom(data1,data2);
	
	printf("两个小数中较大值为:bigger = %c\n",bigger);
	
	return 0;
}

 函数的调用过程:

  1. 在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元。在发生函数调用时,函数max的形参被临时分配内存单元。
  2. 将实参对应的值传递给形参。如图73所示,实参的值为2把2传递给相应的形参x,这时形参x就得到值2,同理,形参y得到值3。
  3. 如果函数返回类型是void,函数体可以不用加return,返回值要注意类型,如果类型不同,可能会发生强制转换影响结果或编译警告。
  4. 通过return语句将函数值带回到主调函数。例72中在return语句中指定的返回值是z这个z就是函数max的值(又称返回值)。执行return语句就把这个函数返回值带
    回主调函数main。应当注意返回值的类型与函数类型一致。如max函数为int型,返回值
    是变量z,也是int型。二者一致。
  5. 调用结束,形参单元被释放。注意:实参单元仍保留并维持原
    值,没有改变。如果在执行一个被调用函数时,形参的值发生改变,不会改变主调函数的实参的值。例如,若在执行max函数过程中x和y的值变为10和15,但a和b仍为2和3,见图74。这是因为实参与形参是两个不同的存储单元。

函数调用的条件:

  1. 函数已被定义 
  2. 调用库函数(比如#include<stdio.h>   #include<math.h>)
  3. 函数的声明:如果使用用户自己定义的函数,而该函数的位置在调用它的函数(即主调函数)的后面(在同一个文件中),应该在主调函数中对被调用的函数作声明(declaration)。声明的作用是把函数名、函数参数的个数和参数类型等信息通知编译系统,以便在遇到函数调用时,编译系统能正确识别函数并检查调用是否合法。

 函数的嵌套:

编程练习:输入四个数,函数方式找出最大值

/*
	输入四个数,函数方式找出最大值
*/
#include <stdio.h>

int GetDataFromTwo(int a,int b)
{
	int bigger;
	
	bigger = a>b ? a:b;
	
	return bigger;
}

int GetDataFromFour(int a,int b,int c,int d)
{
	int biggest;
	
	biggest = GetDataFromTwo(a,b);
	biggest = GetDataFromTwo(biggest,c);
	biggest = GetDataFromTwo(biggest,d);
	
	return biggest;
}

int main()
{
	int data1;
	int data2;
	int data3;
	int data4;
	int max;
	
	
	printf("请输入四个整数\n");
	scanf("%d%d%d%d",&data1,&data2,&data3,&data4);
	
	max = GetDataFromFour(data1,data2,data3,data4);
	
	printf("四个数中的最大值是:%d\n",max);
	return 0;
}

 函数的递归:

编程练习:

#include <stdio.h>

int GetageFrom(int num)
{
	int age;
	if(num==1)
	{
		age = 10;
	}
	else
	{
		age = GetageFrom(num-1)+2;	//如果num不为1,一直递减到为1,把age的数取回来后再进行运                    
                                    // 算,返回age给main函数
	}
	return age;
}

int main()
{
	int num;
	int age;
	
	printf("请问你想知道第几个人的年龄?\n");
	scanf("%d",&num);
	
	age = GetageFrom(num);
	
	printf("第%d个人的年龄是:%d",num,age);
	
	return 0;
}

/*
	n的阶乘
*/
#include <stdio.h>
#include <stdlib.h>

int GetFactorialFrom(int num)
{
	int result = 0;
	
	if(num>=17)
	{
		puts("越界");
		exit(-1);
	}
	if(num==1)
	{
		result = 1;
	}
	else
	{
		result = GetFactorialFrom(num-1) * num;
	}
	return result;
}

int main()
{
	int num;
	int result;
	
	puts("请问您想知道几的阶乘?");
	scanf("%d",&num);
	
	result = GetFactorialFrom(num);
	
	printf("%d的阶乘是%d\n",num,result);
	
	return 0;
}

 数组名当做函数实际参数:当数组名作为函数实际参数的时候,也是值传递,但数组名传递的是数组的首地址

#include <stdio.h>

void PrintArray(int a[],int len)//形参中不存在数组的概念,即便中括号约定了数组的大小,但无效
								//传递的是一个地址,是数组的首地址
{
	int i;
	//printf("形参:%d\n",sizeof(a));  //在操作系统中用8byte表示一个地址
	for(i=0;i<len;i++)
	{
		printf("%d ",a[i]);
	}
}

int main()
{
	int a[] = {21,54,34,97,64};
	int len = sizeof(a)/sizeof(a[0]);
	
	printf("实参:%d\n",sizeof(a));    //求实参所占内存空间大小
	//PrintArray(a,len);	//传递数组名就是传递数组的首地址
	PrintArray(&a[0],len);	//第一个元素的地址就是数组的首地址
	
	
	
	return 0;
	
}

有趣的案例①:

#include <stdio.h>

void GetChange(int data)
{
	data = data + 100;
	printf("GetChange函数中的data = %d\nGetChange函数中的data地址是%p\n",data,&data);
}

int main()
{
	int data = 10;
	GetChange(data);
	printf("main函数中的data = %d\nGetChange函数中的data地址是%p\n",data,&data);
	
	return 0;
}

 有趣的案例②:

#include <stdio.h>

void GetChange(int data[])
{
	data[0] = data[0] + 100;
	printf("GetChange中的data = %d\nGetchange函数中data的地址是:%p\n",data[0],&data[0]);
	
}

int main()
{
	int data[] = {12,24};
	
	GetChange(data);
	printf("main函数中data = %d\nmain函数中data的地址是:%p\n",data[0],&data[0]);
	return 0;
}

编程练习:有两个班的同学,分别是10个人和5个人,分别求这两个班的平均分 。

#include <stdio.h>

void InitArray(int array[],int len)
{
	int i;
	for(i=0;i<len;i++)
	{
		printf("请输入第%d个学生的成绩:\n",i+1);
		scanf("%d",&array[i]);
	}
	puts("输入完毕");
}

void PrintArray(int array[],int len)
{
	int i;
	printf("总人数为:%d\n",len);
	for(i=0;i<len;i++)
	{
		printf("%d ",array[i]);
	}
	puts("\n打印完毕\n");
}

float GetAverage(int array[],int len)
{
	int i;
	int sum = 0;
	float average;
	for(i=0;i<len;i++)
	{
		sum += array[i];
	}
	average = (float)sum/len;
	return average;
}

int main()
{
	int ClassOne[5];
	int ClassTwo[10];
	int len1 = sizeof(ClassOne)/sizeof(ClassOne[0]);
	int len2 = sizeof(ClassTwo)/sizeof(ClassTwo[0]);
	float average1;
	float average2;
	
	InitArray(ClassOne,len1);
	InitArray(ClassTwo,len2);
	
	PrintArray(ClassOne,len1);
	PrintArray(ClassTwo,len2);
	
	average1 = GetAverage(ClassOne,len1);
	average2 = GetAverage(ClassTwo,len2);
	
	printf("一班的平均成绩是:%.2f\n",average1);
	printf("二班的平均成绩是:%.2f\n",average2);
	return 0;
}

 二维数组作为函数的参数:

正确写法:int a[2][3]或int a[][3];

错误写法:int a[][] 或 int a[2][];

 关键两点:数组的数据类型、二维数组中一维数组的个数

编程练习:有3x4矩阵,初始化它并输出,然后求最大值并输出

#include <stdio.h>

void InitArray(int array[][4],int line,int list)
{
	int i;
	int j;
	for(i=0;i<3;i++)
	{
		for(j=0;j<4;j++)
		{
			printf("请输入第%d行第%d列的数值:\n",i+1,j+1);
			scanf("%d",&array[i][j]);
		}
	}
	puts("输入完毕");
}

void PrintArray(int array[][4],int line,int list)
{
	int i;
	int j;
	for(i=0;i<3;i++)
	{
		for(j=0;j<4;j++)
		{
			printf("%d\t",array[i][j]);
		}
		putchar('\n');
	}
	puts("\n打印完毕\n");
}

int GetMaxDataFrom(int array[][4],int line,int list)
{
	int i;
	int j;
	int max;
	max = array[0][0];
	for(i=0;i<3;i++)
	{
		for(j=0;j<4;j++)
		{
			if(max<array[i][j])
			{
				max = array[i][j];
			}
		}
	}
	return max;
}
int main()
{
	
	int max;
	int array[3][4];
	
	InitArray(array,3,4);
	PrintArray(array,3,4);
	
	max = GetMaxDataFrom(array,3,4);
	
	printf("数据中的最大值为:%d\n",max);
	return 0;
}

 全局变量:

全局变量我们也任何的地方都是可以使用的,但是全局变量也存在着不少的缺点,很多有经验的程序员都会避免使用全局变量,这主要是是因为在使用全局变量的时候,可能会引起来一系列的问题,像是干扰了模块化,无意间的修改,并发的问题等等。 无意间的修改的意思是说,在使用全局变量的时候,我们并不知道在什么时候就被修改了,这样产生的后果会有很多,这将会造成测试困难,产生歧义。

编程练习:班上10 个学生,封装一个函数,调用该函数后获得班上的平均分,最高分,最低分

#include <stdio.h>

int max;
int min;

void InitArray(int array[],int len)
{
	int i;
	for(i=0;i<len;i++)
	{
		printf("请输入第%d个学生的成绩:\n",i+1);
		scanf("%d",&array[i]);
	}
	puts("输入完毕");
}

float GetAverage(int array[],int len)
{
	int i;
	int sum = 0;
	max = min = array[0];
	float average;
	for(i=0;i<len;i++)
	{
		if(max<array[i])
		{
			max = array[i];
		}
		if(min>array[i])
		{
			min = array[i];
		}
		sum +=array[i];
	}
	
	average = (float)sum/len;
	return average;
	
}

int main()
{
	
	float average;
	int array[10];
	int len = sizeof(array)/sizeof(array[0]);
	
	InitArray(array,len);
	average = GetAverage(array,len);
	
	printf("最高分是:%d,最低分是:%d,平均分是:%.2f\n",max,min,average);
	return 0;
}

 作业 :

  1. 要求输入10个数,找出最大数以及最大数的下标
  2. 封装冒泡排序的函数
  3. 封装选择排序的函数

编程练习 

① 要求输入10个数,找出最大数以及最大数的下标

#include <stdio.h>
int subscript;

void InitArray(int a[],int len)
{
	int i;
	for(i=0;i<len;i++)
	{
		printf("请输入第%d个数据:\n",i+1);
		scanf("%d",&a[i]);
	}
}

int PrintArray(int a[],int len)
{
	int i;
	int max;
	max = a[0];
	for(i=0;i<len;i++)
	{
		if(max<a[i])
		{
			max = a[i];
			subscript = i;
		}
	}
	return max;
}

int main()
{
	int a[10];
	int max;
	int len = sizeof(a)/sizeof(a[0]);
	
	InitArray(a,len);
	max = PrintArray(a,len);
	
	printf("最大值是%d,最大值的下标是%d\n",max,subscript+1);
	
	return 0;
}

 ② 封装冒泡排序的函数

#include <stdio.h>

void InitArray(int a[],int len)
{
	int i;
	for(i=0;i<len;i++)
	{
		printf("请您输入第%d个数据\n",i+1);
		scanf("%d",&a[i]);
	}
}

void PrintfArray(int a[],int len)
{
	int i;
	int j;
	int temp;
	for(i=0;i<len-1;i++)
		for(j=0;j<len-1-i;j++)
		{
			if(a[j]>a[j+1])
			{
				temp = a[j];
				a[j] = a[j+1];
				a[j+1] = temp;
			}
		}
}
int main()
{
	int i;
	int a[5];
	int len = sizeof(a)/sizeof(a[0]);
	
	InitArray(a,len);
	
	puts("原样输出");
	
	for(i=0;i<len;i++)
	{
		printf("%d ",a[i]);
	}
	
	PrintfArray(a,len);
	
	putchar('\n');
	puts("排序后输出");
	
	for(i=0;i<len;i++)
	{
		printf("%d ",a[i]);
	}
	
	return 0;
}

 ③ 封装选择排序的函数

#include <stdio.h>

void InitArray(int a[],int len)
{
	int i;
	for(i=0;i<len;i++)
	{
		printf("请输入您的第%d个数据\n",i+1);
		scanf("%d",&a[i]);
	}
}

void PrintArray(int a[],int len)
{
	int i;
	int j;
	int temp;
	for(i=0;i<len-1;i++)
	{
		for(j=i+1;j<len;j++)
		{
			if(a[i]>a[j])
			{
				temp = a[i];
				a[i] = a[j];
				a[j] = temp;
			}
		}
	}
}

int main()
{
	int i;
	int a[5];
	int len = sizeof(a)/sizeof(a[0]);
	
	InitArray(a,len);
	
	puts("原样输出");
	for(i=0;i<len;i++)
	{
		printf("%d ",a[i]);
	}
	
	PrintArray(a,len);
	
	putchar('\n');
	
	puts("排序后输出");
	for(i=0;i<len;i++)
	{
		printf("%d ",a[i]);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

日落星野

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值