函数是 C语言中非常重要的一部分,因为它们可以让你编写更加模块化、易于维护的代码。
C语言函数的定义
在编程语言中,函数就像一个工具箱,具有以下三个特性:
在开始执行任务之前,函数可以接收一些输入值;
在执行任务的过程中,函数可以执行一些操作;
在完成任务后,函数可以返回一些值。
举例来说,我们如果想要计算 a 和 b 两个数的和,则可以写一个函数来实现它:
输入参数为 a 和 b。
函数返回值为 a + b 的和。
下面是一个名为 add() 的函数的定义,其中的代码实现了上述功能:
int add(int a, int b)
{
return a + b;
}
因此,可以总结出函数的书写格式:
函数返回值类型 函数名(函数输入参数)
{
做一些事情
return 函数返回值;
}
上述格式中,用花括号括起来的部分被称为函数体,函数体必须用花括号明确地界定。由函数名、函数输入参数及函数返回值类型组成的部分被称为函数头,如下图所示:
图 1 函数头与函数体
下图对 add() 函数进行了详细的解析:
图 2 add()函数的解析
该函数的输入参数为 int a 和 int b,并通过 return 语句返回了它们的和。
需要注意的是,每个输入参数都必须指明其变量类型,不能省略变量类型。例如:
int add(int a, int b) // 正确
int add(int a, b) // 错误
自定义函数的函数名可以按照个人喜好来选择,甚至可以使用 aaaaa 这样的名字。但是,为了使函数名具有语义化,便于人们阅读和理解代码,通常建议使用有意义的英文来命名函数。
C语言函数的调用
函数定义完成后,需要在另一个函数中进行调用才能执行。
例如,使用 main() 函数来调用 add() 函数:
#include
int add(int a, int b)
{
return a + b;
}
int main()
{
int result;
result = add(2, 3); // 调用 add 函数
printf("%d", result);
return 0;
}
在上述代码中,main() 函数被称为主调函数,而 add() 函数被称为被调函数。
在 main() 函数中,我们将 2 和 3 两个参数传递给 add() 函数,并调用它。在 add() 函数头中,定义了函数的返回值类型为 int,这表明该函数被调用后将返回一个 int 类型的结果。因此,我们使用一个 int 类型的变量 result 来存储 add() 函数的返回值。
整个调用过程的具体解析如下图所示:
图 3 add() 函数的调用过程解析
使用函数的意义
为什么需要将代码封装为函数呢?如果程序需要多次完成某项任务,你可以选择两个方案:
一是多次复制相同的代码;
二是将代码封装为一个函数,并在需要的地方调用它。
下面演示如何使用代码求解三角形的面积,并探讨将其封装为函数的优点。
假设在平面内有一个三角形,其三条边的长度分别为 a、b、c,三角形的面积 S 可以通过下图中的海伦公式计算得出:
图 4 海伦公式
此外,三角形中任意两边的长度之和必须大于第三边,否则无法构成三角形。也就是说,三角形的三条边必须满足以下不等式:
a + b > c
a + c > b
b + c > a
例如,当 a = 1,b = 1,c = 1 时,可以构成一个三角形;但当 a = 1,b = 1,c = 3 时,无法构成三角形。
接下来,我们将使用代码计算三角形的面积。首先,我们需要判断三条边是否能够构成一个合法的三角形。为了实现这一点,我们可以使用下面的代码来判断:
if (a + b > c && a + c > b && b + c > a)
{
printf("It's a triangle\n");
}
else
{
printf("Not a triangle\n");
}
接下来,我们可以使用海伦公式来计算三角形的面积 s。其中,a、b、c 分别表示三角形的三条边长度,p 为三角形半周长。我们可以写出如下代码:
p = (a + b + c) / 2;
s = sqrt(p * (p - a) * (p - b) * (p - c));
sqrt() 是平方根函数,使用它需要包含头文件
完整的代码如下:
#include
#include
int main()
{
// 输入 a、b、c
double a, b, c, p, s;
scanf("%lf %lf %lf", &a, &b, &c);
// 是否能构成三角形
if (a + b > c && a + c > b && b + c > a)
{
printf("It's a triangle\n");
}
else
{
// 无法构成三角形,程序结束
printf("Not a triangle\n");
// 这里 return 0 表示 main 函数结束
return 0;
}
// 求三角形的面积
p = (a + b + c) / 2;
s = sqrt(p * (p - a) * (p - b) * (p - c)); // 修正了公式,添加了 (p-c)
// 输出结果
printf("s=%f", s);
return 0;
}
需要注意的是,上述代码中的 scanf() 函数用于获取从键盘中输入的三个 double 类型的变量。我们可以在程序运行时依次输入三个数字,并用空格或 Enter 键将它们分隔开。此外,我们使用 printf() 函数输出结果。
运行上述代码,输入三条边的长度,例如 3、4、5,执行结果如下:
3 4 5
It's a triangle
s=6.000000
复用代码
在计算三角形面积的程序中,可以将其分解为两个可复用的部分:
判断给定的三条边是否能构成一个三角形;
求三角形的面积。
有时候我们只需要知道给定的三条边能否构成三角形,而不需要计算其面积。因此,我们可以将这部分代码提取为一个独立的函数,以提高代码的可复用性。具体代码如下:
int isTriangle(double a, double b, double c)
{
// 是否能构成三角形
if (a + b > c && a + c > b && b + c > a)
{
return 1;
}
return 0;
}
函数 isTriangle() 接收三个参数:三角形的三条边长 a、b、c。该函数的返回值为一个整型,其中 1 表示可以构成三角形,0 表示不能构成三角形。
接下来,我们将计算三角形面积的代码也提取为一个函数,具体代码如下:
double areaOfTriangle(double a, double b, double c)
{
double p, s;
p = (a + b + c) / 2;
s = sqrt(p * (p - a) * (p - b) * (p - c));
return s;
}
函数 areaOfTriangle() 同样接收三个参数:三角形的三条边长 a、b、c。该函数的返回值为三角形的面积。使用者无须关心函数内部的实现细节,只需正确地传入参数即可获得计算结果。
最后,我们把之前的程序改写为使用函数的形式,具体的代码为:
#include
#include
// 求三角形的面积
double areaOfTriangle(double a, double b, double c)
{
double p, s;
// 求三角形的面积
p = (a + b + c) / 2;
s = sqrt(p * (p - a) * (p - b) * (p - c));
return s;
}
// 是否能构成三角形
int isTriangle(double a, double b, double c)
{
// 是否能构成三角形
if (a + b > c && a + c > b && b + c > a)
{
return 1;
}
return 0;
}
int main()
{
// 输入 a、b、c
double a, b, c;
scanf("%lf %lf %lf", &a, &b, &c);
// 是否能构成三角形
if (isTriangle(a, b, c) == 0)
{
printf("Not a triangle\n");
return 0;
}
// 求三角形的面积
double s;
s = areaOfTriangle(a, b, c);
printf("area of triangle is %f", s);
return 0;
}