【C语言】函数讲解(下)

这篇具有很好参考价值的文章主要介绍了【C语言】函数讲解(下)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

所属专栏:C语言
博主首页:初阳785
代码托管:chuyang785
感谢大家的支持,您的点赞和关注是对我最大的支持!!!
博主也会更加的努力,创作出更优质的博文!!
关注我,关注我,关注我,重要的事情说三遍!!!!!!!!

1.函数的声明和定义

1.1函数声明

  1. 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数声明决定不了。
  2. 函数的声明一般出现在函数的使用之前。要满足先声明后使用。
  3. 函数的声明一般要放在头文件中的(以.h结尾的文件)。

比如我们写一个加法函数:
【C语言】函数讲解(下)

1.2函数定义

函数的定义是指函数的具体实现,交待函数的功能实现。
而函数的定义一般放在以.h 为后缀的文件中的。
【C语言】函数讲解(下)
而这里其实重点在于为什么要把函数的声明和定义都写在不同的地方呢?
其实这种写法一般都只出现在一些大型的程序开发中出现的。因为一个大型的程序开发肯定不只有一个人编写代码的,而是由很多人一起编写,最后再把他们链接在一起的,而程序的开发都是由众多的函数嵌套所组成的,如果说我们把函数的声明和定义都写在一个文件里面的话那么一次只能由一个人编写,不但会影响代码的编写速度还很有可能一位每个人的编写代码风格不同导致程序出现错误,所以才要分开写。

当然我们函数声明和函数定义也可以写在同一个文件里面:
第一种写法:
【C语言】函数讲解(下)
我们必须要保证的是函数的声明必须在函数的定义之前
第二种写法:
【C语言】函数讲解(下)

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

2.1嵌套调用

函数和函数之间可以根据实际的需求进行组合的,也就是互相调用的。
就比如:

#include <stdio.h>
void line()
{
 printf("hehe\n");
}
void _line()
{
    int i = 0;
 for(i=0; i<3; i++)
   {
        line();
   }
}
int main()
{
 	_line();
 	return 0;
}

就是说函数里面可以在嵌套一个函数,类似于套娃。
但是我们要注意的是我们的函数可以嵌套使用,但是不能嵌套定义。
【C语言】函数讲解(下)
这样写是打错的错的。

2.2链式访问

把一个函数的返回值作为另外一个函数的参数。
一般我们计算字符串长度的时候会这样写:

int main()
{
    char arr[20] = "hello";
 	int ret = strlen(arr));
 	printf("%d\n", ret);
 	return 0;
}

这里我们介绍一下strlen函数:
【C语言】函数讲解(下)
它是专门用来计算字符串长度的函数,遇到’\0’停止。(后期会详细讲到)
所包含的头文件是#include<string.h>

我们也可以使用函数链式访问来写:

int main()
{
    char arr[20] = "hello";
 	printf("%d\n", strlen(arr));
 	return 0;
}

这个和上面的结果是一样的。
我们再来看下面一串代码:

#include <stdio.h>
int main()
{
    printf("%d", printf("%d", printf("%d", 43)));
    return 0;
}

我们看一下这个结果是什么,这个时候我们就要知道printf的返回值是什么:
【C语言】函数讲解(下)
这里说了,返回所包含字符的个数。
我们看一下结果:
【C语言】函数讲解(下)
这里先打印43;在打印了printf(“%d”, printf(“%d”, 43))也就是打印printf(“%d”, 43)的返回值,而43是两个字符所以返回的是2,所以打印出来了2;再就是 printf(“%d”, printf(“%d”, printf(“%d”, 43)))打印 printf(“%d”, printf(“%d”, 43))的返回值,在上面我们知道了 printf(“%d”, 43)的返回值是2,那么 printf(“%d”, printf(“%d”, 43))== printf(“%d”, 2)自然它的返回值就是1,所以就打印出来了1。

3.函数递归

3.1什么是递归

程序调用自身的编程技巧称为递归( recursion)。
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接
调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问
题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程
序的代码量。
递归的主要思考方式在于:把大事化小

3.2递归的两个必要条件

  • 存在限制条件,当满足这个限制条件的时候,递归便不再继续。
  • 每次递归调用之后越来越接近这个限制条件

3.2.1练习1

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

void print(int n)
{
	if (n == 0)
		return;
	print(n/10);
	printf("%d", n%10);
}
int main()	
{
	int num = 1234;
	print(num);
}

图解:
【C语言】函数讲解(下)

3.2.2练习2

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

#include <stdio.h>
int Strlen(const char*str)
{
 if(*str == '\0')
 	return 0;
 else
      return 1+Strlen(str+1);
}
int main()
{
 	char *p = "abc";
 	int len = Strlen(p);
 	printf("%d\n", len);
 	return 0;
}

图解:
【C语言】函数讲解(下)

3.3递归与迭代

3.3.1练习1

求n的阶乘。(不考虑溢出)

int factorial(int n)
{
 	if(n <= 1)
 		return 1;
 	else
 		return n * factorial(n-1);
}
int main()
{
	int n=0;
	scanf("%d",&n);
	printf("%d",factorial(n));
	return 0;
}

3.3.2练习2

求第n个斐波那契数。(不考虑溢出)

int fib(int n)
{
 	if (n <= 2)        
		 return 1;
    else
    	return fib(n - 1) + fib(n - 2);
}
int main()
{
	int n=0;
	scanf("%d",&n);
	printf("%d",fib(n));
	return 0;
}

但是我们发现有问题;

  • 使用 fib 这个函数的时候如果我们要计算第50个斐波那契数字的时候特别耗费时间。
  • 使用 factorial 函数求10000的阶乘(不考虑结果的正确性),程序会崩溃。

在调试 factorial 函数的时候,如果你的参数比较大,那就会报错: stack overflow(栈溢出)
这样的信息。
系统分配给程序的栈空间是有限的,但是如果出现了死循环,或者(死递归),这样有可能导致一
直开辟栈空间,最终产生栈空间耗尽的情况,这样的现象我们称为栈溢出。

那如何解决上述的问题:文章来源地址https://www.toymoban.com/news/detail-430615.html

  1. 将递归改写成非递归。
  2. 使用 static 对象替代 nonstatic 局部对象。在递归函数设计中,可以使用 static 对象替代
    nonstatic 局部对象(即栈对象),这不仅可以减少每次递归调用和返回时产生和释放
    nonstatic 对象的开销,而且 static 对象还可以保存递归调用的中间状态,并且可为各个调用层
    所访问。
  3. 许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更为清晰。
  4. 但是这些问题的迭代实现往往比递归实现效率更高,虽然代码的可读性稍微差些。
  5. 当一个问题相当复杂,难以用迭代实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开销。

到了这里,关于【C语言】函数讲解(下)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • memcmp函数详解 看这一篇就够了-C语言(函数讲解、函数实现、使用用法举例、作用、自己实现函数 )

    memcmp()函数用于:比较两个内存块 函数声明:int memcmp ( const void * ptr1, const void * ptr2, size_t num ); 参数: ptr1:指向内存块的指针。 ptr2:指向内存块的指针。 数字:要比较的字节数。 返回值: 0: 在两个内存块中不匹配的第一个字节在  ptr1  中的值低于 在 ptr2  中的值(如果计

    2023年04月09日
    浏览(64)
  • C语言中usleep与nanosleep函数讲解以及毫秒级休眠实现

    我们一般接触比较多的就是sleep函数了,这个的话就不用多说了,大家都知道。我们来介绍一下usleep以及nanosleep函数。 (1)函数讲解 为什么先介绍nanosleep函数呢?这是因为后面讲到的usleep函数中微妙级的实现是根据nanosleep函数实现的。 函数名称的 nano 是纳米、纳秒等计量单

    2024年02月08日
    浏览(34)
  • 【C语言】指针的基本知识详细讲解(指针数组、数组指针、函数指针....

    接着上次的函数的基本知识,今天我们来讲一讲🔍指针 目录 一、指针的概念 二、指针变量 三、野指针 四、字符指针 五、指针与数组 六、指针数组 七、数组指针  八、指针与函数 总结 一、指针的概念 1.1、变量和地址 所谓指针,也就是内存的地址;所谓指针变量,也就是

    2023年04月08日
    浏览(41)
  • Streamlit 讲解专栏(八):图像、音频与视频魔法

    欢迎各位读者来到“最全Streamlit教程”专栏系列!如果您正在寻找一种简单而强大的方式来创建交互式数据应用程序,那么Streamlit无疑是您的最佳选择。作为该领域的热门框架,Streamlit让数据科学家、开发者和爱好者能够以前所未有的速度构建出引人入胜的数据可视化工具。

    2024年02月13日
    浏览(32)
  • C语言随机数的产生(rand、srand、time函数细节讲解)

    先上代码,再详细解释: 我们先来查询下rand函数 网站旧版我放在这儿,可以查询库函数等https://legacy.cplusplus.com/reference/cstring/strcat/ rand函数的头文件是stdlib.h。 rand函数无需传参数,返回类型是一个伪随机的整数范围是0到RAND_MAX。那这个RAND_MAX所对应的值是多少呢?我们同样

    2024年02月08日
    浏览(53)
  • Streamlit 讲解专栏(十):数据可视化-图表绘制详解(上)

    在数据可视化的世界中,绘制清晰、易于理解的图表是非常关键的。Streamlit 是一个流行的 Python 库,它提供了简单的界面和强大的功能,帮助用户轻松创建交互式应用程序和数据可视化。而其中的 Chart elements(图表元素)部分则为我们提供了多种图表类型来展示数据。 本文将

    2024年02月12日
    浏览(37)
  • Streamlit 讲解专栏(十一):数据可视化-图表绘制详解(中)

    在上一篇博文《 Streamlit 讲解专栏(十):数据可视化-图表绘制详解(上)》中,我们学习了一些关于数据可视化的基础知识,探索了Streamlit库中的几个常见图表绘制函数,包括st.line_chart、st.area_chart、st.bar_chart和st.pyplot。通过这些函数,我们可以轻松地绘制不同类型的图表

    2024年02月10日
    浏览(46)
  • Streamlit 讲解专栏(十二):数据可视化-图表绘制详解(下)

    数据可视化在数据分析和数据科学领域中扮演着至关重要的角色。通过可视化数据,我们能够更好地理解其背后的模式和趋势,从而作出准确的决策和预测。然而,要将原始数据转化为有意义的图表并不容易。这就是为什么我们需要强大而灵活的工具来帮助我们实现这一目标

    2024年02月09日
    浏览(38)
  • 计算机语言 之【C++】入门级知识讲解(命名空间,C++输入输出,缺省参数,函数重载,引用,内敛函数,auto关键字,for循环,指针空值nullptr)

    三点睡六点起,阎王夸我好身体 不到三点我不睡,太平间里抢C位 目录: 前言: 本片博客是以学习过C语言之后进入C++学习为前提,讲解C++入门级知识,为C++之后的学习做铺垫 –❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀-正文开始-❀–❀–❀–❀–❀

    2024年04月11日
    浏览(134)
  • 微信小程序:微信小程序中首页onLoad()函数加载两次问题(已解决)

    我在学习微信小程序的开发的过程中,在学到云开发时,首页要加载服务器数据,发现onLoad函数被加载了两次,如图 然后来搜,发现问题出在了onShow函数这,这个函数只有在此页面第一次加载时才会被调用,而这个函数里不知道什么时候加上了这行代码 this.onLoad() (可能是开

    2024年02月16日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包