函数递归练习——模拟实现strlen、阶乘和斐波那契

一、关于函数声明与定义分开定义的案例

引言:许多程序员刚刚接触编程的时候,会疑惑为什么不把所有代码内容(特别是不同函数)写在一个源文件中,而是要创建不同的头文件和源文件?

1.为了协作

在公司中不同的员工在一个任务组中共同完成一个项目(比如一个计算器项目),总要有人去写加法、减法、乘法和除法的部分。

不可能所有人在一个源文件中写代码,更可能的实现方式是一个人写一部分,最后整合到一个总工程中,只有一个人实现一部分才能实现工作效率的最大化,冲突的最小化——高内聚低耦合

2.为了模块化

以计算器为例,需要实现各种计算。公司中各种项目也可以划分成一个个小的模块进行分析。每个人完成一个模块的单独功能,保证健壮性,提高可执行性。

案例:如果你是一个计算机天才,开发一个应用程序,想要卖给一个公司。签合同,如果每年公司都使用你的代码,要付给你知识产权费用,你帮助维护和打补丁。

如果你直接把你的源代码——头文件和源文件扔过去,很难不保证这个公司会找一个程序员照扒你的代码,并第二年把你踢出局。为了确保你的代码不会被抄袭,你会将头文件和一个静态库发给公司。

头文件——告诉使用者如果使用你提供的功能,相当于一个功能接口,封装的很好,看不到具体实现(包括函数的声明和需要的头文件),实际使用中公司只需要引用你的头文件就可以使用你的服务

静态库——将源文件进行封装处理,二进制形式难以读懂,琼中包含的是函数的具体实现代码

引入静态库方法:

#pragma comment(lib, "add.lib")

二、递归实现

1.接受一个无符号的整形值,按顺序打印每一位

逻辑一:迭代实现反序打印每一位

#include <stdio.h>

int main()
{
	unsigned int num = 0;
	scanf("%u", &num);
	while (num)
	{
		printf("%d ", num % 10);
		num /= 10;
	}
	return 0;
}

想法是通过不断的模10除10拿到所有十进制位,按顺序存储在数组中,然后反向打印

逻辑二:递归实现正序打印每一位

#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(num);
	return 0;
}

2.编写函数,不允许创建临时变量,求字符串长度

逻辑一:用库函数strlen实现

#include <stdio.h>
#include <string.h>

int main()
{
	int len = strlen("abc");
	printf("%d\n", len);
	return 0;
}

逻辑二:模拟实现strlen,但是使用临时变量记录长度变化

#include <stdio.h>

int my_strlen(char* str)
{
	int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}

int main()
{
	int len = my_strlen("abc");
	printf("%d\n", len);
	return 0;
}

逻辑三:my_strrlen递归版本,不创建临时变量

#include <stdio.h>

int my_strlen(char* str)
{
	if (*str != '\0')
	{
		return 1 + my_strlen(str + 1);
	}
	return 0;
}

int main()
{
	int len = my_strlen("abc");
	printf("%d\n", len);
	return 0;
}

三、递归与迭代对比

1.求n的阶乘

逻辑一:递归版本

#include <stdio.h>

int fac(int n)
{
	if (n > 1)
		return n * fac(n - 1);
	else
		return 1;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = fac(n);
	printf("ret = %d ", ret);
	return 0;
}

逻辑二:迭代版本

#include <stdio.h>

int fac(int n)
{
	int ret = 1;
	int i = 0;
	for (i = 1; i <= n; i++)
	{
		ret *= i;
	}
	return ret;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = fac(n);
	printf("ret = %d ", ret);
	return 0;
}

2.求第n个斐波那契数

斐波那契数列:1 1 2 3 5 8 ···

逻辑一:递归版本

#include <stdio.h>

int Fib(int n)
{
	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);
	return 0;
}

求第50个斐波那契数要超级长时间!!——过多的重复计算

逻辑二:迭代版本

#include <stdio.h>

int Fib(int n)
{
	int a = 1;
	int b = 1;
	int c = 1;
	while (n >= 3)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = Fib(n);
	printf("%d\n", ret);
	return 0;
}

防止递归栈溢出的情况:1.使用静态变量static

                                        2.改用迭代

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ta亻也

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值