1、函数的声明和定义
a、函数的声明,在函数的使用之前,说明存在一个函数,说明函数的返回值类型,名字,形参,形式参数的名字可以省略,一定要先声明后使用
b、函数的定义,详细地写出函数返回值类型,函数名,形参,函数所要实现的某些功能。
做一个较大型的项目,需要多个模块时,可以把每个函数声明放到 .h 文件中,可以把函数定义放到 .c 文件中,在主函数中正常使用函数是,需要引用头文件 #include"add.h"
//主函数所在的模块 #define _CRT_SECURE_NO_WARNINGS #include#include"add.h" int main() { int x = 0; int y = 0; scanf_s("%d %d", &x, &y); int sum = Add(x, y); printf("%d", sum); return 0; } //函数声明所在模块 .h 文件中 int Add(int a, int b); //函数定义所在的模块 新的 .c 文件中 int Add(int a, int b) { return a + b; }
使用别人提供的静态库里的函数,需要引用,我没有了解多少。
2、函数递归
递归:程序调用自身的编程技巧。自己调用自己。一个过程或函数在其定义过程中直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。只需要少量程序就可以解决一些需要重复的步骤的问题,最主要为大事化小。
例题:接受一个无符号的整型值,按照顺序打印它的每一位。 例 输入1234,输出 1 2 3 4 。
#includevoid print(int n) { if (n > 9) { print(n /10); } printf("%d ", n % 10); } int main() { unsigned int num=0; scanf_s("%d ", &num); print(num);//print函数可以把num的每一位按照顺序打印出来 return 0; }
递归的两个必要条件:(1)、存在限制条件,当满足这个限制条件的时候,递归便不再继续。(2)、每次递归调用之后越来越接近这个限制条件。
例题:编写函数不允许创建临时变量,求字符串的长度。
#includeint my_strlen(char* str) { if (*str != ' ') { return 1 + my_strlen(str + 1); } else { return 0; } } int main() { char arr[] = "abcdef"; int len = my_strlen(arr); printf("%dn", len); return 0; }
3、递归与迭代
迭代相当于循环,递归有很多可以写成迭代的方式。
例题:用递归的方法求n的阶乘
#include//递归法 int fac(int n) { if (n <= 1) { return 1; } else { return n * fac(n - 1); } } int main() { int n = 0; scanf("%d", &n); int ret = fac(n); printf("%dn", ret); return 0; }
例题:求第n个斐波那契数(前两个数之和等于第三个数).
fib(n)=fib(n-1)+fib(n-2)(n>=2)
a、递归法存在缺陷,五十次往上的数计算速度会下降很多
#includeint fib(int m) { if (m <= 2) { return 1; } else { return fib(m - 1) + fib(m - 2); } } int main() { int n = 0; scanf_s("%d", &n); int ret = fib(n); printf("%dn", ret); return 0; }
b、迭代法,优于用递归法。
#includeint fib(int m) { int a = 1; int b = 1; int c = 1; while(m>2) { c = a + b; a = b; b = c; m--; } return c; } int main() { int n = 0; scanf_s("%d", &n); int ret = fib(n); printf("%dn", ret); return 0; }
递归重要例题:汉诺塔问题,青蛙跳台阶问题。



