代码编织梦想

目录

前言

嵌套定义与调用

函数的链式访问

函数的声明和定义

函数的声明

函数的定义

函数声明和函数定义的具体实现

 函数递归


前言

        上期我们大致讨论了函数的分类以及函数的调用方式,今天让我们继续讨论。

嵌套定义与调用

函数的嵌套定义是不支持的。

//函数嵌套定义是不支持的
int main(){
    void print(){
        printf(" haha\n");
}
    return 0;
}

函数的嵌套定义不支持,但是函数的嵌套调用是支持的。 

     

函数的链式访问

什么是函数的链式访问呢?顾名思义,链式访问就是链式访问,哈哈,开个玩笑。

在c语言中,我们把一个函数的返回值作为另一个函数的参数,我们把这样的方式称为函数的链式访问。

int main() {
	printf("%d\n",strlen("abc"));
	printf("%d", printf("%d", printf("%d", 43)));
}

 上述代码便是函数的链式访问。strlen是去求字符串的长度,返回的就是字符串的长度,而printf是输出函数,函数返回的是打印的字符的个数。

函数的声明和定义

函数的声明

         简单来说就是声明了一个函数,告诉编译器,这个函数叫什么,参数是什么,返回类型是什么?

        注意:1>函数的声明必须在函数使用之前,满足先声明后使用的原则。

                   2>函数的声明一般放在头文件(.h)中。

函数的定义

        函数的定义就是函数具体功能的实现。

函数声明和函数定义的具体实现

        想必大家都知道,c语言中有两种文件,头文件(.h)和源文件(.c),一般情况下,我们在.h文件中放函数的声明,在.c文件中放函数的实现。

        举个例子:(实现两个数相加的函数)

 函数递归

        这里直接给出定义:在c语言中,程序调用自身的编译技巧称为递归,就是把原来较大的问题划分成与许多个与原来大问题相似的小问题再去解决。优点:使用很少的代码就可以实现多次重复的计算,大大减少了程序的代码量。主要思想就是把大问题划分成小问题。

        需要注意的是,要想实现递归就必须满足以下两个条件:

        1.存在限制条件,当满足这个限制条件的时候,递归便不再继续   。 

        2.每次递归之后,越来越接近这个限制条件。    

       个人觉得,递归的思想就类似于第一期我们讨论的循环。

 例1:实现一个整型值(无符号),按照顺序打印它的每一位,例如:输入1234,打印1,2,3,4

        基本算法如下:将打印1234分为以下几步,分别将其拆为打印其个位与除个位以外的其它位。得到个位直接模10,得到其它位除以10即可,再将除以10之后的其它所有位,按如上方法继续进行打印,直到打印出1234即可,这便用到了递归。我们得判断这个数是否大于等于10,因为只有大于等于10的数才会被分解成个位和其它位,这就是我们的的限制条件。

 

 

#include<stdio.h>
void print(unsigned int n)
{
	if (n > 9)
	{
		print(n / 10);
	}

	printf("%d,", n % 10);

}
int main() {
	unsigned int n = 10;
	scanf("%d", &n);
	print(n);
	return 0;
}

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

算法思想:要求整个字符串的长度,我们可以理解为求为(1+除过第一个元素剩下的字符串的长度)。如果数组首元素的值与'\0'相同,证明该字符串的长度为零,那么我们不就不能递归,所以这便成了递归的限制条件。具体代码如下:

#include<stdio.h>
int my_strlen(char* p) {
	if (*p != '\0') {
		return(1 + my_strlen(p + 1));
	}
	else {
		return 0;
	}
}
int main() {
	char arr[10] = "abcdefg";
	int num = my_strlen(arr);
	printf("%d\n",num);
	return 0;
}

运行结果如下: 

例3:求n的阶乘

算法思想如下图:

显而易见,可以用递归,递归的限制条件就是n>=2

代码如下:

int fac(int n) {
	if (n >= 2) {
		return n * fac(n - 1);
	}
	else {

		return 1;
	}


}
int main() {
	int n = 0;
	scanf("%d",&n);
	int ret = fac(n);
	printf("%d\n",ret);
	return 0;
}

需要注意的是,如果因为我们设置的是整型变量,如果计算的值太大,计算的结果可能不正确,这时只需要改变变量的类型即可。

 例4:求斐波那契数列

算法如下:

我们可以用函数递归,递归的限制条件就是n>2,代码如下:

int fib(int n) {
	if (n > 2) {

		return fib(n - 1) + fib(n - 2);
	}
	else {

		return 1;
	}	
}
int main() {
	int n = 0;
	scanf("%d", &n);
	int ret = fib(n);
	printf("%d\n",ret);
	return 0;
}

     截图如下:

当输入很小的数时,控制台会很快输出答案,但是当我们输入的数字很大时,控制台久久不会给出答案,为什么呢,想想,当输入的数字很大时,会导致栈溢出,所以迟迟不显示结果,栈溢出是什么,大家可以先行百度,后期会与大家一起讨论,那么究竟有没有一种更好的实现方法呢?

对于处理器而言,加法的处理是很快的,能不能把这个函数转化为加法函数呢?

当然可以,代码如下:

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

运行结果如下:

                 数字不管多大,都能很快的给出答案,同样的,当你给n特别大时,因为int类型所存放的值的大小是有限制的,所以会出现负值,改一下变量的类型即可。

        好了这便是c语言函数的所有内容了,我们讨论到了函数的分类,函数的参数,函数的调用方式,函数声明定义和函数递归,希望大家通过这些内容能帮助大家进一步认识c语言函数,如果对大家有帮助的话,那真是泰裤辣!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_55958734/article/details/130844612