C语言基础之——函数(下)

前言:本期内容将承接上期C语言基础之——函数(上)的内容来继续讲解函数方面的知识。

目录

一.函数的嵌套调用和链式访问

1.嵌套调用

2.链式访问

 二.函数的声明与定义

1.函数的声明

2.函数的定义

三.函数递归

1.什么是递归

2.递归的两个必要条件

四.总结


一.函数的嵌套调用和链式访问

1.嵌套调用

函数与函数之间可以根据实际的需求进行组合,也就是说,使用一个函数时,可以在它的函数体里边在调用另一个函数,这便是嵌套调用

#include<stdio.h>
void fun1()
{
    printf("hehe\n");
}
void fun2()
{
    printf("haha\n");
    fun1();
}
int main()
{
    fun2();
    return 0;
}

我们来看这样一段简单的代码,我们在函数fun2里调用了函数fun1,然后再在main函数中调用函数fun2,结果如下:

 “hehe”“haha”都被打印出来了,这便是嵌套调用。

这里要注意一点,函数虽然可以嵌套调用,但却不能嵌套定义,也就是说不能在一个函数中来定义另一个函数。

#include<stdio.h>

void fun2()
{
    void fun1()
        {
            printf("hehe\n");
        }
    printf("haha\n");
}
int main()
{
    fun2();
    return 0;
}

像上边这种代码就是绝对不允许的,这就和不能在main函数中定义函数一样

2.链式访问

把一个函数的返回值(函数尾),作为另一个函数的参数(函数头),我们可以理解为将几个函数按从头到尾的顺序连接在一起,像一条函数链,这便是链式访问

我们来举一个常见的例子来帮助大家理解:

#include<stdio.h>
#include<string.h>
int main()
{
	int arr[] = "1234567";
	int len = strlen(arr);
	printf("%d", len);
	return 0;
}
-------------------------------------------------------------------------------------------
int main()
{
	int arr[] = "1234567";
	printf("%d", strlen(arr));
	return 0;
}

strlen()函数printf()函数都是我们常用的函数,我们先来看第一段代码,我们定义了整型变量len来接收strlen()函数的返回值, 而后len作为printf()函数的参数被打印

再看第二段代码,我们并没有定义任何变量来接收strlen()函数的返回值,而是直接将strlen(arr)这样一个整体用做printf()函数的参数

事实上,strlen(arr)便是strlen()函数对应的返回值,只是我们平时习惯于定义一个新变量来接收。

 二.函数的声明与定义

1.函数的声明

  • 告诉编译器这个函数叫什么,参数是什么,返回值是什么,这便是函数的声明。
  • 函数的声明要在使用之前。
#include<stdio.h>
int main()
{
	int a = 2;
	int b = 5;
	Add(a, b);
	return 0;
}
void Add(int x, int y)
{
	printf("%d", x + y);
}

我们之前的讲解所写的代码,自定义函数都是在main函数的前边,但是现在我们把它放在main函数的后边,会有什么不一样吗???

 

 很遗憾,这样的做法是错误的。

我们知道,编译器是从上到下一行一行阅读代码的,对于上述代码,因为Add函数在main函数之后,编译器在main函数中调用到Add函数时,编译器并不认识Add函数,所以就发生了错误。

但是如果这样的话,自定义函数就必须在main函数之后吗???当然不是:

#include<stdio.h>
void Add(int x, int y);//提前声明
int main()
{
    int a = 2;
    int b = 5;
    Add(a, b);
    return 0;
}
void Add(int x, int y)
{
    printf("%d", x + y);
}

我们只需要在main函数之前声明一下Add函数,便可以正常使用了。这里的声明只需要函数的头,便可以让编译器记住Add函数,不要忘记末尾要加上';'

2.函数的定义

具体交代一个函数到底是什么构造,有什么作用,这便是函数的定义。

void Add(int x, int y)
{
	printf("%d", x + y);
}

这便是一个简单的加法函数的定义。

三.函数递归

1.什么是递归

简单来说,递归就是一个函数自己嵌套调用自己,也就是——套娃。意在于把大事化小

下面给大家演示一个史上最简单的递归代码: 

#include<stdio.h>
int main()
{
	printf("hehe\n");
	main();
	return 0;
}

结果如下:

 它会无止境的打印“hehe”。

2.递归的两个必要条件

  • 事实上,函数递归也类似于循环,存在限制条件,当满足这个限制条件的时候,递归便不再继续。
  • 每次递归调用之后都要越来越接近这个限制条件

 下面我们便正式借助一个例子来具体讲解函数递归:

接收一个整型值(无符号),按顺序打印出它的每一位。

例如:输入:1234,输出:1 2 3 4.

如果这个代码,我们不用递归,正常来写的话,只需要先判断这个数的位数,然后再利用辗转相除取商来实现,代码如下,仅供了解:

#include<stdio.h>
int main()
{
	int n;
	scanf("%d", &n);
	int count = 1;
	int z = n;
	while (z > 10)//循环统计位数
	{
		z /= 10;
		count *= 10;
	}
	while (count > 0)//辗转相除取商
	{
		int x = n / count;
		n = n % count;
		count /= 10;
		printf("%d ", x);
	}
		return 0;
}

我们可以看出,正常写虽然不是很难,但是代码有些过于繁琐,那么,递归又是怎么实现的呢?

#include<stdio.h>
int print(int n)
{
	if (n > 9)
	{
		print(n / 10);
	}
	printf("%d ", n % 10);
}
int main()
{
	int n;
	scanf("%d", &n);
	print(n);
	return 0;
}

下面我们就来具体讲解一下这段递归代码是怎么运转的。

首先呢,我们输入一个整数:1234

进入函数中,n > 9 便是一个限制条件

如果n > 9 那么我们就递归调用这个函数,并且将 n / 10 的商作为参数传入

直到 n == 1 时,我们才停止嵌套,随后开始从内向外的打印 n % 10 的余数

如果这样你还是不太理解的话,那么来看我接下来的操作:

#include<stdio.h>
int print(int n)// n = 1234
{
	if (n > 9)
	{
		int print(int n / 10) //n = 123
		{
			if (n > 9)
			{
				int print(int n/ 10)//n = 12
				{
					if (n > 9)
					{
						int print(int n / 10) //n = 1
						{
							if (n > 9)//不满足
							{
								print(n / 10);//不执行
							}
							printf("%d ", n % 10);//打印1
					}
					printf("%d ", n % 10);//打印2
			}
			printf("%d ", n % 10);//打印3
	}
	printf("%d ", n % 10);//打印4
}

如果是这样的形式,你是不是就豁然开朗啦哈哈哈,没错,其实本质就是这种套娃,但是我们不能这样写代码,一是冗杂,二是编译器也不能通过

四.总结

由于函数递归是C语言知识中的一个重点,也是一个难点,所以在此博主就不过多展开讲解啦,后续会抽时间做一期文章来专门详解函数递归,敬请期待!

好啦,关于函数的知识到这里就要结束啦,喜欢博主文章的小伙伴们不要忘记一键三连哦!

我们下期再见!

猜你喜欢

转载自blog.csdn.net/2303_78442132/article/details/132395198
今日推荐