C语言函数
马桶上看算法 人气:0一、函数的嵌套调用
在定义函数时,一个函数内不能再定义另一个函数,即不能嵌套定义,但可以嵌套调用函数,即在调用一个函数的过程中,又调用另一个函数。
⚠️注意:
- 函数可以嵌套调用但是不可以嵌套定义。
- 每一个函数都应该在大括号的外面独立存在。
代码示例:
根据这张图可以清楚的看到,three_line() 函数内部嵌套了一个 new_line() 函数。
当前代码打印了3个haha。
二、函数的链式访问
函数的链式访问就是把一个函数的返回值作为另一个函数的参数。
当前代码,strlen()函数是作为printf()打印函数的参数,把自己的返回值3返回给了printf()函数,所以最终打印结果是:3。
下面代码的打印结果是什么?
#include<stdio.h> int main() { printf("%d", printf("%d", printf("%d", 43))); return 0; }
输出结果:
代码分析:
⚠️注意:printf()函数的返回值是打印字符的个数。
当得知了printf()函数的返回值是打印字符的个数后,可以做出一下分析。
三、函数递归
递归的优缺点
程序调用自身的编程技巧称为递归。可以直接或间接的调用,本质是把复杂的问题转化为一个规模小的问题。递归一般只需少量的代码就可描绘出多次重复计算。递归的主要思考方式:大事化小
必要条件
- 存在限制条件,当满足这个限制条件的时候,递归便不再继续。
- 每次递归调用之后越来越接近这个限制条
使用场景
1. 能够要求转化为新的问题,且二者解决方法相同,所处理的对象存在规律变化。
2. 非递归比较麻烦,而递归很简单。
3. 有模板或是公式可以直接套用,不会出现明显问题。
函数递归的细节说明
1. 每级递归都有自己的变量,可能名称相同,但是值不同。
递归调用时,系统自动保留当前函数的参数变量。
每次调用系统都会为函数开辟相应的空间。
2. 每次调用都要返回值,递归执行结束后,控制权传回到上一级函数。
调用结束后,系统释放本次调用所开辟的空间,
程序返回到上一次的调用点,同时获得初进该级调用的参数。
每级递归必须逐级返回,不可跳跃或间断。
3. 函数中递归语句之前的代码,按被调函数的顺序执行,
递归之后的代码,与被调函数相反的顺序执行。
举例说明
接受一个整型值(无符号),按照顺序打印它的每一位。例如,输入:1234,输出:1 2 3 4
代码示例:
#include<stdio.h> void print(unsigned int n) { if (n > 9) { print(n / 10); } printf("%d ", n % 10); } int main() { unsigned int num = 0; scanf("%u", &num); //print函数可以打印参数部分数字的每一位 print(num); //函数递归 - 自己调用自己 return 0; }
输出结果:
代码分析:
对两个必要条件的理解
存在限制条件,当满足这个限制条件的时候,递归便不再继续。
每次递归调用之后越来越接近这个限制条件。
如果是递归,两个限制条件必定满足。
四、递归练习
编写函数不允许创建临时变量,求字符串的长度:
题目要求不允许创建临时变量,当前代码不符合要求。
#include<stdio.h> #include<string.h> int my_strlen(char* str) { int count = 0; // 临时变量 //printf("%c\n", *s); while (*str != '\0') { count++; str++; } return count; } int main() { //求字符串的长度 char arr[] = "haha"; int len = strlen(arr); printf("%d\n", len); return 0; }
符合要求的写法:
#include<stdio.h> #include<string.h> int my_strlen(char* str) { if (*str == '\0') { return 0; } else { return 1 + my_strlen(str + 1); } } int main() { //求字符串的长度 char arr[] = "haha"; //arr是数组名,数组名是数组首元素的地址 int len = my_strlen(arr); printf("%d\n", len); return 0; }
代码分析:
运行结果:
加载全部内容