一、关于函数声明与定义分开定义的案例
引言:许多程序员刚刚接触编程的时候,会疑惑为什么不把所有代码内容(特别是不同函数)写在一个源文件中,而是要创建不同的头文件和源文件?
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.改用迭代