函数
函数
现在你已经学习了变量、循环和条件语句,是时候学习函数了。你应该对它们的作用有所了解,因为我们已经使用过它们,并且以 main 的形式定义了一个。getchar 是另一个函数的例子。一般来说,函数是执行一系列预定义命令以完成有意义的任务的代码块。你可以使用内置库函数,也可以创建自己的函数。
程序员编写的函数通常需要一个原型。就像蓝图一样,原型提供了基本的结构信息:它告诉编译器函数将返回什么,函数将如何被调用,以及函数可以传递哪些参数。当我提到函数返回一个值时,我的意思是函数可以像变量一样被使用。例如,一个变量可以设置为等于一个返回 0 到 4 之间值的函数。
例如:
#include <stdlib.h> /* 包括rand () */
int a = rand(); /* rand 是所有编译器都具有的标准函数 */不要认为'a'会随机改变,它将被设置为函数被调用时返回的值,但不会再改变。
原型的通用格式很简单:
return-type function_name ( arg_type arg1, ..., arg_type argN );arg_type 意思是每个参数的类型——例如,一个 int、一个 float 或一个 char。这与你声明变量时输入的内容完全相同。
可以向函数传递多个参数,也可以一个都不传递(此时括号是空的),并且函数不必返回值。不返回值的函数有一个 void 的返回类型。让我们看一个函数原型:
int mult ( int x, int y );这个原型指定了函数 mult 将接受两个参数,且这两个参数都是整数,并且它将返回一个整数。不要忘记末尾的分号。没有它,编译器可能会认为你正在尝试编写函数的实际定义。
当程序员实际定义函数时,它将以原型(去掉分号)开始。然后应该始终有一个代码块(用花括号包围),其中包含函数要执行的代码,就像你为 main 函数编写的那样。传递给函数的任何参数都可以像在代码块中声明的那样使用。最后,用一个句号和一个关闭花括号结束。
让我们来看一个示例程序:
#include <stdio.h>
int mult ( int x, int y );
int main()
{
int x;
int y;
printf( "请输入两个要相乘的数字 " );
scanf( "%d", &x );
scanf( "%d", &y );
printf( "这两个数的乘积是 %d\n", mult( x, y ) );
getchar();
}
int mult (int x, int y)
{
return x * y;
}这个程序以唯一的必要include文件开始。接下来是函数的原型。请注意它有一个最终的分号!主函数返回一个整数,你应该始终遵循标准。如果你跟随了前面的教程,应该不会对输入和输出函数感到困惑。
注意 printf 实际上接收了看似是 mult 函数的值。真正发生的是 printf 接受由 mult 返回的值,而不是 mult 本身。结果与我们使用这个打印命令相同
printf( "The product of your two numbers is %d\n", x * y );mult 函数实际上定义在 main 下面。因为它的原型在 main 上面,编译器仍然将其识别为已声明,因此编译器不会给出 mult 未声明的错误。只要原型存在,即使没有定义,函数也可以使用。然而,即使可以编译,没有定义的代码无法运行。
函数原型是对函数的声明,但如果我们不想立即完全定义函数,它们只是用来通知编译器函数的存在。如果 mult 在使用前已经定义,我们就可以省去原型——定义本身基本上也充当了原型的功能。
return 是强制函数返回值的关键字。请注意,可以有一个不返回值的函数。如果一个函数返回 void,return 语句是有效的,但前提是它不包含表达式。换句话说,对于返回 void 的函数,语句"return;"是合法的,但通常冗余。(它可以用来在函数结束前退出函数。)
最关键的功能性问题(半开玩笑地说)是我们为什么需要函数?函数有很多用途。例如,程序员可能在程序中重复使用了四十次某段代码。创建一个函数来执行这段代码可以节省大量空间,同时也会使程序更易读。此外,只有一段代码副本使得修改更加容易。你宁愿在可能很大的程序中散布四十处小修改,还是对函数体进行一次修改?我也是这么想的。
函数的另一个原因是将复杂程序分解为逻辑部分。例如,考虑一个菜单程序,当选择菜单项时会运行复杂代码。这个程序最好为每个实际菜单项创建函数,然后将复杂任务分解为更小、更易于管理的任务,这些任务可以放在它们自己的函数中。这样,程序在被阅读时可以设计得更有意义,并且具有更易于快速理解的结构。最糟糕的程序通常只有必需的函数 main,并用大量杂乱的代码填充它。
