内容正文:
专题七 函数(讲义)
---《编程语言基础—C语言》专题复习讲练测
[考纲要求]
1:理解函数的定义。
2:掌握函数的调用。
[课时安排]
2课时
[知识梳理]
一:函数的定义
· 定义
在C语言中,函数是一段具有特定功能的代码块,可以被重复调用。
1. 返回类型 函数名(参数类型1 参数名1, 参数类型2 参数名2, ..., 参数类型n 参数名n) {
2. // 函数体
3. // 可以包含局部变量声明、语句、控制结构等
4. return 返回值; // 根据需要返回值,如果返回类型为void,则不需要这行
5. }
① 返回类型:
函数执行后返回给调用者的值的数据类型。它可以是基本数据类型(如int, float, char等),也可以是结构体、指针等更复杂的类型。如果函数不返回任何值,返回类型是void。
② 函数名:
函数的标识符,用于在代码中调用该函数。函数名应该遵循C语言的命名规则,通常是小写字母,如果需要可以加上下划线分隔。
③ 参数列表:
这是函数可以接受的输入值列表,每个参数包括其数据类型和名称。参数列表中的参数用逗号分隔。如果函数不接受任何参数,参数列表为空,但仍需包含一对圆括号()。
④ 函数体:
这是函数执行的代码块,包括一系列语句,它们定义了函数的行为。函数体以左大括号{开始,以右大括号}结束。函数体可以包含变量声明、表达式、控制结构(如循环和条件语句)等。
⑤ 局部变量声明:
可以声明局部变量,这些变量只在函数的作用域内可见。
⑥ 语句:
函数体中可以包含执行特定操作的语句,如赋值、输入输出、循环、条件判断等。
⑦ 返回语句:
使用return关键字从函数返回一个值。如果函数的返回类型不是void,则必须至少有一个return语句来返回一个相应类型的值。如果函数的返回类型是void,则可以省略return语句,或者使用return;来提前退出函数。
具体的函数定义示例:
1. /* 函数的注释说明 */
2. int sum(int a, int b) { // 函数名是sum,有两个int类型的参数a和b,返回类型是int
3. int result; // 局部变量声明,用于存储结果
4.
5. // 函数体开始
6. result = a + b; // 执行加法操作
7. if (result > 100) { // 控制结构,如果结果大于100
8. printf("The result is greater than 100.
"); // 输出信息
9. }
10. return result; // 返回结果
11. // 函数体结束
12. }
sum函数接受两个整数参数a和b,计算它们的和,并将结果存储在局部变量result中。如果结果大于100,则打印一条消息。最后,函数返回计算得到的和。
· 函数的参数
在C语言中,函数调用涉及到两个重要的概念:实际参数和形式参数。
① 实际参数
在C语言中,实际参数是函数调用时提供给函数的值或变量,用于初始化函数的形式参数。
类型:
实际参数可以是任何有效的C语言表达式,包括变量、常量、表达式、数组元素、指针等。
值传递:
C语言默认使用按值传递。这意味着在函数调用时,实际参数的值被复制给形式参数。
类型转换:
当实际参数的类型与形式参数的类型不匹配时,编译器会自动进行类型转换。
示例:
1. #include <stdio.h>
2.
3. // 函数定义,接受两个整数参数
4. void printSum(int a, int b) {
5. printf("Sum: %d
", a + b);
6. }
7.
8. int main() {
9. int x = 5;
10. int y = 10;
11. int z = x + y; // 表达式作为实际参数
12.
13. // 调用函数,使用变量、常量和表达式作为实际参数
14. printSum(x, y); // x和y是变量
15. printSum(10, 20); // 10和20是常量
16. printSum(z, x); // z是表达式的结果
17.
18. return 0;
19. }
printSum函数被调用了三次,每次使用不同类型的实际参数:变量、常量和表达式的结果。这些实际参数的值在函数调用时被复制给形式参数a和b,然后计算它们的和并打印出来。由于C语言是按值传递的,所以函数内部对a和b的修改不会影响x、y或z的值。
② 形式参数
形式参数定义在函数的首部,即在函数名和圆括号()内。每个形式参数都有一个指定的数据类型,决定了它可以接收的值的类型。形式参数具有一个名称,这个名字在函数体内部用于引用传递给该参数的值。
值传递:
默认情况下,C语言通过值传递参数。这意味着实际参数的值被复制到形式参数中。
作用域:
形式参数的作用域仅限于函数体内部。一旦离开函数体,形式参数的值不可访问。
参数的顺序和个数:
在函数调用时,实际参数必须按照形式参数在函数定义中的顺序传递。调用函数时提供的参数个数必须与函数定义中的参数个数一致,除非函数定义了可变参数。
1. #include <stdio.h>
2.
3. // 函数定义,形式参数a和b
4. void calculate(int a, int b) {
5. int result = a + b; // 使用形式参数进行计算
6. printf("The result is: %d
", result);
7. }
8.
9. int main() {
10. int x = 5;
11. int y = 10;
12. calculate(x, y); // x和y作为实际参数传递给形式参数a和b
13. return 0;
14. }
calculate函数定义了两个形式参数a和b。在main函数中调用calculate时,变量x和y作为实际参数传递给a和b。在calculate函数体内,使用这些形式参数进行加法运算,并打印结果。由于C语言是按值传递的,所以函数内部对a和b的修改不会影响x和y的值。
· 函数的返回值
在C语言中,函数的返回值是函数执行完成后返回给调用者的数据。返回值是函数与调用者之间通信的一种方式,它允许函数将计算结果或状态信息传递回去。
1. #include <stdio.h>
2.
3. // 函数定义,返回两个数的和
4. int add(int a, int b) {
5. int sum = a + b; // 计算和
6. return sum; // 返回计算结果
7. }
8.
9. int main() {
10. int result = add(5, 10); // 调用函数并将返回值赋给result
11. printf("The sum is: %d
", result); // 打印返回的和
12. return 0;
13. }
① 返回值类型:
函数的返回类型定义了返回值的数据类型。它可以是基本数据类型(如int、float、char等),也可以是结构体、指针等更复杂的类型。如果函数不返回任何值,则使用void作为返回类型。
② 返回语句:
使用return关键字来从函数返回一个值。return语句后面跟着的表达式会被计算,并将其结果作为函数的返回值。
1. return 表达式; //表达式是计算后将结果返回给调用者的值
return语句后面可以跟任何有效的表达式,该表达式在执行return语句时被计算。
返回的值必须与函数的返回类型声明一致。如果函数返回int,则表达式的结果必须可以转换为int类型。
1. #include <stdio.h>
2.
3. // 函数定义,返回两个整数的最大值
4. int max(int a, int b) {
5. if (a > b) {
6. return a; // 如果a大于b,则返回a
7. } else {
8. return b; // 否则返回b
9. }
10. }
11.
12. int main() {
13. int num1 = 10;
14. int num2 = 20;
15. int maxVal = max(num1, num2); // 调用函数并将返回值赋给maxVal
16. printf("The maximum value is: %d
", maxVal); // 打印最大值
17. return 0;
18. }
③ 按值返回:
C语言中的返回值是通过值传递的方式返回的。这意味着返回值被复制到调用者提供的存储位置。
二:函数的调用
C语言函数调用是程序流程控制的一个重要部分,它允许程序的不同部分通过调用函数来共享代码和数据。C语言函数调用的一般形式如下:
1. 函数名(实际参数列表);
调用函数时使用函数名,必须与函数定义时使用的名称完全一致。调用函数时,函数名后紧跟一对圆括号,即使没有参数也需要包含这对圆括号。
实际参数列表:
函数调用时传递给函数的参数列表,实际参数用于初始化函数定义中的形式参数。实际参数列表中的各项参数以逗号分隔,并且必须与函数定义中的形式参数在数量和类型上匹配(或者能够被隐式转换)。
1. #include <stdio.h>
2.
3. // 函数定义
4. int add(int a, int b) {
5. return a + b;
6. }
7.
8. int main() {
9. int x = 5;
10. int y = 10;
11. int sum = add(x, y);
12. // 函数调用本身可以作为表达式的一部分,例如,它可以出现在赋值语句的右侧或作为其他函数调用的实际参数。
13. printf("The sum of %d and %d is %d
", x, y, sum);
14. return 0;
15. }
函数原型:
C语言中的函数原型是一种向编译器声明函数的方式,它告诉编译器函数的名称、返回类型以及所接受的参数类型和数量。
1. 返回类型 函数名(参数类型1, 参数类型2, ..., 参数类型n);
· 返回类型:函数执行后返回的数据类型。
· 函数名:函数的标识符。
· 参数列表:包括每个参数的类型和顺序,参数名在原型中可以省略。
· 省略参数名:与函数定义不同,函数原型中的参数列表通常不包括参数名,只保留参数类型。
· 空参数列表:如果函数不接受任何参数,参数列表应该为空,但仍需包含一对圆括号()。
计算两个整数乘积的函数,下面是其原型和定义:
1. // 函数原型
2. int multiply(int, int);
3.
4. // 函数定义
5. int multiply(int a, int b) {
6. return a * b;
7. }
8.
9. // 在其他文件或代码部分调用multiply函数
10. int main() {
11. int x = 5;
12. int y = 10;
13. int result = multiply(x, y); // 正确调用multiply函数
14. printf("The result is: %d
", result);
15. return 0;
16. }
multiply的原型声明了函数的返回类型为int,并且接受两个int类型的参数。函数定义提供了函数的实际实现,包括参数名a和b。在main函数中,multiply被正确调用,传递了两个整数值x和y。
嵌套调用和递归调用:
在C语言中,函数的嵌套调用指的是一个函数在执行过程中调用另一个函数。这种调用可以是直接的,也可以是间接的。
· 直接嵌套调用
直接嵌套调用是指在一个函数内部直接调用另一个函数。
1. #include <stdio.h>
2.
3. // 函数定义:计算两个数的和
4. int add(int a, int b) {
5. return a + b;
6. }
7.
8. // 函数定义:计算两个数的乘积
9. int multiply(int a, int b) {
10. return a * b;
11. }
12.
13. // 函数定义:计算表达式 (a + b) * c
14. int calculate(int a, int b, int c) {
15. return multiply(add(a, b), c);
16. }
17.
18. int main() {
19. int num1 = 5;
20. int num2 = 3;
21. int num3 = 2;
22.
23. int result = calculate(num1, num2, num3);
24. printf("Result: %d
", result);
25.
26. return 0;
27. }
在这个例子中:
· calculate函数首先调用add函数计算num1和num2的和。
· 然后将这个和与num3的乘积通过调用multiply函数计算出来。
· 最终结果存储在result变量中。
在C语言中,递归调用是一种函数自己调用自己的方法。
递归函数通常包括以下两个部分:
基本情况:递归终止的条件。
递归情况:函数调用自身的情况。
示例:计算计算一个数的阶乘
1. #include <stdio.h>
2.
3. // 递归函数定义:计算n的阶乘
4. int factorial(int n) {
5. if (n == 0) { // 基本情况
6. return 1;
7. } else { // 递归情况
8. return n * factorial(n - 1);
9. }
10. }
11.
12. int main() {
13. int num = 5;
14. printf("Factorial of %d is %d
", num, factorial(num));
15. return 0;
16. }
示例:斐波那契数列
斐波那契数列是一个每一项都是前两项和的数列,通常定义为:F(0) = 0, F(1) = 1, 且对于 n > 1, 有 F(n) = F(n-1) + F(n-2)。
1. #include <stdio.h>
2.
3. // 递归函数定义:计算斐波那契数列的第n项
4. int fibonacci(int n) {
5. if (n <= 1) { // 基本情况
6. return n;
7. } else { // 递归情况
8. return fibonacci(n - 1) + fibonacci(n - 2);
9. }
10. }
11.
12. int main() {
13. int num = 10;
14. printf("Fibonacci number at position %d is %d
", num, fibonacci(num));
15. return 0;
16. }
[限时练习]
1.以下程序的运行结果是( )
#include <stdio.h>
func(int a, int b) {
static int m = 0, i = 2;
i += m + 1;
m = i + a + b;
return m;
}
main() {
int k = 4, m = 1, p;
p = func(k, m);
printf("%d, ", p);
p = func(k, m);
printf("%d
", p);
}
A.8,7 B.8,17
C.8,8 D.4,1
【答案】B
【解析】第一次调用func(k, m):
初始时,i = 2,m = 0(静态变量的初始值)。
i增加m + 1,变为2 + 0 + 1 = 3。
m更新为i + a + b,即3 + 4 + 1 = 8。
返回m的值为8。
第二次调用func(k, m):
此时,i保留上一次调用的值,即3。
m也保留上一次调用的值,即8。
i再次增加m + 1,变为3 + 8 + 1 = 12。
m更新为i + a + b,即12 + 4 + 1 = 17。
返回m的值为17。
因此,程序的输出是:8, 17
2.C语言程序中,如果函数定义省略了“类型说明符”,则系统认为函数的返回值是( )
A.double B.int
C.float D.char
【答案】B
【解析】在C语言中,如果函数定义时省略了类型说明符,系统默认函数的返回类型是int。这是C语言的一个特性,即如果函数定义中没有明确指定返回类型,则默认为int。
3.下列函数调用语句中,含有实参的个数为( )
func(exp1,exp2,(exp3,exp4))
A.1 B.2 C.3 D.4
【答案】C
【解析】函数调用语句中,实参的个数是由函数调用时传递给函数的表达式的个数决定的。
这里有三个表达式作为参数传递给函数func:exp1、exp2、(exp3,exp4)(这是一个复合表达式,但仍然算作一个参数)因此,含有实参的个数为 3。
4.在C语言的函数调用中,如果普通变量作为函数的实参,则它与对应形参之间的传递方式是( )
A.地址传递 B.由用户指定传递方式
C.由实参传递给形参,再由形参传递给实参 D.单向值传递
【答案】D
【解析】当一个普通变量作为参数传递给函数时,实际上是将这个变量的值复制一份传递给函数的形参。形参对这个值的修改不会影响到实参的原始值。只有当实参是指针类型时,函数才能通过形参间接地修改实参的值。
5.在C语言中规定,函数返回值的类型由( )
A. 定义该函数时所指定的函数类型决定 B. 调用该函数的主调函数决定
C. return语句中的表达式类型决定 D. 调用该函数时系统临时决定
【答案】A
【解析】在C语言中,函数返回值的类型是由定义该函数时所指定的函数类型决定的。这意味着,当你声明或定义一个函数时,你需要指定函数的返回类型,这个返回类型决定了函数返回值的类型。
6.在C语言中,下面关于函数正确的叙述是( )
A. 函数不可以嵌套定义,也不可以嵌套调用
B. 函数可以嵌套定义,但不可以嵌套调用
C. 函数可以嵌套定义,也可以嵌套调用
D. 函数不可以嵌套定义,但可以嵌套调用
【答案】D
【解析】函数不可以嵌套定义,但可以嵌套调用
7.一个函数的组成有( )
A. 函数首部和函数体 B. 函数名、函数类型、函数参数名、函数参数类型
C. 主函数和子函数 D. 函数的声明部分和执行部分
【答案】D
【解析】函数首部定义了函数的名称、返回类型和参数列表,而函数体包含了函数的执行代码。
8.实现一个函数,打印乘法口诀表,输入n,输出n*n口诀表。
【答案】
#include <stdio.h>
// 函数声明
void printMultiplicationTable(int n);
int main() {
int n;
printf("Enter the size of the multiplication table: ");
scanf("%d", &n); // 从用户输入获取n的值
// 调用函数打印乘法口诀表
printMultiplicationTable(n);
return 0;
}
// 函数定义
void printMultiplicationTable(int n) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
printf("%d*%d=%d\t", i, j, i * j); // 打印乘法口诀表的一项
}
printf("
"); // 每完成一行后换行
}
}
9.实现一个函数,判断year是不是闰年。
【答案】
#include <stdio.h>
// 函数声明
int isLeapYear(int year);
int main() {
int year;
printf("Enter a year: ");
scanf("%d", &year); // 从用户输入获取年份
// 判断是否是闰年
if (isLeapYear(year)) {
printf("%d is a leap year.
", year);
} else {
printf("%d is not a leap year.
", year);
}
return 0;
}
// 函数定义
int isLeapYear(int year) {
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
return 1; // 是闰年
} else {
return 0; // 不是闰年
}
}
【归纳小结】
C语言函数是程序模块化的基础,通过定义和调用实现代码复用和任务分离。函数可以接收输入参数,执行特定任务,并可通过返回值输出结果。函数内部的局部变量具有独立作用域,而静态变量则在调用间保持状态。递归函数允许自我调用,但需注意防止无限递归。函数原型确保了调用时参数类型的正确性。
学科网(北京)股份有限公司
$$