c语言——函数(2)

本文介绍了C语言中函数的嵌套调用和链式访问,强调了函数可以嵌套调用但不能嵌套定义,并通过示例解释了链式访问的概念。此外,讨论了函数的声明与定义的重要性,以及函数递归的基本原理和应用,通过实例展示了如何使用递归解决打印数字每位的问题。
摘要由CSDN通过智能技术生成

本文章是c语言中介绍函数的第二篇,第二篇的主要内容大概由:

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

6.函数的声明与定义

7.函数递归

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

5.1函数的嵌套调用

在学习函数的嵌套调用之前,我们首先明确一个定义:函数可以嵌套调用,但是不可以嵌套定义!

下面,我们对这两种情况分别进行解释

5.1.1函数的嵌套定义再次强调函数不可以嵌套定义!函数不可以嵌套定义!函数不可以嵌套定义!)例如:

可以看到,这就是一个函数嵌套定义的例子,当我们在定义一个函数时,在这个函数内部再定义一个函数,则显示错误 。

5.1.2函数的嵌套调用:

同样,我们先来举个例子:

可以看到,如果我们在名为dayin的函数中去调用上面定义的add函数,则显示正常,这里,为了更加清楚的说明函数在嵌套调用的情况下是可以正常运行的,我们写一个代码:先写一个加法函数,如果这个加法函数的结果是5,则在另一个函数中打印正确 ,否则显示错误

 如图所示,我们在主函数中调用了dayin函数,在dayin函数中,我们又调用了add函数,同时,为了方便说明,我们直接人工将打印函数的结果设置为5,结果如下:

可以看到,结果显示是正确。

如果我们更改加法函数的值,使他的结果不等于5

结果如下,显示为错误:

这个例子,再次验证了我们开头提到的那句话,即函数可以嵌套调用,但是不可以嵌套定义

5.2函数的链式访问 

首先我们简要说一下链式访问的概念,即:把一个函数的返回值作为另一个函数的参数

下面,我们再举个例子:

如图,我们写这样一个函数,用于打印字符串的长度,可以在下图看到,结果为5

如果,我们将上述代码简化,把两行代码合并成一行代码,则:

打印结果依旧是5,这就是把strlen函数的返回值作为printf函数的参数,也就是我们上面所提出的,链式访问概念:把一个函数的返回值作为另一个函数的参数。

在了解了链式访问的的概念之后,我们来看一个有趣的代码

首先,我们需要明确一点,就是Printf函数的返回值,是他打印的字符的数目,所以,这里的链式访问,可以理解为三个步骤:最里面的printf函数的打印了字符串“43”,因为一共打印了两个字符,所以他的返回值是2。

中间的printf把最里面的printf的返回值,也就是“2”,当做参数,进行打印。因为只打印了2这一个字符,所以他的返回值就是1

最外层的printf函数接收到的参数是中间printf函数的返回值,也就是1,所以最外层的函数打印“1”

最后的结果就是“4321”。结果如下:

如果我们对上述代码再进行更改,把printf函数的打印格式从“%d" 改成”%d ",又会变成什么样子呢?

首先我们先放上更改后的代码:

首先,我们直接放上结果:

此时可以看到

结果从“4321”变成了“43 3 2”,这是因为,我们更改了printf函数打印的格式,在后面多加了一个空格,所以,最内层的printf函数的打印内容便是“43 ”,此时最内层函数的返回值便是“3 ”,中间的printf函数接收到的参数就是“3 ”,此时进行打印,且中间的printf函数的返回值是2,因此,最外层printf函数的打印结果就是“2”,因此,最终结果便是:“43 3 2”

6.函数的声明与定义

同样,我们通过一个例子来解释函数的声明与定义

如图所示,这是一个简单的加法函数,但是如果我们把函数定义的部分,放到主函数下面,会发生甚, ?

可以看到,此时程序运行发生了错误

这是因为,编译器在编译代码的时候,是从上往下一依次编译的。编译器在编译上面的代码时,因为只看到了我们调用了一个函数,但是并没有找到我们对于该函数的定义,所以会发生错误,此时,如果我们遇到了函数定义必须在主函数之后的情况,就可以使用函数声明 ,如下图

当我们在主函数前面加上函数声明的时候,虽然我们对于函数的定义在主函数后面,但是代码依然可以运行。所以,在使用一个函数之前,必须对这个函数提前声明。

通过上面的例子,接下来,我们直接引出函数声明的定义:

1. 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数

声明决定不了。

2. 函数的声明一般出现在函数的使用之前。要满足先声明后使用

3. 函数的声明一般要放在头文件中的。

7.函数递归

首先,我们先说明函数递归的定义:

程序调用自身的编程技巧称为递归( recursion)。

递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接

调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相

递归策略

规模较小的问题来求解,只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。

可以看到,函数递归的定义是相对复杂的,如果我们用一句话来概括函数递归,就是:函数自己调用自己就称为函数递归

为了更形象的解释递归,下面我们给出一个最简单的关于递归的例子:

可以看到,main函数在打印函数后面,自己调用了自己,这就是一个简单的递归的例子。

注:上述关于递归的代码只是用于举例,这并不是一个好的代码,无限次的打印hehe会造成栈溢出导致程序卡死

下面,我们通过一个具体的问题,来详细说明函数递归的特点,例如:

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

例如:

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

 我们先对这个题目进行简单的解析,输入1234,如果我们想要得到4,则用1234%10就可以得到,如果我们想要得到3,则我们先1234/10得到123,再用123%10就可以得到,同理,如果想得到2,则先123/10得到12,再12%10,最后再单独打印1即可。不过这样用常规方法输入会过于啰嗦,在函数递归的定义中我们得知,函数递归的主题思想就是把问题由大化小,我们可以通过这个思想,把这个问题拆分,通过上面对于题目进行的简单的解析,我们发现,相对于打印1 2 3 ,打印4会简单很多,只需要让12345\%10即可,所以,将题目拆分为,先打印(123) 4,再把(123)拆开,先打印(12) 3,再把(12)拆开,变成打印 1 2,同时可以看到,需要进行拆分时,数据都是2位数,即都是>9的,由此,我们可以通过下面这个函数递归来解决这个问题。

很难想象,通过函数的递归,原本复杂的问题所需的代码只是短短的这十几行,接下来,我们将对于这串代码如何实现目的进行详细的解读:

首先,我们通过主函数,输入1234,此时1234被传入函数中

,因为1234>9,所以进入(print/10),此时,代码不会执行printf函数。

此时print的值为123,下面经过判定,123>9,所以,再次进入print(n/10)

 这是,得出来的结果等于12,再次进入print函数,

 经过判定,因为12>9,所以在进入print(n/10)。这时,print(n/10) = 1

 经过判定,1<9,不符合if语句的条件,于是进入下方的printf函数,打印n%10,因为此时的n = 1,所以最终打印结果为1,这时,函数在返回去向上执行每个步骤没有执行的printf函数,

这时,不再执行if语句中的内容,而是单纯的执行上面没有执行的printf函数,此时的n =12,n%10 = 2,最终打印结果为2,然后再向上返回去执行没有执行的printf

此时的n = 123,n%10 = 3,最终打印结果为3,打印结束后,再次向上返回执行没有执行的printf函数

此时的n = 1234,n%10 = 4,打印结果最终为4,由此可见,经过printf函数的四次打印,我们通过函数递归,成功的将“1234”分成:1 2 3 4,四步进行打印。

注:关于内存如何保存1234 123 12 1,并在printf函数返回时进行四次打印时进行使用,将在后面单独写一篇文章进行介绍,这里不过解释)

通过上面一个例子,相信我们对递归的理解又加深了一点,这里我们直接总结出函数递归的两个必要条件:

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

每次递归调用之后越来越接近这个限制条件。

 

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
sscanf函数C语言中一个非常常用的函数,它可以将一个字符串按照指定的格式转换成相应的数据类型。在嵌入式开发中,sscanf函数也是非常常见的,因为很多时候需要从串口或者其他外部设备中读取数据,并将其转换成相应的数据类型进行处理。下面是一些sscanf函数的使用技巧: 1. 使用sscanf函数时一定要注意格式字符串的正确性。格式字符串中的占位符必须与待转换的数据类型相对应,否则会发生未知错误。 2. 如果待转换的字符串中包含多个数据,可以使用多个占位符进行转换。例如,如果待转换的字符串为"1,2,3",可以使用" %d,%d,%d"的格式字符串进行转换。 3. 可以使用sscanf函数的返回值来判断转换是否成功。如果返回值等于待转换字符串的长度,则说明转换成功,否则转换失败。 4. 如果待转换的字符串中包含浮点数,可以使用"%f"或者"%lf"的格式字符串进行转换。 5. 如果待转换的字符串中包含十六进制数,可以使用"%x"的格式字符串进行转换。 6. 如果待转换的字符串中包含字符或字符串,可以使用"%c"或者"%s"的格式字符串进行转换。 7. 如果待转换的字符串中包含指针类型的数据,可以使用"%p"的格式字符串进行转换。 总之,在使用sscanf函数时一定要注意格式字符串的正确性,否则很容易出现转换错误的情况。同时,还应该注意sscanf函数返回值的判断,以确保转换的正确性。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

起床写代码啦!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值