C日志-函数

函数

为什么要用函数?

1.避免代码冗长

2.模块化设计思路

3.按功能划分,每个函数代表一个功能,命名顾名思义

函数三要素

函数要先定义再调用

三要素:

1、函数名

2、参数列表

3、返回值

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

函数的封装和调用

定义无参数函数

一般形式:

类型名 函数名()

{

函数体

}

或者

类型名 函数名(void)//void表示空的意思,无参数

{

函数体

}

例如:

#include <stdio.h>
void printfwelcome()
{
	printf("=======================\n");
	printf("欢迎来到我的程序\n");
	printf("=======================\n");
	//无返回值
}

int main()
{
	printfwelcome();//调用
	return 0;
}

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

int getDataFromX(int a)//形式参数,需要包含变量类型,变量名(非必须)
{
	return a - 1;
}
int main()
{
	int x,y;
	puts("请输入一个整数:");
	scanf("%d",&x);
	y = getDataFromX(x);
	printf("x=%d,y=%d\n",x,y);
	return 0;
}

#include <stdio.h>
int add(int data1,int data2)
{
	return data1+data2;
}
int main()
{
	int x,y,z;
	puts("请输入2个整数:");
	scanf("%d%d",&x,&y);
	z = add(x,y);
	printf("%d+%d=%d\n",x,y,z);
	return 0;
}

只关心函数的数据和值,不关心变量名,不同函数可以用相同变量名

 空函数

函数里面什么都没有,占坑用的

函数可以直接当表达式输出返回值,如

a=add(2,3)+add(3,4)

printf(。。。。。。,add(x,y));add是一个封装好的函数

形式参数和实际参数

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

#include <stdio.h>
int add(int x)//形参
{
	printf("add函数中的内存地址是:%p,存放的值是%d\n",&x,x);
	return x+100;
}
int main()
{
	int x,y;
	puts("请输入1个整数:");
	scanf("%d",&x);
	printf("main函数中的内存地址是:%p,存放的值是%d\n",&x,x);
	y = add(x);//实参
	printf("x=%d,y=%d\n",x,y);
	return 0;
}

形参的生命周期:栈空间,被调用的时候才为形参申请内存,调用结束,内存被系统示范

局部变量

只作用在局部的变量,只出现在函数内部的变量,不能在其他地方使用

练习

获取两个数的大数

#include <stdio.h>
int getBigDataFromTwo(int x,int y)
{
	//int big;
	/*
	if(x>y){
		big=x;
	}else{
		big=y;
	}
	*/
	//非黑即白的时候可以用三目运算
	//big = x>y?x:y;
	//return big;
	return x>y?x:y;//甚至直接返回
}
int main()
{
	int data1;
	int data2;
	int bigOne;
	puts("请输入两个数:");
	scanf("%d%d",&data1,&data2);
	bigOne=getBigDataFromTwo(data1,data2);
	printf("这两个数是:%d,%d,大数是%d\n",data1,data2,bigOne);
	return 0;	
}

 

如果是两个小数呢,字符呢?

改变相应类型就可以了

#include <stdio.h>
float getBigDataFromTwo(float x,float y)
{
	return x>y?x:y;
}
int main()
{
	float data1;
	float data2;
	float bigOne;
	puts("请输入两个数:");
	scanf("%f%f",&data1,&data2);
	bigOne=getBigDataFromTwo(data1,data2);
	printf("这两个数是:%.2f,%.2f,大数是%.2f\n",data1,data2,bigOne);
	return 0;	
}

函数的声明

如果一个函数放在了调用的后面或者外面,需要提前声明

比如#include <stdio.h>头文件

或者

#include <stdio.h>
float getBigDataFromTwo(float x,float y);//声明
int main()
{
	float data1;
	float data2;
	float bigOne;
	puts("请输入两个数:");
	scanf("%f%f",&data1,&data2);
	bigOne=getBigDataFromTwo(data1,data2);
	printf("这两个数是:%.2f,%.2f,大数是%.2f\n",data1,data2,bigOne);
	return 0;	
}
float getBigDataFromTwo(float x,float y)
{
	return x>y?x:y;
}

否则会出现如下问题:

函数嵌套

 

 例如找4个数的最大值

#include <stdio.h>
int getBigDataFromTwo(int x,int y)
{
	return x>y?x:y;
}
int getMaxDataFromFour(int a,int b,int c,int d)
{
	int max;
	max = getBigDataFromTwo(a,b);
	max = getBigDataFromTwo(max,c);
	max = getBigDataFromTwo(max,d);
	return max;
}
int main()
{
	int data1;
	int data2;
	int data3;
	int data4;
	int bigOne;
	puts("please input four numbers:");
	scanf("%d%d%d%d",&data1,&data2,&data3,&data4);
	bigOne=getMaxDataFromFour(data1,data2,data3,data4);
	printf("the four numbers are:%d,%d,%d,%d,the biggest one is %d\n",data1,data2,data3,data4,bigOne);
	return 0;	
}

 函数递归(一般不用)

调用自己,有退出条件

 

#include <stdio.h>
int getAge(int currPersonNum)
{
	int age;
	if(currPersonNum==1){
		age=10;//第一个同学10岁
	}else{
		age = getAge(currPersonNum-1)+2;//比上一个同学大2岁
	}
	return age;
}
int main()
{
	int num;
	int age;
	printf("你要知道第几个学生的年龄:\n");
	scanf("%d",&num);
	age=getAge(num);
	printf("第%d个学生的年龄是%d\n",num,age);
	return 0;	
}

阶乘

#include <stdio.h>
#include <stdlib.h>//要使用exit命令需要使用stdlib.h
int getRet(int num)
{
	int result;
	if(num>16){
		printf("越界\n");
		exit(-1);
	}
	if(num==1){
		result=1;
	}else{
		result = getRet(num-1)*num;
	}
	return result;
}
int main()
{
	int num;
	int ret;
	printf("请输入一个整数:\n");
	scanf("%d",&num);
	ret=getRet(num);
	printf("%d的阶乘是%d\n",num,ret);
	return 0;	
}

 数组和函数

数组名当做实参

#include <stdio.h>
void printArr(int arr[3])
{
	int i;
	for(i=0;i<3;i++){
		printf("%d ",arr[i]);
	}
}
int main()
{
	int arr[3]={1,2,3};
	printArr(arr);
	return 0;	
}

秘密

#include <stdio.h>
void printArr(int arr[6])//形参中不存在数组的概念,即使括号约定了数组的大小,也无效
                         //传递的是一个地址,是数组的首地址
{
	int i;
	printf("main:arr的大小是:%d\n",sizeof(arr));//在OS中用8位表示一个地址
	for(i=0;i<6;i++){
		printf("%d ",arr[i]);
	}
}
int main()
{
	int arr[6]={1,2,3,5,6};
	printf("main:arr的大小是:%d\n",sizeof(arr));
	printArr(arr);
	return 0;	
}

编译时警告

需要用指针来解决

运行结果

优化:

#include <stdio.h>
void printArr(int arr[],int len)//形参中不存在数组的概念,即使括号约定了数组的大小,也无效
                         //传递的是一个地址,是数组的首地址
{
	int i;
	printf("main:arr的大小是:%d\n",sizeof(arr));//在OS中用8位表示一个地址
	for(i=0;i<len;i++){
		printf("%d ",arr[i]);
	}
}
int main()
{
	int arr[6]={1,2,3,4,5,6};
	int len;
	len = sizeof(arr)/sizeof(arr[0]);//方便以后改动
	printf("main:arr的大小是:%d\n",sizeof(arr));
	printArr(arr,len);//第一个元素的地址代表了数组的首地址
	//printArr(&arr[0],len);//等价于上一行,数组名代表了数组的首地址
	return 0;	
}

案例比较

#include <stdio.h>
void changeData(int data)//数值传递,操作的是不同空间
{
	data=data+100;
	printf("address: %p dataInfunc = %d\n",&data,data);
}
int main()
{
	int data = 10;
	changeData(data);
	printf("address: %p data = %d\n",&data,data);
	return 0;	
}
#include <stdio.h>
void changeData(int data[])//操作的一定是同一空间,数组名作实参,传递了地址
{
	data[0]=data[0]+100;
	printf("address: %p dataInfunc = %d\n",&data[0],data[0]);
}
int main()
{
	int data[2] = {10,20};
	changeData(data);
	printf("address: %p data = %d\n",&data[0],data[0]);
	return 0;	
}

结果对照

 

练习

求2个班的平均分

#include <stdio.h>
void initArr(int arr[],int len,int num)
{
	int i;
	for(i=0;i<len;i++){
		printf("please input the score of student No.%d in Class%d\n",i+1,num);
		scanf("%d",&arr[i]);
	}
	puts("done");
}
void printArr(int arr[],int len,int num)
{
	int i;
	printf("sum of students:%d in Class%d\n",len,num);
	printf("scores: ");
	for(i=0;i<len;i++){
		printf("%d ",arr[i]);
	}
	printf("\ndone\n");
}
float getAverage(int arr[],int len)
{
	int i;
	float average = 0.0;
	int sum = 0;//初始化为0否则默认为最大数或0
	for(i=0;i<len;i++){
		sum += arr[i];
	}
	average = (float)sum/len;
	printf("\ndone\n");
	return average;
}
int main()
{
	int classOne[5];
	int classTwo[10];
	int num1 = 1;
	int num2 = 2;
	float averageOfClassOne;
	float averageOfClassTwo;
	int lenOfClassOne=sizeof(classOne)/sizeof(classOne[0]);
	int lenOfClassTwo=sizeof(classTwo)/sizeof(classTwo[0]);
	//初始化
	initArr(classOne,lenOfClassOne,num1);
	initArr(classTwo,lenOfClassTwo,num2);//API
	//输出数组
	printArr(classOne,lenOfClassOne,num1);
	printArr(classTwo,lenOfClassTwo,num2);
	//求平均分
	averageOfClassOne=getAverage(classOne,lenOfClassOne);
	averageOfClassTwo=getAverage(classTwo,lenOfClassTwo);
	printf("the average of class One is: %.2f\n",averageOfClassOne);
	printf("the average of class Two is: %.2f\n",averageOfClassTwo);
	return 0;	
}

函数与二维数组

#include <stdio.h>
void printArrDouble(int arr[][3])//一定要写列数
{
	int i;
	int j;
	for(i=0;i<2;i++){
		for(j=0;j<3;j++){
			printf("%d ",arr[i][j]);
		}
		putchar('\n');
	}
}
int main()
{
	int arr[2][3] = {{1,2,3},{4,5,6}};//特殊的以为数组,要关心每一维有多少个确定元素
	printArrDouble(arr);
	return 0;	
}

练习,求最大值

#include <stdio.h>
void initArrDouble(int arr[][4],int row,int line)
{
	int i;
	int j;
	for(i=0;i<row;i++){
		for(j=0;j<line;j++){
			printf("请输入第%d行,第%d列的数据\n ",i+1,j+1);
			scanf("%d",&arr[i][j]);
		}
	}
}

void printArrDouble(int arr[][4],int row,int line)
{
	int i;
	int j;
	for(i=0;i<row;i++){
		for(j=0;j<line;j++){
			printf("%d ",arr[i][j]);
		}
		putchar('\n');
	}
}

int getMaxDataFromArrDouble(int arr[][4],int row,int line)
{
	int i;
	int j;
	int max;
	max = arr[0][0];
	for(i=0;i<row;i++){
		for(j=0;j<line;j++){
			if(arr[i][j]>max){
				max=arr[i][j];
			}
		}
	}
	return max;
}

int main()
{
	int max;
	int arr[3][4];
	
	initArrDouble(arr,3,4);
	printArrDouble(arr,3,4);
	max = getMaxDataFromArrDouble(arr,3,4);
	//max = getMaxDataFromArrDouble(&arr[0][0],3,4);
	printf("这个二维数组中最大的数是%d\n",max);
	return 0;	
}

全局变量

全局变量是写在最开始的外部变量

外部变量是作用在函数外部的变量

 全局变量使代码自上到下读取,有先后顺序程序员便捷,但有隐藏风险,就是所有的函数都可以调用它,容易改变它

练习

返回10个学生的平均分,最高分,最低分。

#include <stdio.h>
int max;
int min;

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

int main()
{
	int score []={66,87,98,35,65,78,99,31,59,100};
	float aver;
	int len = sizeof(score)/sizeof(score[0]);
	
	aver = getResult(score,len);
	printf("班级最高分:%d 最低分:%d 平均分%.2f",max,min,aver);
	return 0;	
}

作业:

1.输入10个数,找出最大值及其下标

tip:关键字不能作为全局变量

#include <stdio.h>
int max;
int inde;
void initData(int arr[],int len)
{
	int i;
	puts("请输入10个整数:");
	for(i=0;i<len;i++){
		printf("第%d个数:\n",i+1);
		scanf("%d",&arr[i]);
	}
	putchar('\n');
}

void printData(int arr[],int len)
{
	int i;
	for(i=0;i<len;i++){
		printf("%d ",arr[i]);
	}
	putchar('\n');
}

int getMaxData(int arr[],int len)
{
	int i;
	max = inde = 0;
	for(i=0;i<len;i++){
		if(max<arr[i]){
			max = arr[i];
		}
	}
	for(i=0;i<len;i++){
		if(max==arr[i]){
			inde = i+1;
		}
	}
	return 0;
}

int main()
{
	int arr[10];
	int len = sizeof(arr)/sizeof(arr[0]);
	
	initData(arr,len);
	printData(arr,len);
	getMaxData(arr,len);
	printf("这10个数的最大值是%d,它的下标是%d\n",max,inde);
	return 0;
}

 

2.封装冒泡排序法函数

#include <stdio.h>
void initData(int arr[],int len)
{
	int i;
	puts("请输入10个整数:");
	for(i=0;i<len;i++){
		printf("第%d个数:\n",i+1);
		scanf("%d",&arr[i]);
	}
	putchar('\n');
}

void printData(int arr[],int len)
{
	int i;
	printf("原数组序列为:");
	for(i=0;i<len;i++){
		printf("%d ",arr[i]);
	}
	putchar('\n');
}

int getUpSerial(int arr[],int len)
{
	int i;//行
	int j;//列
	int temp;
	int num = 0;
	printf("\n升序排列:");
	for(i=0;i<len-1;i++){
		for(j=0;j<len-1-i;j++){
			if(arr[j] > arr[j+1]){
				temp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = temp;
			}
			num++;
		}
	}
	for(i=0;i<len;i++){
		printf("%d ",arr[i]);
	}
	printf("\n一个比较了%d次\n",num);
	return 0;
}

int getDownSerial(int arr[],int len)
{
	int i;//行
	int j;//列
	int temp;
	int num = 0;
	printf("\n降序排列:");
	for(i=0;i<len-1;i++){
		for(j=0;j<len-1-i;j++){
			if(arr[j] < arr[j+1]){
				temp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = temp;
			}
			num++;
		}
	}
	for(i=0;i<len;i++){
		printf("%d ",arr[i]);
	}
	printf("\n一个比较了%d次\n",num);
	return 0;
}

int main()
{
	int arr[10];
	int len = sizeof(arr)/sizeof(arr[0]);
	
	initData(arr,len);
	printData(arr,len);
	getUpSerial(arr,len);
	getDownSerial(arr,len);
	return 0;
}

3.封装选择排序法函数

#include <stdio.h>
void initData(int arr[],int len)
{
	int i;
	puts("请输入10个整数:");
	for(i=0;i<len;i++){
		printf("第%d个数:\n",i+1);
		scanf("%d",&arr[i]);
	}
	putchar('\n');
}

void printData(int arr[],int len)
{
	int i;
	printf("原数组序列为:");
	for(i=0;i<len;i++){
		printf("%d ",arr[i]);
	}
	putchar('\n');
}

int getUpSerial(int arr[],int len)
{
	int i;//行
	int j;//列
	int temp;
	int num = 0;
	printf("\n升序排列:");
	for(i=0;i<len-1;i++){
		for(j=i+1;j<len;j++){
			if(arr[i] > arr[j]){
				temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
			}
			num++;
		}
	}
	for(i=0;i<len;i++){
		printf("%d ",arr[i]);
	}
	printf("\n一个比较了%d次\n",num);
	return 0;
}

int getDownSerial(int arr[],int len)
{
	int i;//行
	int j;//列
	int temp;
	int num = 0;
	printf("\n降序排列:");
	for(i=0;i<len-1;i++){
		for(j=i+1;j<len;j++){
			if(arr[i] < arr[j]){
				temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
			}
			num++;
		}
	}
	for(i=0;i<len;i++){
		printf("%d ",arr[i]);
	}
	printf("\n一个比较了%d次\n",num);
	return 0;
}

int main()
{
	int arr[10];
	int len = sizeof(arr)/sizeof(arr[0]);
	
	initData(arr,len);
	printData(arr,len);
	getUpSerial(arr,len);
	getDownSerial(arr,len);
	return 0;
}

函数学完了,还OK,这次写了9699个字耶

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

run sun

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

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

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

打赏作者

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

抵扣说明:

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

余额充值