函数声明:
1.告诉编译器有一个函数叫什么,参数是什么,返回类型是什么,但是具体是不是存在,函数声明决定不了。
2.函数的声明一般出现在函数使用之前,要满足先声明后使用。
3.函数的声明一般要放在头文件中。
函数定义:
函数定义是指函数的具体实现,交代函数的功能实现。
函数定义在后面,在前面使用,会产生警告,因为是从前往后执行的。
在函数使用之前,加上函数声明就不会产生警告。
函数递归
程序调用自身的编程技巧称为递归。
递归作为一种算法在程序设计语言中广泛应用,一个过程或函数在其定义或说明中有直接或间接调用自身的。
一种方法,它通常把一个大型复杂的问题层层转换为与一个与原问题相似的规模较小的问题来求解,递归策略。
只需少量的程序就可描述出解题过程中需要的多次重复计算,大大减少了程序的代码量。
递归的主要思考方式在于:把大事化小
递归的两个必要条件
1.存在限制条件,当满足这个限制条件的时候,递归便不在继续。
2.每次递归调用后越来越接近这个限制条件。
//输入1234,按位输出:1 2 3 4
把大事化小:
print(1234) ---> print(123) 4 ---> print(12) 3 4 ---> print(1) 2 3 4 ---> 1 2 3 4
#include <stdio.h>void print(int x){if(x / 10 != 0){print(x / 10);}printf("%d\n",x % 10);
}
//输入1234,输出:1 2 3 4
int main()
{int n = 0;scanf("%d",&n);print(n);return 0;
}
自定义求字符串长度的函数
#include <stdio.h>//int my_strlen(char* ch){
// int count = 0;
// while(*ch != '\0')
// {
// count++;
// ch++;
// }
// return count;
//}
//不创建临时变量,求字符串长度
int my_strlen(char* ch){if(*ch != '\0'){//return my_strlen(++ch) + 1;//这种写法虽然可以,但是会改变chreturn my_strlen(ch + 1) + 1;}elsereturn 0;
}
int main()
{int length = 0;char ch[12] = "Hello World";length = my_strlen(ch);printf("%d\n",length);system("pause");return 0;
}
上面一种注释掉的方法是用while循环,并创建临时变量来辅助计数,也可以使用递归:
my_strlen("abc") ---> 1 + my_strlen("bc") ---> 1 + 1 + my_strlen("c") ---> 1 + 1 + 1 + my_strlen("") ---> 1 + 1 + 1 + 0 = 3
计算k的阶乘
#include <stdio.h>//计算k的阶乘//递归实现
//int fac(int x){
// if(x != 1)
// return x * fac(x - 1);
// else
// return 1;
//}//迭代实现
int fac(int x){int i = 0;int ret = 1;for(i = 1;i <= x;i++)ret = ret * i;return ret;
}
int main()
{int k = 0;int n = 0;scanf("%d",&k);n = fac(k);printf("%d\n",n);return 0;
}
斐波那契数列:
#include <stdio.h>//斐波那契数列
//递归
//int Fibonacci(int x){
// if(x <= 2)
// return 1;
// else
// return Fibonacci(x - 1) + Fibonacci(x - 2);
//}
//非递归
int Fibonacci(int x){int i = 0;int a = 1;int b = 1;int c = 0;if(x <= 2)return 1;elsefor(i = 3;i <= x;i++){c = a + b;a = b;b = c;}return c;
}
//1 1 2 3 5 8
int main()
{int k = 0;int n = 0;scanf("%d",&k);n = Fibonacci(k);printf("%d\n",n);return 0;
}
系统分配给程序的栈空间是有限的,但是如果出现了死循环或死递归,这样有可能导致一直开辟栈空间,最终产生栈空间耗尽的情况,这样的现象我们成为栈溢出。
如何解决上述问题:
1.将递归改写为非递归
2.使用 static 对象替代 nonstatic 局部对象。在递归函数设计中,可以使用static对象替代nonstatic局部对象(即栈对象),这不仅可以减少每次递归调用和返回时产生和释放nonstatic对象的开销,而且static对象还可以保存递归调用的中间状态,并且可为每个调用层所访问。