2.6 函数
如果程序的逻辑比较复杂、代码量比较大或者重复性的功能比较多,那么全部写在主函数里就会显得比较冗长杂乱,为了使代码更加简洁、思路更加清晰,c语言提供了”函数“。
函数是一个实现一定功能的语句的集合,并在需要时可以 反复调用而无需再写一遍。
2.6.1 函数的定义
函数的基本语法格式:
返回类型 函数名称(参数类型 参数){
函数主体
}
举一个例子:
#include <stdio.h>
using namespace std;
void print1()//函数1
{
printf("Haha,\n");
printf("Good idea!\n");
}
void print2()//函数2
{
printf("Ohno,\n");
printf("Bad idea!\n");
}
int main()
{
print1();
print2();
return 0;
}
实现结果:
Haha,
Good idea!
Ohno,
Bad idea!
其中print1()和print2()就是自定义的两个函数,分别实现了输出两条语句的功能。单独提出print1来看,void是指返回类型,不返回任何参数,print1是函数名称,在print1小括号内没有写任何参数——这种不需要提供任何参数的函数就叫做无参函数,相对应的有有参函数。
举一个有参函数的例子:
#include<stdio.h>
using namespace std;
int judge(int x)//judge函数
{
if(x>0)
return 1;
else if(x==0)
return 0;
else
return -1;
}
int main()//主函数
{
int a,ans;
scanf("%d",&a);
ans=judge(a);
printf("%d",ans);
}
输入一个整数:
4
输出一个整数:
1
其中judge就是一个有参函数,int是返回类型,judge是函数名称,int x是传入参数,传
入一个int型参数x,若x>0,则返回1,若x<0,则返回-1,若x==0,则返回0。
2.6.2 全局变量、局部变量
下面介绍一下全局变量与局部变量的概念。
1.全局变量
全局变量是指在定义之后的所有程序段内都有效的变量,如:
#include<stdio.h>
using namespace std;
int x;//全局变量x
int change(){//change函数
x=x+1;
return x;
}
int main(){//主函数
x=10;
change();
printf("%d",x);
return 0;
}
输出结果:
11
在本例中,x就是一个全局变量,定义在所有函数之前,在所有函数内都有效。故在主函数中先对全局变量x赋值10,调用change函数使x加1,最后输出x为11。
2.局部变量
#include <stdio.h>
using namespace std;
int change(int x){
x=x+1;
return x;
}
int main(){
int x=10;
change(x);
printf("%d",x);
return 0;
}
输出结果:
10
可以看到,当在主函数中定义了x之后,将其作为change函数的参数传入,并令x加1,但最后输出的结果仍然是10。这是因为change函数的参数为局部变量,只在函数内部有效,通过change函数传进去的x只是传入的一个副本,即在main函数中的x和change函数中的x根本是两个不同的变量,只是名字相同,其实名字不同也可以,这种传递方式称为值传递。
函数定义的小括号内的参数称为形式参数或形参,而当实际调用时小括号内的参数称为实际参数或实参。最后指出,函数的参数可以不止一个。
2.6.3 再谈main函数
主函数对整个程序来说只能有一个,且无论主函数在程序的哪个位置,程序总是从主函数的第一个语句开始执行。下面对主函数的写法进行解释:
int main(){
...
return 0;
}
现在以函数的眼光来看主函数:main是函数名称且是无参函数,返回类型是int型,并且在函数主体的最后面返回了0。对计算机来说,main函数返回0的意义在于告知系统程序正常终止。
2.6.4 以数组作为函数参数
1.函数的参数也可以是数组,且数组作为函数参数时,参数中数组的第一维不需要填写长度(如果是二维数组,那么第二维需要填写长度),且实际调用时,也仅需要填写数组名。
2.最重要的是,当数组作为函数参数时,在函数中对数组的修改就等同于是对原数组元素的修改(这一点与普通的局部变量不同)。
不过为什么呢?因为将数组作为实参传入,传入的是数组名,而数组名代表的就是数组的首地址
3.不过,虽然数组可以作为函数参数,但是却不可以作为返回类型出现,如果要使用数组作为返回类型,那么就只能将数组作为参数传入。
举个例子:
#include<stdio.h>
using namespace std;
void change(int a[],int b[][5])
{
a[0]=1;
a[1]=2;
a[2]=3;
b[0][0]=1;
}
int main()
{
int a[3]= {0};
int b[5][5]= {0};
change(a,b);
for(int i=0; i<3; i++)
{
printf("a[%d]=%d\n",i,a[i]);
}
return 0;
}
输出结果:
a[0]=1
a[1]=2
a[2]=3
在本例中可以看到,最初数组a赋值全为0,而最终数组a打印出的值是1,2,3。
2.6.5 函数的嵌套调用
函数的嵌套调用顾名思义就是在一个函数中调用另一个函数,如本例中在max_3中调用了两次max_2。
#include<stdio.h>
int max_2(int a,int b)
{
if(a>b)
return a;
else
return b;
}
int max_3(int a,int b,int c)
{
int temp=max_2(a,b);//函数的嵌套调用
temp=max_2(temp,c);
return temp;
}
int main()
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
printf("%d",max_3(a,b,c));
return 0;
}
输入:
5 3 2
输出结果:
5
2.6.6 函数的递归调用
函数的递归调用其实就是函数自己调用自己的过程。
如计算n!:
#include<stdio.h>
int F(int n)
{
if(n==0)
return 1;
else
return F(n-1)*n;
}
int main()
{
int n;
scanf("%d",&n);
printf("%d",F(n));
return 0;
}
输入一个整数:
3
输出结果:
6