函数
为什么要用函数?
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个字耶