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

news2025/1/13 7:36:40

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

  • 1.函数的声明和定义
    • 1.1函数声明
    • 1.2函数定义
  • 2.函数的嵌套调用和链式访问
    • 2.1嵌套调用
    • 2.2链式访问
  • 3.函数递归
    • 3.1什么是递归
    • 3.2递归的两个必要条件
      • 3.2.1练习1
      • 3.2.2练习2
    • 3.3递归与迭代
      • 3.3.1练习1
      • 3.3.2练习2

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

1.函数的声明和定义

1.1函数声明

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

比如我们写一个加法函数:
在这里插入图片描述

1.2函数定义

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

当然我们函数声明和函数定义也可以写在同一个文件里面:
第一种写法:
在这里插入图片描述
我们必须要保证的是函数的声明必须在函数的定义之前
第二种写法:
在这里插入图片描述

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;
}

就是说函数里面可以在嵌套一个函数,类似于套娃。
但是我们要注意的是我们的函数可以嵌套使用,但是不能嵌套定义。
在这里插入图片描述
这样写是打错的错的。

2.2链式访问

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

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

这里我们介绍一下strlen函数:
在这里插入图片描述
它是专门用来计算字符串长度的函数,遇到’\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的返回值是什么:
在这里插入图片描述
这里说了,返回所包含字符的个数。
我们看一下结果:
在这里插入图片描述
这里先打印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);
}

图解:
在这里插入图片描述

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;
}

图解:
在这里插入图片描述

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(栈溢出)
这样的信息。
系统分配给程序的栈空间是有限的,但是如果出现了死循环,或者(死递归),这样有可能导致一
直开辟栈空间,最终产生栈空间耗尽的情况,这样的现象我们称为栈溢出。

那如何解决上述的问题:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/468278.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android Jetpack—LiveData

1.LiveData LiveData是Android Jetpack包提供的一种可观察的数据存储器类&#xff0c;它可以通过添加观察者被其他组件观察其变更。不同于普通的观察者&#xff0c;LiveData最重要的特征是它具有生命周期感知能力&#xff0c;它遵循其他应用组件&#xff08;如 Activity、Frag…

软件测试—进阶篇

软件测试—进阶篇 &#x1f50e;根据测试对象划分界面测试可靠性测试容错性测试文档测试兼容性测试易用性测试安装卸载测试安全性测试性能测试内存泄漏测试 &#x1f50e;根据是否查看代码划分黑盒测试白盒测试灰盒测试 &#x1f50e;根据开发阶段划分单元测试集成测试系统测试…

mulesoft MCIA 破釜沉舟备考 2023.04.27.25 (易错题)

@[TOC](mulesoft MCIA 破釜沉舟备考 2023.04.27.25 (易错题)) 1. According to MuleSoft, which deployment characteristic applies to a microservices application architecture? A. Services exist as independent deployment artifacts and can be scaled independently…

ABeam Insight | 智能制造系列(6):虚拟/增强现实(VR/AR)×智能制造

虚拟现实&#xff08;VR&#xff09;和增强现实&#xff08;AR&#xff09;的概念早在20世纪60年代就被提出&#xff0c;但由于当时的技术水平无法满足相关应用的需求&#xff0c;这些概念并没有引起广泛关注。直到近年来随着计算机技术的飞速发展&#xff0c;虚拟现实和增强现…

python+nodejs+php+springboot+vue高校教室自习室预约管理系统

建立的自习室预约管理系统用户使用浏览器就可以对其进行访问&#xff0c;管理员在操作上面能够方便管理&#xff0c;因此用户和管理员能够方便对这个系统进行操作。论文全面介绍系统数据库&#xff0c;功能设计和业务流程设计。数据库能够存储自习室预约管理系统需要的数据。 …

Leanback(1)-播放控制栏下添加新的行

我们要在播放控制栏下面加入下面一行。 这个就是标准的row。 leanback的原理 Android Leanback结构源码简析 - 简书 我们知道Row用来提供数据&#xff0c;row可以通过一个ObjectAdapter来管理和提供数据 我们知道presenter是一个负责将数据绑定到视图上的对象&#xff0c;它可以…

基于STM32的智能语音垃圾桶设计

一. 系统设计及框图&#xff1a; 本设计整体功能如下&#xff1a; 1. 超声波感应到有人靠近时语音提示“垃圾放置请分类”。 2. 检测垃圾筒时是否满&#xff0c;当满时语音提示“垃圾桶已满”。 3. 光传感器检测&#xff0c;指示灯指示。 4. 语音识别不同的垃圾类型。 二.…

前端程序员的职业发展规划与路线——ChatGPT的回答

文章目录 一、前端程序员的职业规划是&#xff1f;回答1&#xff1a; 作为一个前端开发程序员&#xff0c;您的职业发展路线可能如下&#xff1a;回答2&#xff1a;作为前端开发程序员&#xff0c;您的职业发展路线可能如下&#xff1a;回答3&#xff1a; 你的职业发展路线可能…

ASEMI代理ADI亚德诺ADM3051CRZ-REEL7车规级芯片

编辑-Z ADM3051CRZ-REEL7芯片参数&#xff1a; 型号&#xff1a;ADM3051CRZ-REEL7 显性状态&#xff1a;78 mA 隐性状态&#xff1a;10 mA 待命状态&#xff1a;275μA CANH输出电压&#xff1a;4.5V CANL输出电压&#xff1a;2V 差动输出电压&#xff1a;3V 输入电压…

【AI生产力工具】Upscale.media:用AI技术提升照片质量,让你的作品更出色

文章目录 简介一、Upscale.media是什么&#xff1f;二、如何使用Upscale.media&#xff1f;三、总结 简介 在如今的数字时代&#xff0c;图片已经成为我们日常生活中不可或缺的一部分&#xff0c;从社交媒体到电子商务网站&#xff0c;从广告宣传到个人生活&#xff0c;都需要…

璀璨盛启·焕美升级 上颜集团杭州医学旗舰中心盛大启幕

2023年4月26日&#xff0c;「璀璨盛启焕美升级」上颜杭州医学旗舰中心启幕盛典在杭州滨江钱龙大厦耀新启幕。上颜用审美、匠心构建城市的活力与色彩&#xff0c;致力于为客户带来全新的美丽方式和一流的品质服务。 &#xff08;上台剪彩嘉宾从左至右依次为&#xff09;上颜集团…

CSS3小可爱亲吻表白特效,给你的五一假期增添点小乐趣

马上五一假期了&#xff0c;小伙伴们是不是都准备出去旅游呢&#xff0c;或者回老家陪陪父母。今天我用CSS3制作一个小可爱亲吻表白的特效&#xff0c;来给你即将到来的五一假期增添点小小的乐趣。 目录 实现思路 左边小可爱的实现 右边小可爱的实现 左右摇摆动效的实现 右…

LeetCode43. 字符串相乘(Java解法)

0 题目描述 给定两个以字符串形式表示的非负整数 num1 和 num2&#xff0c;返回 num1 和 num2 的乘积&#xff0c;它们的乘积也表示为字符串形式。 注意&#xff1a;不能使用任何内置的 BigInteger 库或直接将输入转换为整数。 示例 1: 输入: num1 “2”, num2 “3” 输出…

【三十天精通 Vue 3】 专栏内容介绍

在这个专栏中&#xff0c;我们将带你深入了解 Vue 3 的各个方面。首先&#xff0c;我们将带你了解 Vue 3 的新特性和改进&#xff0c;包括 Composition API、Provide/Use Case、Vuex 3 等。然后&#xff0c;我们将详细介绍 Vue 3 的组件化开发、路由、状态管理等方面的内容。 …

LineSegmentIntersector::Intersections中ratio含义及LineSegmentIntersector相交点说明

osg用osgUtil库中的LineSegmentIntersector、IntersectionVisitor类来求线段和三维模型的交点 如下代码&#xff1a; #include <QtCore/QCoreApplication> #include <osgViewer/Viewer> #include <osgViewer/ViewerEventHandlers> #include <osgViewer…

Duboo介绍与入门

文章目录 1、Dubbo的前世今生2、Dubbo的快速入门2.1、Dubbo的基本架构2.2、Nacos2.3、管理后台2.4、入门案例2.4.1、服务提供者搭建环境代码实现配置文件 2.4.2、服务消费者搭建环境代码实现配置文件 最后说一句 1、Dubbo的前世今生 2011年10月27日&#xff0c;阿里巴巴开源了…

Vue项目解决跨域问题

跨域&#xff08;Cross-Origin&#xff09;是指在浏览器中运行的 JavaScript 代码试图访问不同源的资源时所遇到的一类限制问题。不同源是指协议&#xff08;http、https&#xff09;、域名&#xff08;example.com、google.com&#xff09;、端口号&#xff08;80、8080&#…

双时间维度,你的时间管理大师丨三叠云

双时间维度 路径 表单 >> 表单设计 功能简介 「甘特图视图」新增 双时间维度设置 的配置项。 为了解决日常任务管理中对于“计划时间”维度的时间设置问题&#xff0c;【时间设置】项增加了【双时间维度设置】的配置项&#xff0c;用户开启后可以设置 计划开始时间 …

Matlab 牛顿迭代法(1)牛顿法

一、牛顿迭代公式 1、定义 2、原理推导 泰勒公式&#xff1a; 常用的8个泰勒公式&#xff1a; 推导&#xff1a; 将f(x)f(x)在Xk 处的泰勒公式展开&#xff1a; f(x)f(Xk)f(Xk)(X-Xk) f(Xk)/2 *(x-Xk)^2.......... 我们吧线性的一部分先拿出来&#xff1a;f(x)f(Xk)f(X…

【python知识】容器对象的推导式

一、说明 Python 推导式&#xff0c;是针对容器对象&#xff08;列表,字典&#xff0c;集合&#xff0c;元组&#xff09;的产生方式的语句。它可以从一个数据序列构建另一个新的数据序列的结构体。 Python 支持各种数据结构的推导式&#xff1a; 列表(list)推导式字典(dict)推…