【C语言初阶(9)】函数2

news2024/9/20 20:36:38

文章目录

  • 1. 函数的嵌套调用和链式访问
    • 1.1 嵌套调用
    • 1.2 链式访问
  • 2. 函数的声明和定义
    • 2.1 函数定义
    • 2.2 函数声明
    • 2.3 函数的实际应用
  • 3. 函数递归
    • 3.1 什么是递归?
    • 3.2 递归使用条件
    • 3.3 递归的案例
    • 3.4 递归的优缺点
  • 4. 递归练习题

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

  • 函数和函数之间是可以根据实际的需求进行组合的,也就是互相调用。
  • 既然循环之间可以互相嵌套调用,那么函数当然也可以。
  • 函数可以嵌套调用,但是不能嵌套定义。

1.1 嵌套调用

1. 函数只能嵌套调用

#include <stdio.h>
void new_line()
{
	printf("hello world!\n");
}
void three_line()
{
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		new_line();
	}
}
int main()
{
	three_line();
	return 0;
}

在这里插入图片描述

2. 函数不能嵌套定义

  • 函数之间都是平等的,函数之间只有互相调用的关系,但没有主仆关系。

在这里插入图片描述

1.2 链式访问

  • 把一个函数的返回值作为另外一个函数的参数。
  • 链式访问依赖的是函数的返回值。
  • A 函数的返回值作了 B 函数的参数,这些函数之间就像个链条一样串了起来。

举个栗子

  • 把 strlen 函数的返回值作为 printf 函数的参数。
#include <stdio.h>
#include <string.h>

int main()
{
	printf("%d\n", strlen("abcdef"));
	
	return 0;
}

经典链式访问题

  • 下面代码的结果是什么?
#include <stdio.h>
int main()
{
    printf("%d", printf("%d", printf("%d", 43)));
    return 0;
}

在这里插入图片描述

  • printf :printf 函数的返回值是打印在屏幕上字符的个数

在这里插入图片描述

  1. printf1 在屏幕上打印了 43 ,它的返回值是这一次在屏幕上打印的字符个数,也就是 2;
  2. printf2 接收到的 printf1 的返回值就是 2,在屏幕上打印一个字符 2,所以 printf2 的返回值就是在屏幕上打印的字符数量 1 了;
  3. printf3 接收到的返回值自然也就是 1了,所以这段代码的结果才会是 4321 这么一个看起来古怪的答案。

2. 函数的声明和定义

2.1 函数定义

  • C 语言要求函数必须先定义,再调用,定义函数的格式如下:
类型名  函数名(参数列表)
{
        函数体
}
  • 类型名:就是函数的返回值,如果这个函数不准备返回任何数据,那么需要写上 void(void 就是无类型,表示没有返回值)。
  • 函数名:就是函数的名字,一般我们根据函数实现的功能来命名,比如 print_C 就是“打印C”的意思,一目了然。
  • 参数列表:指定了参数的类型和名字,如果这个函数没有参数,那么这个位置直接 void 即可。
  • 函数体:就是指定函数的具体实现过程,是函数中最重要的部分。

举个栗子

//定义一个求两数之和的函数
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int a, b;
	scanf("%d %d", &a, &b);
	printf("%d\n", Add(a, b));
	return 0;
}

2.2 函数声明

  • 所谓声明(Declaration),就是告诉编译器我要使用这个函数,你现在没有找到它的定义不要紧,请不要报错,稍后我会把定义补上。
  • 有时候,你可能会发现即使不写函数的声明,程序也是可以正常执行的。但如果你把函数的定义写在调用之后,那么编译器可能就会找不着北了。
  • 函数的声明一般要用在头文件中

举个栗子

  • 将函数的定义写在调用之后。
#include <stdio.h>
int main()
{
	int a, b;
	scanf("%d %d", &a, &b);
	printf("%d\n", Add(a, b));//先调用再定义
	return 0;
}
//将函数的定义写在调用之后
int Add(int x, int y)
{
	return x + y;
}

在这里插入图片描述

  • 程序的编译是从上到下执行的,所以从原则上来说,函数必须先定义,再调用
  • 但在实际开发中,经常会在函数定义之前调用它们,这个时候就需要提前进行声明了。

函数声明格式

  • 声明函数的格式非常简单,只需要去掉函数定义中的函数体再加上分号即可。
int Add(int x, int y);

在这里插入图片描述

2.3 函数的实际应用

  • 在实际工作的时候,是不会像上面那样将函数都写在同一个源文件底下的。
  • 而是会把 Add 函数写成一个加法模块,在主函数中调用 Add 的头文件即可。各自分开写代码会让逻辑变得更清晰。
  • 将函数的声明、定义以及调用写在不同的文件底下。

举个栗子

在这里插入图片描述

  • .h 文件用于存放函数的声明,放置在头文件底下;

在这里插入图片描述

  • .c 文件用于存放函数的实现,放置在源文件底下;

在这里插入图片描述

  • 想使用 Add 函数的内容就得先引用 头文件 Add.h
#include <stdio.h>
#include "Add.h" //必须先引用 Add.h 才能使用该函数

int main()
{
	int a, b;
	scanf("%d %d", &a, &b);
	printf("%d\n", Add(a, b));
	return 0;
}

在这里插入图片描述

为何将函数的声明及定义放置在不同文件?

  • 在初学编程的时候,觉得把所有的代码写到一个文件中最方便。
  • 但是在工作中,假如所有的开发人员都把他们的函数写到同一个文件中,那这代码简直就没法看了。
  • 不同的程序员在不同的文件底下写自己的函数,最后使用的时候直接引头文件即可。

3. 函数递归

  • “ 从前有座山,山上有座庙,庙里有个老和尚在给小和尚讲故事:‘从前有座山,山上有座庙,庙里有个老和尚在给小和尚讲故事:……’ ”
  • 这种自己套用自己的故事可以讲上一辈子,这个故事就很符合递归这个知识点。

3.1 什么是递归?

递归的概念

  • 从原理上来说函数调用自身的行为称之为递归
  • 在函数内部可以调用其他函数,那么当然也可以调用函数本身。
  • 递归的主要思考方式在于:把大事化小

举个栗子

  1. 接受一个整型值(无符号),按照顺序打印它的每一位。
    • 例如:输入:1234,输出 1 2 3 4。
#include <stdio.h>
void print(unsigned int n)
{
	if (n > 9)//n > 9 就说明还有的拆
	{
		print(n / 10);//n /10 去掉最后一位数字
	}
	printf("%u ", n % 10);//n % 10 获得最后一位数字
}
int main()
{
	unsigned int n;
	scanf("%u", &n);
		print(n);//此处为第一次调用 print 函数,
	return 0;
}
  • 前面几次调用 print 函数的时候其实是没有执行 n % 10 这一步的,而是直接开始下一次递进。

  • 等到了最后 n 不大于 9 不满足执行递进的条件了,开始回归,n % 10 才能够执行。

    • 递进完了之后再从最后一次递进所在的位置开始回归。
  • 先递进,再回归,这就是 [递归]。

看到递归了吗?
在这里插入图片描述

递归的本质

  • 递归的本质说白了就是递进,回归
  • 当达到递进的结束条件时,开始回归,回归是按照递进的轨迹一层一层的归来。
    • 例如: 像我走到五楼时,到了顶层(递进结束条件),此时从五层开始一层一层的回归,直到回到一楼时结束递归。

3.2 递归使用条件

想使用递归有两个必要条件

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

3.3 递归的案例

1. 汉诺塔游戏

  • 汉诺塔游戏要求将最左边柱子的圆盘借助中间柱子依次移动到最右边,要求每次只能移动一个圆盘,并且较大的圆盘必须在下方。

在这里插入图片描述

2. 谢尔斯宾基三角形

  • 三角形里边填充有三角形,只要空间够大,它可以撑满整个宇宙,这就是谢尔斯宾及三角形。

在这里插入图片描述

3. 目录树的索引

  • 后续开发程序可能会遇到目录访问的情况,需要逐层去访问目录,但是并不知道目录究竟有多少层,这时候使用递归就可以很好的解决这个问题。

在这里插入图片描述

3.4 递归的优缺点

1. 递归的优点

  • 代码简介。
  • 在树的前、中、后序遍历算法中,递归明显比循环要更好用。

2. 递归的缺点

  • 在程序执行中,递归是利用堆栈来实现的。每当进入一个函数调用,栈就会增加一层栈帧,每次函数返回,栈就会减少一层栈帧。而栈不是无限大的,当递归层数过多时,就会造成栈溢出的后果。

  • 递归中很多计算都是重复的,由于其本质是把一个问题分解成两个或者多个小问题,多个小问题存在相互重叠的部分,则存在重复计算,如斐波那契数列的递归实现。

4. 递归练习题

  • 可能有小伙伴还是搞不太明白递归到底是怎么一回事,在这篇递归练习题中,我会详细讲解递归的具体:https://editor.csdn.net/md/?articleId=131504627

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

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

相关文章

悟道·天鹰 Aquila + 天秤 FlagEval,打造大模型能力与评测标准双标杆

为推动大模型在产业落地和技术创新&#xff0c;智源研究院发布“开源商用许可语言大模型系列开放评测平台” 2 大重磅成果&#xff0c;打造“大模型进化流水线”&#xff0c;持续迭代、持续开源开放。 开源商用许可语言大模型系列 悟道天鹰&#xff08;Aquila&#xff09; 语…

教师资格证考试(高中数学)-考什么

目录 考什么 及格线 科一-综合素质 ​编辑 科二-教育知识与能力 科三-学科知识与教学能力(数学) 题型 考什么 及格线 大家要明确3个分数&#xff1a; ✅卷面分数&#xff1a;满分为150分&#xff0c;也就是大家平时拿到的试卷及真题卷面分数。 ✅报告分数&#xff1a;…

React 之 组件化开发

本文主讲解类组件&#xff0c;函数组件会在后续文章中学习 一、组件化开发 1. 概念 组件化是一种分而治之的思想&#xff1a; 如果将一个页面中所有的处理逻辑放在一起&#xff0c;处理起来会变得非常复杂&#xff0c;不利于后续的管理以及扩展 但如果讲一个页面拆分成一个个小…

Web安全-AntSword(中国蚁剑)Webshell管理工具使用

为方便您的阅读&#xff0c;可点击下方蓝色字体&#xff0c;进行跳转↓↓↓ 01 工具下载地址02 工具介绍03 使用案例04 参考资料 01 工具下载地址 https://github.com/AntSwordProject/蚂剑工具的下载分为两个部分&#xff0c;一个是项目核心源码antSword&#xff0c;另一个是…

【算法】树形DP ①(树的直径)

文章目录 知识准备例题543. 二叉树的直径124. 二叉树中的最大路径和2246. 相邻字符不同的最长路径 相关题目练习687. 最长同值路径 https://leetcode.cn/problems/longest-univalue-path/solution/shi-pin-che-di-zhang-wo-zhi-jing-dpcong-524j4/1617. 统计子树中城市之间最大…

测试的流程,jira工具的使用

目录&#xff1a; 测试流程价值与体系测试计划业务架构分析思路bug基本概念bug处理流程测试总结业务架构分析工具plantuml测试流程管理jira系统-测试流程定制测试流程管理 jira 系统-Bug管理流程定制 1.测试流程价值与体系 软件测试流程 完成软件测试工作的必要步骤 测试流…

用图计算解密大脑,蚂蚁技术研究院与复旦联手启动类脑研究

大脑为什么会产生意识&#xff1f;我们为什么会失眠&#xff1f;帕金森、阿尔兹海默等神经性疾病如何有效治疗&#xff1f;这一切谜题的背后都绕不开脑科学。可以说脑科学问题是人类面临的基础科学问题之一&#xff0c;是我们解密人类自身的“终极疆域”。 我们的大脑由大约86…

第十二章线程池

文章目录 享元模式手写数据库连接池 为什么需要线程池自定义线程池自定义拒绝策略接口自定义任务队列自定义线程池 JDK中的线程池常用的线程池的类和接口的之间的关系线程池状态构造方法线程池的工作流程拒绝策略 ExecuctorsnewFixedThreadPoolnewCachedThreadPoolnewSingleThr…

【Matlab】智能优化算法_平衡优化器算法EO

【Matlab】智能优化算法_平衡优化器算法EO 1.背景介绍2.数学模型2.1 初始化和功能评估2.2 平衡池和候选者&#xff08;Ceq&#xff09;2.3 指数项&#xff08;F&#xff09;2.3 生成率&#xff08;G&#xff09; 3.文件结构4.伪代码5.详细代码及注释5.1 EO.m5.2 Get_Functions_…

Linux基础服务7——lamp架构

文章目录 一、基本了解二、单机部署LAMP2.1 安装httpd2.2 安装mysql2.3 安装php环境2.4 配置apache 三、分离部署四、脚本单机部署 一、基本了解 LAMP架构介绍&#xff1a; lamp是由LinuxApacheMysql/MariaDBPhp/Perl/Python的一组动态网站或者服务器的开源软件。LAMP指Linux&a…

多元回归预测 | Matlab基于深度置信网络(DBN)回归预测,matlab代码回归预测,多变量输入模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元回归预测 | Matlab多元回归预测 | Matlab基于深度置信网络(DBN)回归预测,matlab代码回归预测,多变量输入模型 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 部分…

原来工作18年的企业大佬都是这样自定义企业微信扫码登录的样式

前言 由于企业微信扫码登录都是固定样式和模板&#xff0c;每个公司在前期使用的时候可能会使用原样的模版&#xff0c;随着业务场景的复杂及细分场景优化&#xff0c;这个固定样式的模版满足不了企业的需求&#xff0c;所以需要对模版进行改造&#xff0c;使它更加贴合企业业务…

【elementplus】解决el-table开启show-overflow-tooltip后,tooltip的显示会被表格边框遮挡的问题

如图所示&#xff1a; 原因&#xff1a; 1. el-table没有设置高度&#xff1b;2.就是被遮住了 解决&#xff1a; 方法一&#xff1a;给el-table设置高度 方法二: .el-table {overflow: visible !important;}如果不想给el-table设置高度&#xff0c;就直接使用方法二解决即可

Pycharm使用Anoconda配置虚拟环境

目录 1.Anoconda的介绍 2.Anaconda的作用 3.Anaconda的安装 4.Anaconda的配置 4.1添加镜像源 4.2创建、使用并切换虚拟环境 5.pycharm的集成 1.Anoconda的介绍 Anaconda是一个可用于科学计算的 Python 发行版&#xff0c;可以便捷获取和管理包&#xff0c;同时对环境进行…

Java内存结构分析

一、Java内存结构划分 Java虚拟机的运行时数据区域主要包括程序计数器、Java虚拟机栈、本地方法栈、堆、方法区。 &#xff08;1&#xff09;程序计数器&#xff08;Program Counter Register&#xff09; 它是一块较小的内存空间&#xff0c;它可以看作是当前线程所执行的字…

SpringBoot项目整合WebSocket+netty实现前后端双向通信(同时支持前端webSocket和socket协议哦)

目录 前言 技术栈 功能展示 一、springboot项目添加netty依赖 二、netty服务端 三、netty客户端 四、测试 五、代码仓库地址 专属小彩蛋&#xff1a;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家…

OLS回归分析理论基础

前言 由于目前的实证研究中需要对变量间的因果关系进行定量分析&#xff0c;所以以伍德里奇和陈强两版本计量经济学教材为基础&#xff0c;有针对性的整理出OLS回归的相关知识&#xff0c;以解决实证分析中的实际问题。 1&#xff09;本文重点&#xff1a;本文重点研究OLS下面板…

vs code koroFileHeader插件相关配置

https://www.cnblogs.com/melodyjerry/p/14449990.html 一、安装插件 koroFileHeader 插件作用&#xff1a;在文件顶部添加头部注释 VS Code 中搜索并安装插件 koroFileHeader&#xff1b; 点击插件右下方的 设置 按钮 > 扩展设置 > 点击 在settings.json 中编辑&…

数据结构 线性表的定义和基本操作(以顺序表为例)

名人说&#xff1a;一花独放不是春&#xff0c;百花齐放花满园。——《增广贤文》 作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 〇、线性表是什么&#xff1f;1、定义2、特点3、基本操作 一、代码实现二、思路阐明…

记录使用ffmpeg把mp4转换成m3u8

背景:公司需要上一些视频资源,平均每一个都在600m以上,经过考虑以后采取视频分片以后上传到oss上进行加速播放的流程.这里记录一下使用ffmpeg进行转换视频格式的过程中的一些命令. 准备工作: 下载ffmpeg到本地,以及配置ffmpeg到环境变量中,这里就不多说了. 使用的时候先打开…