函数和函数之间可以根据实际的需求进行组合的,也就是互相调用的。
#include <stdio.h>
void new_line()
{
printf("hehe\n");
}
void three_line()
{
int i = 0;
for (i = 0; i < 3; i++)
{
new_line();
}
}
int main()
{
three_line();
return 0;
}
函数可以嵌套调用,但是不能嵌套定义
把一个函数的返回值作为另外一个函数的参数。
#include <stdio.h>
#include <string.h>
int main()
{
char arr[20] = "hello";
int ret = strlen(strcat(arr, "bit"));//这里介绍一下strlen函数
printf("%d\n", ret);
return 0;
}
#include <stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d", 43)));
//结果是啥?
//注:printf函数的返回值是打印在屏幕上字符的个数
return 0;
}
结果是4321
函数的定义是指函数的具体实现,交待函数的功能实现。
无论是变量还是函数,都得满足先声明后使用。
一般情况下:
add.h文件 放函数的声明
add.c文件 放函数的定义
test.c文件 (#include “add.h”)里面可以调用函数
这样写可以将代码进行封装和隐藏。
test.c中需要使用某个函数,某人卖给他使用,但不暴露函数实现的源代码,某人将add模块生成静态库add.lib,将add.h文件和静态库add.lib卖给别人使用。别人使用add.h文件和test.c文件,并在test.c文件中写上以下这样的代码:
#pragma comment(lib,“add.lib”)
#incluide “add.h”
即可使用
程序调用自身的编程技巧称为递归( recursion)。
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接
调用自身的
一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,
递归策略
只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的主要思考方式在于:把大事化小
通俗来说,递归就是自己调用自己
每一次函数调用都要在栈区申请空间,当栈区空间耗干,就会出现栈溢出(Stack overflow)
存在限制条件,当满足这个限制条件的时候,递归便不再继续。
每次递归调用之后越来越接近这个限制条件。
接受一个整型值(无符号),按照顺序打印它的每一位。
例如:
输入:1234,输出 1 2 3 4
#include <stdio.h>
void print(int n)
{
if (n > 9)
{
print(n / 10);
}
printf("%d ", n % 10);
}
int main()
{
int num = 1234;
print(num);
return 0;
}
编写函数不允许创建临时变量,求字符串的长度
思路:当发现指向的第一个字符不是’\0’时,长度为1,字符串的长度是1+其余字符串的长度。
#include <stdio.h>
int Strlen(const char* str)
{
if (*str == '\0')
return 0;
else
return 1 + Strlen(str + 1);
}
int main()
{
char* p = "abcdef";
int len = Strlen(p);
printf("%d\n", len);
return 0;
}
注意点
因为++是后置,已经把a的地址传进去了,str再++,str++后的结果留给当前函数了。当调用my_strlen时,新的my_strlen函数2的str还是指向a的,之后再调用的其他my_strlen中的str都是指向a的。所以如果写成str++,直接死递归了。
🎗?所以,在递归中尽量不要写成前置++,或者后置++,会带有副作用
写成str+1,就是把下一个字符的地址传进去了,str没动
写成str++,把下一个字符地址传进去了,str也动了,如果递归回来,还想使用这个地址的话,而这个地址已经变了,就有问题了。
求n的阶乘。(不考虑溢出)
int factorial(int n)
{
if(n <= 1)
return 1;
else
return n * factorial(n-1);
}
求第n个斐波那契数。(不考虑溢出)
🎗?斐波那契数列:
1 1 2 3 5 8 13 21 34 55 …
特点:当前位置的值是前两个数相加的和。
这样写可以解决问题,但是当我们输入的n值比较大时,比如50,在程序的运行窗口迟迟计算不出来结果,为什么呢?
探究
接下来我们可以统计一下Fib(3)的调用次数
代码如下:
#include<stdio.h>
int count = 0;
int Fib(int n) {
if (n == 3) {
count++; //统计的是第三个斐波那契数被重复计算的次数
}
if (n <= 2) {
return 1;
}
else {
return Fib(n - 1) + Fib(n - 2);
}
}
int main() {
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("%d\n", ret);
printf("count=%d\n", count);
return 0;
}
由此发现,递归虽然能解决问题,但是它的效率比较低。
换个思路
用迭代的思路,一直用a+b赋值给c,如果计算的结果c过大会溢出,所以范围有限。
提示:
函数递归的几个经典题目(自主研究):