Loading... 9.1 函数 ====== 函数 (Function) , 一个封装起来的功能模块 函数的一般形式: ``` 返回值类型 函数名 ( 参数列表 ) { 函数体 } ``` 示例1: 写一个函数:假设一个班有32人,实现报数的功能。 (1) 定义一个函数 ``` void report( ) { } ``` (2) 调用这个函数 ``` report ( ) ; ``` 函数的定义 ----- 1 函数与main()函数的位置是并列的,顶格书写 2 自定义函数写在 main() 的前面 3 函数的命名规则:和变量名规则相同 一般使用动词结构来命名,如: ``` start(), stop(), open(), close(), start_now(), stop_quietly(), remove_all(), ``` 函数的调用 ----- 函数:表示有一个功能模块 函数调用:使用这个功能 使用函数名加括号,来调用一个函数 ``` report( ); ``` 函数可以调用多次,没有限制。 小结 -- 初步引入了函数的概念 学会定义最简单的函数,并在main()里调用 9.2 函数的参数(1) ============ 函数的参数 , Arguments 函数的一般形式: -------- 返回值类型 函数名 ( 参数列表 ) { 函数体 } 示例1 --- 假设1班有32人,2班46人,分别报数 问题:report1() 和 report2() 逻辑相同 代码存在很大的重复冗余 ``` #include <stdio.h> void report1() { for (int i = 1; i <= 32; i++) { printf("%2d ", i); if (i % 10 == 0) { printf("\n"); // 每10个换行 } } printf("\n"); } void report2() { for (int i = 1; i <= 46; i++) { printf("%2d ", i); if (i % 10 == 0) { printf("\n"); // 每10个换行 } } printf("\n"); } int main() { printf("1班报数!\n"); report1(); printf("2班报数!\n"); report2(); getchar(); return 0; } ``` 示例2 --- 优化办法:把变化的部分作为参数变量 ``` void report (int N ) { } ``` 这样,代码逻辑就统一了,所区别的是N值不同 给 report 函数添加一个参数 ``` #include <stdio.h> void report(int N) { for (int i = 1; i <= N; i++) { printf("%2d ", i); if (i % 10 == 0) { printf("\n"); // 每10个换行 } } printf("\n"); } int main() { printf("1班报数!\n"); report( 32 ); printf("2班报数!\n"); report( 46 ); getchar(); return 0; } ``` 函数的参数 ----- 比如,有一个函数表示空调致冷的功能 ``` void freeze () { … } ``` 是的,它能够致冷,但是要致冷到多少度呢? 显然,目标温度应该是一个外部传入的参数,而不是内部定死 添加一个参数,表示目标温度 void freeze (int degree) { } 使用时,freeze(20) 表示我调到20度,freeze(16) 表示我想要更冷的温度 小结 -- - 介绍了什么是函数的参数 - 参数的作用 - 参数的声明:和普通变量一样,类型+名字 9.3 函数的参数(2) ============ 函数是可以设置多个参数的,称为 参数列表 比如,空调都是可以设置多个参数的 void freeze (int degree, int fan, int mode) { … } 其中,degree, 温度, fan , 风量, mode, 模式 示例1: ---- 示例:显示【120,300】之间的完全平方数 void show( int from, int to ) { } 此函数有两个参数:int from, int to ``` #include <stdio.h> // 显示 [from,to] 之间所有的完全平方数 void show(int from, int to) { for (int i =from; i <= to; i++) { for (int k = 1; k <= i; k++) { if (k * k == i) { printf("%d = %d x %d \n", i, k, k); } } } printf("\n"); } int main() { printf("显示【120,300】之间的完全平方数! \n"); show(120, 300); getchar(); return 0; } ``` 示例2 --- ``` #include <stdio.h> #include <stdbool.h> // 显示三角形 // reversed: true, 显示倒三角; false, 显示正三角 void triangle(int N, bool reversed) { for (int i = 1; i <= N; i++) { // 每行星星的个数 int numStar = i; if (reversed) { numStar = N - i + 1; } // 打印一行星星 for (int k = 1; k <= numStar; k++) { printf("*"); } printf("\n"); } } int main() { triangle(8, false); getchar(); return 0; } ``` 参数的传递 ----- 1 按顺序 2 按类型 类型不匹配时,需要转换 小结 -- - 介绍了函数有多个参数的情形 - 所以,函数可能没有参数,也有可能有多个参数 9.4 函数的返回值(1) ============= 函数的返回值 , Return Value 函数的一般形式: ``` 返回值类型 函数名 ( 参数列表 ) { 函数体 } ``` - 函数: 可以做一件事情 - 函数的返回值:这件事件的结果 打个比方,让小明去买一支冰淇淋, 他买了,并且自己吃了 void buy ( int money ) { } 他买了,然后把冰淇淋交给来 IceCream buy ( int money ) { } 注:void 表示不返回任何东西 示例1 --- 写一个函数:求两个数的平方和 ``` int compute( int a, int b) { } ``` 这个函数将返回a, b的平方和,返回值的类型为int ``` #include <stdio.h> #include <stdbool.h> // 求两数的平方和 int compute(int a, int b) { int result = a * a + b * b; return result; } int main() { int v = compute(3, 4); printf("结果为: %d \n", v); getchar(); return 0; } ``` - return 语句:返回一个值 ``` int compute(int a, int b) { int result = a * a + b * b; return result; } ``` 首先计算出结果,然后使用return返回 示例2 --- 写一个函数:用于判断一个数是否为完全平方数 ``` bool is_square ( int n ) { } ``` 结果是true/false,所以应该返回bool类型 ``` #include <stdio.h> #include <stdbool.h> // 返回值: true, 是完全平方数; false, 不是完全平方数 bool is_square(int n) { bool result = false; for (int i = 1; i <= n; i++) { if (i * i == n) { result = true; break; } } return result; // 返回结果 } int main() { for (int i = 200; i < 300; i++) { // 调用is_square()方法,并取得其返回值 bool ok = is_square(i); if (ok) { printf("%d 是完全平方数!\n", i); } } getchar(); return 0; } ``` 基本步骤 ---- 函数的返回值的写法: 1 先确定结果是什么类型 2 在函数里先计算出结果,然后用return返回 注意:printf 只是辅助调试用的,并不是返回 小结 -- 介绍了函数的返回值的意义,及其用法 9.5 函数的返回值(2) ============= ##return 语句 return 语句有两个作用: 1 返回一个值 2 立即退出函数 所以,在函数体里,当确定结果的时候就可以立即返回。函数会立即退出。 示例1 --- 判断一个数是否为完全平方数 ``` #include <stdio.h> #include <stdbool.h> // 返回值: true, 是完全平方数; false, 不是完全平方数 bool is_square(int n) { bool result = false; for (int i = 1; i <= n; i++) { if (i * i == n) { result = true; break; } } return result; // 返回结果 } int main() { for (int i = 200; i < 300; i++) { // 调用is_square()方法,并取得其返回值 bool ok = is_square(i); if (ok) { printf("%d 是完全平方数!\n", i); } } getchar(); return 0; } ``` 示例2 --- 显示N行的三角形星星 ``` #include <stdio.h> #include <stdbool.h> // 显示三角形 // reversed: true, 显示倒三角; false, 显示正三角 void triangle(int N, bool reversed) { for (int i = 1; i <= N; i++) { // 每行星星的个数 int numStar = i; if (reversed) { numStar = N - i + 1; } // 打印一行星星 for (int k = 1; k <= numStar; k++) { printf("*"); } printf("\n"); } } int main() { triangle(8, false); getchar(); return 0; } ``` 小结 -- 介绍了函数的return的用法 1 return时,函数立即退出 2 如果函数是void,也可以用return退出函数 9.6 数组作为参数 ========== 数组参数 ---- 当需要传递一个数组给函数时: (1) 数组首地址 (2) 数组长度 ``` void test ( int* arr, int size) { } ``` 写一个函数,求数组里的最大值 `int a[] = { 12, 39, 99, -18 };` `int b[] = { -90, 29, 0, 12 , 92, 8888 };` 注:当数组长度未指定时,为大括号内的实际个数 ``` #include <stdio.h> #include <stdbool.h> int find_max(int* arr, int size) { int max = arr[0]; for (int i = 1; i < size; i++) { if (arr[i] > max) { max = arr[i]; } } return max; } int main() { int a[] = { 12, 39, 99, -18 }; int max = find_max(a, 4); printf("a[]最大值为: %d\n", max); int b[] = { -90, 29, 0, 12 , 92, 8888 }; max = find_max( b, 6); printf("b[]最大值为: %d\n", max); getchar(); return 0; } ``` 示例2 --- 已知一个数组 `int a[ ] = { 23, 99, 8, 44, 10, 72, 90, 12 };` 求前3项的和,后3项的和 ``` #include <stdio.h> #include <stdbool.h> int sum(int* arr, int size) { int result = 0; for (int i = 0; i < size; i++) { result += arr[i]; } return result; } int main() { int a[] = { 23, 99, 8, 44, 10, 72, 90, 12 }; int v1 = sum(a, 3); // 前3项的和 int v2 = sum(a + 5, 3); // 后3项的和, 或sum(&a[5], 3) printf("前3项的和:%d, 后3项的和: %d \n", v1, v2); getchar(); return 0; } ``` 小结 -- - 介绍了如何传递一个数组作为参数 - 数组首地址,数组长度 9.7 函数的调用 ========= 可以在表达式中直接嵌入函数的返回值 示例1:已知 a=1.3 ,求a + a2 + a3 的值 total = a + power(a, 2) + power(a, 3); ``` #include <stdio.h> #include <stdbool.h> // 求a的n次方 double power(double a, int n) { double result = 1.0; for (int i = 0; i < n; i++) { result *= a; } return result; } int main() { double a = 1.3; double total = a + power(a, 2) + power(a, 3); getchar(); return 0; } ``` 示例2: ---- 求100-200间的完全平方数 ``` #include <stdio.h> #include <stdbool.h> // 判断 n 是否为完全平方数 bool is_square(int n) { for (int i = 1; i <= n; i++) { if (i * i == n) { return true; } } return false; } int main() { for (int i = 100; i <= 200; i++) { if (is_square(i)) { printf("%d 是完全平方数\n", i); } } getchar(); return 0; } ``` 可以发现,可以直接使用函数调用的返回值 ``` if ( is_square(i) ) { printf("%d 是完全平方数\n", i); } ``` 示例3: ---- 求100-200之间的完全平方数 ``` #include <stdio.h> #include <stdbool.h> // 判断 n 是否为完全平方数 bool is_square(int n) { for (int i = 1; i <= n; i++) { if (i * i == n) { return true; } } return false; } void show_square(int from, int to) { for (int i = from; i <= to; i++) { if (is_square(i)) { printf("%d 是完全平方数\n", i); } } } int main() { show_square(100, 200); getchar(); return 0; } ``` 结论:函数里还可以调用别的函数 main() → show_square() → is_square() 注:一层层的调用,形成“函数栈” ( 菜单 :调试|窗口|调用堆栈 ) 注意: --- 多层函数调用时,注意书写顺序 ``` is_square() { } show_square() { } main() { } main() → show_square() → is_square() ``` 小结 -- - 介绍了函数调用的方法 - 可以直接使用返回值 - 可以嵌套调用多层函数 9.8 函数的声明 ========= 函数的顺序 ----- 编译器在编译test.c时,是从上往下依次处理的 ``` void triangle(int N, bool reversed) { } int main () { triangle(10, true); } ``` 显然,在调用一个函数时,必须得先知道它的存在 ! 如果把triangle() 写在 main() 的下面会怎样 … 编译器看到 main() 里有一行triangle() .. 但是此时,它并不是知道 triangle是个啥 ... 一般会报告“未定义”的错误,或者“不能识别” 函数的声明 ----- 解决方案有两种: 1 先定义,后调用 2 先声明,后调用,再定义 声明:void triangle(int, bool); 调用:int main() { triangle(10, true); … } 定义:void triangle(int N, bool reserved){ … } 函数的声明:void triangle(int, bool); 就是先告诉编译器:别慌,triangle是一个函数 这种不带参数名字、不带函数体的形式,叫函数原型 (prototype) 小结 -- - 介绍了函数声明的作用 - 为了练习的方便,还是先定义、后使用 最后修改:2020 年 10 月 31 日 © 允许规范转载 打赏 赞赏作者 赞 如果觉得我的文章对你有用,请随意赞赏