庖丁解牛函数知识---C语言《2》
目录
前言:
1.嵌套调用函数
2.链式访问
3.函数的声明与定义
4.*递归
5.递归与非递归
❤博主CSDN:啊苏要学习
▶专栏分类:C语言◀
C语言的学习,是为我们今后学习其它语言打好基础,C生万物!
开始我们的C语言之旅吧!✈
前言:
在第一篇的基础上,我们接着学习函数相关的知识。虽然都是基础知识,但干货满满,读来没有新的知识收获,也有复习的奇效。
1.嵌套调用函数
在C语言中,调用函数是非常常见的。我们需要使用函数来解决问题,自然就需要把函数给调出来使用。那么什么是嵌套调用呢?我们看下面的代码:
#include <stdio.h>void put_word(int n)
{if (11 == n)printf("I miss you!\n");if (13 == n)printf("I want to say\n");
}
void put_line()
{int a = 0;int i = 0;printf("Hello long time no see!\n");for (i = 0; i < 2; i++){if (i != 1){printf("你可以输入两次\n");}printf("请输入你要听的字符数(13,11)>:");scanf("%d", &a);put_word(a);}}
int main()
{put_line();return 0;
}
这段代码的逻辑是:先在main函数里调用put_line函数;进入到put_line函数里面再调用了put_word函数;这里是多层调用,A调用B,B调用C来完成"我想你"这段有趣的输出。这种就是函数的嵌套调用。
函数的嵌套调用是必要的,比如在生成汽车的时候,原材料从哪里来,各种原材料加工厂是原材料变成相应的部件,最后组装在一起变成汽车。在计算机中,每个函数就是一个部件,最后有机组合(嵌套调用)在一起,完成程序任务。
补充:
相信大家看完这段代码后,印象会更深刻一点~
2.链式访问
链式访问是将函数的返回值作为一个函数的参数使用。
#include <stdio.h>
#include <string.h>int main()
{int len = strlen("abcdef");printf("%d\n", len);printf("%d\n", strlen("abcdef"));return 0;
}
printf函数参数为strlen("abcdef")利用的就是函数的链式访问,strlen返回字符串的长度,这个长度作为printf函数的参数被打印出来。
它的效果和使用整型len接收strlen返回的长度,并打印len是一样的。
我们接下来看这样一段代码,感受函数的链式调用:
#include <stdio.h>int main()
{printf("%d", printf("%d", printf("%d", 43)));return 0;
}
这段代码将打印什么呢?首先最外层的printf要打印一个整型值,它要看里层printf函数的返回值是多少; 里层函数要打印一个整型值,它要看最里层printf函数的返回值是多少;这个时候,从最外层的printf函数打印,层层往里像一条链一样串起来。
现在已经分析到最里层的printf函数了,它打印了43这个整型,但我们不知道printf函数打印完后,返回什么东西,这时候我们得上网站查一查:cplusplus.com
具体的使用方法可以快速阅读一下上一篇函数知识讲解如何学习库函数:链接
得知printf函数的返回值是成功读取到字符的个数;那么最里层printf函数成功读取到43这两个字符,返回值是2;上面的代码就变成了printf("%d", printf("%d", 2));这样子了。接着就是里层打印2,成功读取的字符个数是1,返回值为1,变成printf("%d", 1);。
最终在屏幕上显示的就是:
3.函数的声明与定义
函数的使用必须遵循先声明后使用的原则。
#include <stdio.h>int Add(int, int);//声明Add函数
int main()
{int a = 10;int b = 20;printf("%d\n", Add(a, b));return 0;
}int Add(int x, int y)//定义函数
{return x + y;
}
声明函数的时候,需要指出它的返回类型、函数名、函数的参数类型,由于声明是一条语句,不要漏了最后的分号。
补充:函数声明参数的时候,可以只写类型,而不用写名字。我们不必写int Add(int x, int y);。
由于程序的执行流程是从上往下执行的,程序入口是main函数,所以将定义放在函数使用之前,就可以不用声明。
#include <stdio.h>int Add(int x, int y)//定义函数
{return x + y;
}int main()
{int a = 10;int b = 20;printf("%d\n", Add(a, b));//已经知道Add是什么样的函数了return 0;
}
这是一种特殊的声明,定义声明。主旨思想就是:编译器需要知道你使用的函数是什么,要么定义在我使用之前,要么你告诉我这个函数是什么。
4.*递归
函数自己调用自己叫做递归;递归往往能将一个大量重复的计算用简洁少量的代码写出来,递归的本质是大事化小。我们先来看一个代码:
#include <stdio.h>//打印12345的每一位数
void print(int n)
{if(n > 9){print(n/10);//打印1234的每一位数}printf("%d ", n%10);//打印5}//打印1234的每一位数
//void printf(int n)
//{
// if(n > 9)
// {
// print(n/10);//打印123的每一位数
// }
// printf("%d ", n%10);//打印4
//}
//...
//...
//打印1的每一位数
//void printf(int n)
//{
// if(n > 9)
// {
// print(n/10);
// }
// printf("%d ", n%10);//1
//}int main()
{int n = 0;scanf("%d", &n);//12345//将n的每一位打印出来print(n);return 0;
}
想求数字12345的每一位,可以使用取模取商交替使用的方法求。12345%10 = 5;得到数字5。12345/10得到数字1234;再将1234%10 = 4;得到数字4。1234/10得到数字123........。
打印12345的每一位数,我们定义一个print函数用来求之。利用大事化小的本质,可以这样思考:使用print函数打印1234的每一位+打印数字5,再将(打印数字1234的每一位)分解成,打印123每一位+打印数字4.......。
这个比较难理解,再过一会下面有图解,保证清晰易懂~。
从这个思考里面我们可以得出:每次打印最后一位是需要打印数字每一位的最后一位,也就是说当我需要打印数字12345的每一位的时候,我需要打印5,然后在打印数字1234的每一位的时候,我需要打印4。以此类推,直到当我在打印数字1的时候,我把最后一位1打印出来,已经没有数字了,程序停止。
注意的要点是:递归需要有限制,没有限制条件或限制条件不恰当都会导致栈溢出。
在调用函数的时候,函数需要在栈上开辟空间,这个过程叫做压栈,如果递归一直持续下去没有完结,栈上的空间都被占满了,没有栈空间程序就自动挂掉,并给警告说栈溢出。
所以使用递归的时候,有两个注意点:
- 进行递归是有限制条件的,不是可以任何情况都可以递归下去。
- 每进行一次递归调用,都会使递归条件越来越接近结束条件。
在求数字的每一位的时候,进行递归的条件是大于9,也就是要有两位数才进行递归,如果只有一位数,那直接取余打印出来就OK了。每次递归n的值都会少一位,所以这个递归不会出现很大的问题。最重要的一点来了:用画图法来解释刚刚这道代码题,保证能理解透彻。
一层一层往下递推下去,限制条件限制继续往下递归的时候,开始往回退,一层一层处理,结束。
5.递归与非递归
一般能用递归解决的问题,都可以使用循环解决,因为递归实际上也相当于是在重复做一件事,只不过递归不像循环一样一点都不变,但仍可以使用循环代替。是使用循环还是递归呢?我们需要结合具体情况。
求斐波那契数列的第n的数:
#include <stdio.h>//递归实现
int Fib(int n)
{if(n <= 2)return 1;elsereturn Fib(n-2)+Fib(n-1);
}
int main()
{int n = 0;scanf("%d", &n);int ret = Fib(n);printf("%d\n", ret);
}
斐波那契数列的规律是:1 1 2 3 5 8 13 21 34 55.......、从第三各个数开始,每个数都是前两个数的和。递归的实现思路是:如果求的是第一,第二个斐波那契数列,就返回1;如果不是就返回求n-1和n-2的斐波那契数列值。这样一直递归求下去直到n<=2时到达限制条件,不再递归下去了,开始回溯。
假如我们求的是第五十个斐波那契数列,那么由代码可知,我们会求第48斐波那契数列值和第49斐波那契数列值;48再求46和47的,49在求47和48的;这样每次递归下去,求的数值都翻一倍,重复计算很多,效率非常低下。我们可以用一个计数器,看看求40的斐波那契额数列值时,Fib(3)被重复计算了多少次!
被重复计算了3千9百多万次!!! 这时候用递归来求是不可以取的。我们看循环求解斐波那契额数列。
#include <stdio.h>int Fib(int n)
{int a = 1;int b = 1;int c = 1;while (n >= 3){c = a + b;a = b;b = c;n--;}return c;
}int main()
{int n = 0;scanf("%d", &n);int ret = Fib(n);printf("%d\n", ret);return 0;
}
循环求解斐波那契数列就是,1 1 2 3 5 8.....、a代表Fib(n-2)、b代表Fib(n-1),每次循环都把Fib(n-2)和Fib(n-1)的和赋给cFib(n),然后整体将a、b整体向右移。当n=3时,这个循环操作一次,n=4时,循环操作两次,也就是两次将a、b的和赋值给c,符合要求斐波那契额数列的求法。
这个算法可以很快的算出n = 50时的斐波那契数列值。这时我们会选择用循环解决这个问题。
总结:什么时候使用递归呢?如果递归的实现比较简单,而且不需要耗费太多时间,我们就可以选择递归。即使递归写起来比较方便,但耗时太久了,我们反而会选择,代码篇幅较长的循环来解决。
文已至此,函数的内容就讲完啦~,感谢观看,咱们下篇见。
结语:希望读者读完有所收获!在学C的路上,祝福我们能越来越C!✔
读者对本文不理解的地方,或是发现文章在内容上有误等,请在下方评论区留言告诉博主哟~,也可以对博主提出一些文章改进的建议,感激不尽!最后的最后!
❤求点赞,求关注,你的点赞是我更新的动力,一起努力进步吧。
相关文章:
庖丁解牛函数知识---C语言《2》
目录 前言: 1.嵌套调用函数 2.链式访问 3.函数的声明与定义 4.*递归 5.递归与非递归 ❤博主CSDN:啊苏要学习 ▶专栏分类:C语言◀ C语言的学习,是为我们今后学习其它语言打好基础,C生万物! 开始我们的C语言之旅吧…...
Git 使用教程:最详细、最正宗手把手教学(万字长文)
目录 一:Git二:SVN与Git的的区别三、安装Git四:常规操作五:远程仓库六:创建与合并分支七:bug分支八:多人协作九:git可视化工具 Git Git 是一种分布式版本控制系统,用于…...
【华为OD机试 2023最新 】最优资源分配/芯片资源占用(C语言题解 100%)
文章目录 题目描述输入描述输出描述备注用例题目解析代码思路C语言题目描述 某块业务芯片最小容量单位为1.25G,总容量为M*1.25G,对该芯片资源编号为1,2,…,M。该芯片支持3种不同的配置,分别为A、B、C。 配置A:占用容量为 1.25 * 1 = 1.25G配置B:占用容量为 1.25 * 2 =…...
markdown二元运算符
符号markdown名称 \pm \pm正负/加减 ∓ \mp ∓\mp负正/减加 \times \times乘号 ⋅ \cdot ⋅\cdot点乘号 \div \div除号 ∣ \mid ∣\mid整除 ∤ \nmid ∤\nmid不整除 ⊕ \oplus ⊕\oplus异或...
【华为/华三】PPP
NCP network阶段 用于协商网络层参数,IPCP静态协商IP地址(即互推地址)动态协商叫做获得地址 Q:为什么PPP两端,可以不在一个网段内,也能够通信? A:因为PPP中的NCP会通过IPCP协商IP…...
【Java笔试强训 9】
🎉🎉🎉点进来你就是我的人了博主主页:🙈🙈🙈戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔🤺🤺🤺 目录 一、选择题 二、编程题 🔥另类加法…...
【C++】STL标准库之list
STL标准库之list list类的简介常用的list类的接口构造迭代器容量访问修改 list和vector的区别 list类的简介 list是一种序列式容器,可以在任意位置插入和删除元素,并且其时间复杂度为O(1),在底层,list是双向链表结构,…...
Nomogram | 盘点一下绘制列线图的几个R包!~(二)
1写在前面 不知道各位小伙伴的五一假期过的在怎么样,可怜的我感冒了。😷 今天继续之前没有写完的列线图教程吧,再介绍几个制作列线图的R包。🤠 2用到的包 rm(list ls())library(tidyverse)library(survival)library(rms)library(…...
Django之定时任务django-crontab
Django之定时任务django-crontab crontab安装django-crontab注册应用定时时间格式定时时间示例设置定时任务符号方法解决crontab中文问题管理定时任务注意 crontab Django可以使用第三方库如django-crontab来实现定时任务的调度。该库允许使用类似于crontab文件格式的语法指定任…...
linux常见命令
ls:列出当前目录下的所有文件和子目录 cd:切换当前工作目录,例如 cd /home/user 进入 /home/user 目录 pwd:显示当前工作目录的路径 mkdir:创建一个新目录,例如 mkdir newdir 创建一个名为 newdir 的目录…...
【14.HTML-移动端适配】
移动端适配 1 布局视口和视觉视口1.1 设置移动端布局视口宽度 2 移动端适配方案2.1 rem单位动态html的font-size;2.2 vw单位2.3 rem和vw对比2.4 flex的弹性布局 1 布局视口和视觉视口 1.1 设置移动端布局视口宽度 避免布局视口宽度默认980px带了的缩放问题,并且禁止…...
平衡二叉树旋转机制
概念 平衡二叉树的旋转机制是一种通过对树进行旋转操作来保持其平衡的方法。 分类 平衡二叉树的旋转机制包括两种基本类型的旋转:左旋和右旋,以及它们的组合。 左旋 左旋是将一个节点的右子节点旋转到它的位置上,同时将该节点移到其左侧&…...
深入浅出C++ ——C++11
文章目录 一、C11简介二、列表初始化二、声明四、范围for循环五、STL中的变化六、右值引用和移动语义1. 什么是左值?什么是左值引用?2. 左值引用与右值引用比较3. 右值引用使用场景和意义4. 完美转发 新的类功能默认成员函数类成员变量初始化defaultdele…...
智能座舱3.0阶段,看全球巨头如何打造更具“价值”的第三空间
面向中国这一全球最大的汽车电动化与智能化单一市场,作为全球第七大汽车技术供应商的FORVIA佛瑞亚集团开始全面发力。 在2023年上海国际车展上,FORVIA佛瑞亚携旗下佛吉亚与海拉一系列突破性技术和互动体验亮相,展示了对电气化与能源管理、安…...
【Linux】入门介绍
🌱博客主页:大寄一场. 🌱系列专栏:Linux 😘博客制作不易欢迎各位👍点赞⭐收藏➕关注 目录 前言 Linux背景介绍 1.发展史 UNIX发展的历史 Linux发展历史 2. 开源 3. 官网 4. 企业应用现状 5. 发行版…...
【Python】序列类型②-元组
文章目录 1.元组简介2.元组的定义2.1定义只有一个元素的元组 3.元组的下标访问4.元组的常用方法5.使用in判断是否存在元素6.多元赋值操作 1.元组简介 元组和列表一样可以存放多个,不同数据类型的元素 与列表最大的不同就是:列表是可变的,而元组不可变 2.元组的定义 元组的定义:…...
循环的数字
循环的数字 题目描述 你曾经因为看见一样的东西一遍又一遍地重复、循环而对电视节目感到厌烦么?好吧,虽然我并不关心电视节目的好坏,不过有时却也很像那样不断循环的数字。 让我们假定两个不同的正整数 ( n , m ) (n, m) (n,m) 是循环的&…...
MySQL查询之聚合函数查询
0. 数据源 student.sql文件。 /*Navicat Premium Data TransferSource Server : localhost_3306Source Server Type : MySQLSource Server Version : 80016Source Host : localhost:3306Source Schema : testdbTarget Server Type : MySQLTa…...
普通2本,去过字节外包,到现在年薪25W+的测试开发,我的2年转行心酸经历...
个人简介 我是一个普通二本大学机械专业毕业,17年毕业,19年转行,目前做IT行业的软件测试已经有3年多,职位是高级测试工程师,坐标上海… 我想现在我也有一点资格谈论关于转行这个话题;希望你在决定转行之前…...
util.callbackify
util.callbackify(original) 将 async 异步函数(或者一个返回值为 Promise 的函数)转换成遵循异常优先的回调风格的函数,例如将 (err, value) > ... 回调作为最后一个参数。 在回调函数中,第一个参数为拒绝的原因(如…...
解决使用CLIP模型时TypeError: Cannot handle this data type: (1, 1, 224, 224), |u1
想提供Huggingface的transformer库实现多模态模型CLIP的推断,结果报错 (myenv) rootd27d1ff1836c:/home/model_test# python3 CLIP.py ftfy or spacy is not installed using BERT BasicTokenizer instead of ftfy. Traceback (most recent call last): File “/hom…...
Mysql第二章 多表查询的操作
这里写自定义目录标题 一 外连接与内连接的概念sql99语法实现 默认是内连接sql99语法实现左外连接,把没有部门的员工也查出来sql99语法实现右外连接,把没有人的部门查出来sql99语法实现满外连接,mysql不支持这样写mysql中如果要实现满外连接的…...
ESP32-CAM:TinyML 图像分类——水果与蔬菜
目录 故事 硬件参数: 在 Arduino IDE 上安装 ESP32-Cam 使用 BLINK 测试电路板 测试无线网络 运行您的 Web 服务器 水果与蔬菜-图像分类 下载数据集 使用 Edge Impulse Studio 训练模型...
如何防止订单重复支付
想必大家对在线支付都不陌生,今天和大家聊聊如何防止订单重复支付。 看看订单支付流程 我们来看看,电商订单支付的简要流程: 订单钱包支付流程 从下单/计算开始: 下单/结算:这一步虽然不是直接的支付起点,但…...
不是那么快乐的五一
大家好,我是记得诚。 五一假期结束了,明天开始上班了。 这个假期没休息好,也没出去玩。 放假前一天,接到通知让加班。 第一天就去公司加班了,属实很难受,我心想如果别人有了出远门的安排,还…...
Maven命令和配置详解
Maven命令和配置详解 1. pom基本结构2. build基本结构3. Maven命令详解3.1 打包命令3.2 常用命令3.3 批量修改版本-父子pom4. Maven配置详解4.1 settings.xml4.2 项目内的maven工程结构Maven POM构建生命周期工程实践1. pom基本结构 <?xml versi...
P3029 [USACO11NOV]Cow Lineup S 双指针 单调队列
“五一”小长假来了趟上海,在倒数第二天终于有时间做了一会儿题目,A了之后过来写一篇题解 【问题描述】 农民约翰雇一个专业摄影师给他的部分牛拍照。由于约翰的牛有好多品种,他喜欢他的照片包含每个品种的至少一头牛。 约翰的牛都站在一条沿…...
数据结构与算法之链表: Leetcode 83. 删除排序链表中的重复元素 (Typescript版)
删除排序链表中的重复元素 https://leetcode.cn/problems/remove-duplicates-from-sorted-list/ 描述 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 示例 1 输入:head [1,1,2] 输出&…...
ubuntu16.04升级到20.04后报错 By not providing “FindEigen.cmake“
编译问题: CMake Error at modules/perception/lidar/CMakeLists.txt:14 (find_package): By not providing "FindEigen.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by "Eigen&…...
设计模式——模板方法模式
是什么? 在我们的实际开发中尝尝会遇到这种问题:在设计一个系统时知道了算法所需要的关键步骤,而且确定了这些步骤的执行顺序,但是某些步骤的具体实现还不知道,或者说某些步骤的实现与具体的环境相关,例如每…...
美国纽约网站建设费用/今日头条新闻视频
实现Servlet的三种方式:一个实现,两个继承 /* * servlet的执行过程: * 1.创建servlet对象(Tomcat执行) * 2.第一次访问servlet时执行 * init()方法 该方法只执行一次 * service()方法 * 3.之后每访问一次 就执行一次se…...
做网站网页版和手机版/百度免费建网站
题面描述了一种加密的方式,让coder按照要求解密~ 将字母分成三段,再将位置用数组储存~所谓的旋转其实就是右移~ #include"cstdio" #include"iostream" #include"cstring" using namespace std; int main() { int k1,k2,…...
西宁电子商务网站建设/免费seo培训
这是松哥之前一个零散的笔记,整理出来分享给大伙! MySQL 读写分离在互联网项目中应该算是一个非常常见的需求了。受困于 Linux 和 MySQL 版本问题,很多人经常会搭建失败,今天松哥就给大伙举一个成功的例子,后面有时间再…...
自己做的网站很卡/网络营销的特点包括
原文链接:http://blog.csdn.net/maozefa/archive/2008/09/08/2896752.aspx无论是用何种语言,只要使用过Windows的GDI的人对ColorMatrix都不陌生,我的BLOG文章中也多次提到过,并在《GDI for VCL基础 -- 颜色调整矩阵ColorMatrix详解…...
上海网站备案核验/怎样做自己的网站
烤瓷牙修复牙齿的种类都有哪些?烤瓷牙它的种类有很多,这往往就令消费者眼花撩换,他们不知该如何选择。接下来我们就看看烤瓷牙种类的介绍吧希望以下的介绍对大家有所帮助。 烤瓷牙修复牙齿的种类都有哪些呢?烤瓷牙修复牙齿的种类如下所示:…...
新闻网站哪个做的好/学网络与新媒体后悔死了
vim编辑模式下 没有ctrla 的 全选方式 然后del 切换到 命令模式 :%d 既可...