函数与递归

news2024/11/28 12:32:59

函数与递归

  • 函数定义与分类
  • 库函数
    • 库函数的定义与种类
    • 二级
    • 查询库函数性质工具的使用
    • c语言中常用的库函数总结
  • 自定义函数
  • 函数的参数
    • 实参定义
    • 形参定义
  • 函数调用
    • 传值调用
    • 图解分析
    • 传址调用
    • 图解分析
    • 编程题
    • 判断一个数是不是素数
    • 判断一年是不是闰年
    • 实现一个整形有序数组的二分查找。
  • 函数嵌套调用和链式访问
    • 嵌套调用
    • 嵌套定义
    • 链式访问
    • 链式访问经典题目
  • 函数的声明和定义
    • 函数的声明
    • 函数的定义
    • 函数声明和定义的实际应用
  • 函数递归
    • 递归定义
    • 递归的两个必要条件
    • 递归与迭代
    • 迭代定义
    • 递归与迭代编程题以及详细图解
    • 打印一个整形值(无符号)的每一位(递归实现)
    • 求字符串长度(递归实现)

铁汁们~今天给大家分享一篇函数与递归的详解,来吧,开造⛳️

函数定义与分类

函数的定义:

1.函数,又被其他地区成为子程序,是一个大型工程项目的部分代码,由一个或多个语句块【】组成,负责完成某项 特定的任务,相对于其他代码,具有相对的 独立性

2.C语言中把常用的功能进行了封装,封装成一个个函数,提供出来大家都可以进行使用—>库函数:如输入输出型库函数scanf、printf,字符串拷贝函数strcpy,字符串求长度函数strlen等。

3.c语言并不是直接去实现库函数的,而是提供了c语言标准以及库函数约定,c语言标准为:函数功能、函数参数、返回值类型、函数名,库函数的实现一般是由编译器去实现的,实现库函数要遵循c语言标准以及库函数约定,相当于连锁商店。

注意:使用库函数之前一定要引用其相对应的头文件,否则编译器识别不出来,编译器会报错。

库函数

库函数的定义与种类

1.库函数的定义:大家都要频繁去使用的功能性函数。

2.库函数的种类:
a.输入输出库函数(引用的头文件为#include<stdio.h>):prinf(打印)、scanf(输入)。
在这里插入图片描述

b.字符串库函数(引用的头文件为#include<string.h>):字符串的拷贝strcpy库函数、字符串求长度strlen库函数、字符串比较strcmp库函数。
在这里插入图片描述

c.数学库函数(引用的头文件为#include<math.h>):求n的k次方pow库函数、求n开根号sqrt库函数等。
在这里插入图片描述

二级

查询库函数性质工具的使用

工具1:MSDN
使用步骤:输入要查询的函数—>索引
在这里插入图片描述
2www.cplusplus.com网站

第一步:
在这里插入图片描述
第二步:
在这里插入图片描述
第三步:
在这里插入图片描述

c语言中常用的库函数总结

IO函数:输入输出函数:<stdio.h>,printf、scanf、putchar。

字符串操作函数:<string.h>,strlen、strcpy、strcmp等。

内存操作函数:<string.h>,memset、memcmp等。

时间或日期操作函数:<time.h>,time等。

数学函数:<math.h>,sqrt、pow等。

其他库函数:产生随机数函数:rand、srand、time; islower、isupper、tolower、toupper、isalpha等<ctype.h>。

自定义函数

自定义函数与库函数相同:有函数名、函数参数、返回值类型。
函数的组成:
在这里插入图片描述
在这里插入图片描述

自定义一个函数找出两个整数的最大值

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int SearchMax(int a, int b)
{
	return a > b ? a : b;
}
int main()
{
	int a = 0;
	int b = 0;
	int max = 0;
	scanf("%d %d", &a, &b);
	max=SearchMax(a, b);
	printf("最大值为=%d", max);
	return;
}

在这里插入图片描述

函数的参数

实参定义

实际参数:又称实参,是指函数调用时函数名后面的括号,实参的种类可以是常量、变量、表达式、函数等,无论参数为何种类型,在函数的调用时,实参必须为确定的值,,以便于将该值很好的传递给形参。

形参定义

形式参数:又称为形参,是函数调用操作符里面的内容,形式参数只有在函数被调用时才被实例化(分配内存单元),在栈上开辟空间,当函数调用完后就自动销毁了,形式参数只在函数体中有效。

函数调用

写一个函数可以交换两个整形变量的内容

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void swap1(int a, int b)  //传值调用
{                         //a、b为形参
	int tmp = a;
	a = b;
	b = tmp;
}
void swap2(int* a, int* b)//传址调用
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("交换前a=%d,b=%d", a, b);
	swap1(a, b);                       //a、b为实参
	printf("swap1交换后a=%d,b=%d", a, b);
	swap2(&a, &b);
	printf("swap2交换后a=%d,b=%d", a, b);
	return 0;
}

在这里插入图片描述

传值调用

定义:函数的形参和实参分别占有不同的内存块,对形参的改变不会影响实参的改变,形参只是实参的一份临时拷贝

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void swap1(int a1,int b1)//传值调用
{                         //a、b为形参
	int tmp = a1;
	a1 = b1;
	b1= tmp;
}
int main()

{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("交换前a=%d,b=%d\n",a,b);
	swap1(a, b);                       //a、b为实参
	printf("swap1交换后a=%d,b=%d\n", a, b);
	return 0;
}

在这里插入图片描述

tips:运行错误:该代码可以通过编译器编译通过,无语法错误,但不能达到我们预期的效果。

未交换的原因:

形参只是实参的一份临时拷贝,形参的改变不会影响实参的改变 ,因为形参所占空间的地址与实参所占空间的地址不同,属于两个不同的独立空间,实参只是把值传递给了形参,形参的变化不会影响实参的变化,两者之间未建立联系

图解分析

在这里插入图片描述

传址调用

定义:把在函数外部创建的变量地址传递给函数的形参的一种调用函数的方式。

意义:可以将函数形参与函数外部变量实参建立起真正的联系,函数的内部可以直接操作函数外部的变量,即:通过指针就可以访问外部变量,对其直接进行操作,形参的改变会引起实参的变化。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void swap2(int* a1, int* b1)//传址调用
{
	int tmp = *a1;
	*a1 = *b1;
	*b1 = tmp;
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("交换前a=%d,b=%d", a, b);
    swap2(&a, &b);
	printf("swap2交换后a=%d,b=%d", a, b);
	return 0;
}

交换的原因:

因为指针变量可以与它所指向的变量建立起联系,指针变量可以修改它指向对象的值,a1中存放着a中的地址,可以通过存放的地址找到a,b1中存放者b中的地址,可以通过存放的地址找到b,a1与b1的交换实际上是函数体外a与b的交换,形参的改变会引起实参的改变。
在这里插入图片描述

图解分析

在这里插入图片描述

编程题

判断一个数是不是素数

思路:素数为只能被1和自己本身整除的数,不能被2到本身-1之间的数整除,素数不能被2到sqrt(n)之间的数整除。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int issushu(int n)
{
	int i = 0;
	for (i = 2; i <= sqrt(n); i++)
	{
		if (n % i == 0)
			return 0;
	}
	return 1;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret=issushu(n);
	if (ret == 1)
	{
		printf("%d是素数\n", n);
	}
	else
	{
		printf("%d不是素数\n", n);
	}
}

在这里插入图片描述

判断一年是不是闰年

思路:闰年能被4整除但不能被100整除或者闰年能被400整除。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int runyear(int year)
{
	return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int main()
{
	int year = 0;
	scanf("%d", &year);
	int ret=runyear(year);
	if (ret == 1)
	{
		printf("%d是闰年\n", year);
	}
	else
	{
		printf("%d不是闰年\n", year);
	}
}

在这里插入图片描述

实现一个整形有序数组的二分查找。

思路及代码实现在博主的另一篇博文有详解,请点击链接二分查找编程题

函数嵌套调用和链式访问

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

嵌套调用

定义:一个函数里面调用了一个或多个函数,该函数可以是该函数本身,也可以是其他函数。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void print()
{
    printf("happy\n");
}
void test()  //函数定义
{
	print();  //函数嵌套调用
}
int main()
{
	test();  //函数调用
	return 0;
}

在这里插入图片描述

注意:函数可以嵌套调用,但不可以嵌套定义

嵌套定义

概念:一个函数定义中嵌套了另一函数定义,编译器不允许此操作。

#define _CRT_SECURE_NO_WARNINGS 1  //错误代码
#include<stdio.h>
void test()
{
	void print()
	{
		printf("happy\n");
	}
}
int main()
{
	test();
	return 0;
}

在这里插入图片描述

链式访问

定义:把一个函数的返回值作为另外一个函数的参数。

链式访问经典题目

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

在这里插入图片描述

解释:printf函数的返回值为在屏幕上打印的字符总个数,包括空格
先执行该函数本身的功能,在将该函数的返回值作为另一个函数的参数,从后往前看,第一个printf在屏幕上打印出 43空格,返回值为3,第二个printf在屏幕上打印 3空格,返回值为2,第三个printf在屏幕上打印2。

函数的声明和定义

函数的声明

函数声明的作用:

1.先提前告诉编译器该函数的相关信息,如:函数名、函数参数、函数返回值类型,参数名可省略,eg:int add(int,int)。但是在代码中该函数存不存在,函数的声明决定不了。
2.函数声明一般放在函数定义之前。必须要满足先声明后定义。、
3.函数的声明一般放在头文件中。

函数定义如果放在函数调用前面,则函数的定义是一种特殊的函数声明,可省略函数的声明。

函数定义如果放在函数调用后面,则必须要满足先声明后定义。

函数的定义

函数的定义:是指函数的具体实现,交代函数功能的实现。

函数声明和定义的实际应用

eg1:当程序员进入企业时,完成一个大工程,需要多个程序员分模块编写代码,方便协作,最后做整合。
在这里插入图片描述
eg2:程序员在业余时间写了一个库,完成减法操作,需要卖出去,赚钱,但不希望别人看到自己的源代码实现(函数的实现),需要把sub.c——>sub.lib

具体操作:项目名—>右击“属性”—>点击“配置类型”—>点击“应用程序”—>点击“静态库(.lib)"

.lib为静态库,导入静态库,别人打开后里面的内容看不懂。

函数递归

递归分为递推和回归

由函数的调用堆栈以及函数栈帧的创建与销毁可知,每一次函数调用都要只在栈区上开辟一块空间用来保存函数在调用过程中的上下文信息。

每一次回归时,函数调用时被分配的空间都要被释放,还给操作系统,每一次递推时,都需要在栈上开辟内存空间

递归定义

递归定义:

程序自己调用自己,一个过程或者函数在其定义或者说明中有直接或间接调用自身,把一个大型问题层层转化为与原问题相似但规模较小的问题进行求解,只需要少量的程序就可以描述出题解过程中所需要的多次重复计算,大大减少了代码量。

递归思考方式精髓:把大事化小,化小从简单思路入手

递归的两个必要条件

1.存在限制条件 ,当满足这个限制条件时,递归便不再继续;
2.每次递归调用都会无限接近这个限制条件
若两个必要条件缺一,会导致死递归,出现栈溢出现象。

递归与迭代

迭代定义

迭代定义:又称为循环

在完成同一个功能实现时,有递归与迭代两者方法实现,此时需要考虑使用递归时是否存在递归的两个必要条件、是否会出现栈溢出现象,若出现栈溢出,则用迭代实现,减少空间的使用,从而大大提高效率。

栈溢出现象:系统分配给程序的栈空间是有限制的,如果出现了死循环或者死递归,就会导致一直开辟栈空间,一直在使用栈空间,最终使栈空间耗尽。

解决栈溢出问题的方法:

1.将递归改写成非递归,比如:使用迭代的方法实现;

2.使用静态变量对象代替非静态变量对象(原因:既可以减少每次递归调用在栈上开辟的空间、返回时产生和释放栈对象的开哨,并且静态对象还可以保存递归调用的中间状态,并且可为各个调用层所访问。

递归与迭代编程题以及详细图解

打印一个整形值(无符号)的每一位(递归实现)

思路:因为我们可以很容易获得一个数的每一位,只需要%10、/10相互循环,直到该数为0停止,先打印123,在打印4(为先后关系 ,不是选择关系)。
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void print(int n)
{
	if (n > 9)
	{
		print(n / 10);
	}
	printf("%d ", n % 10);
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	print(n);
	return 0;
}

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

求字符串长度(递归实现)

思路:因为我们很容易拿到第一个字符,判断第一个字符是否为’\0’,若不为‘\0’,则个数至少为1,再继续判断后面的字符(为选择关系,不是先后关系)。
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int mystrlen(char* s)
{
	if (*s != 0)
	{
		return mystrlen(s + 1)+1;
	}
	else
	return 0;
}
int main()
{
	char arr[] = "abcde";
	int ret = mystrlen(arr);
	printf("%d\n", ret);
	return 0;
}

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

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

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

相关文章

四元数与旋转矩阵之间的转换

在https://blog.csdn.net/fengbingchun/article/details/130039337 中介绍了相机外参及相机的位姿R,t&#xff0c;其中R为3*3旋转矩阵(R的逆矩阵与R的转置矩阵相同)&#xff0c;t为3*1平移向量&#xff0c;R,t组合成3*4的矩阵。 在instant-ngp中执行scripts/colmap2nerf.…

DHT11温湿度传感器

1.认识DHT11 1、概述&#xff1a; DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器&#xff0c;应用领域&#xff1a;暖通空调&#xff1b;汽车&#xff1b;消费品&#xff1b;气象站&#xff1b;湿度调节器&#xff1b;除湿器&#xff1b;家电&#x…

通过cloudflare创建openai api的代理

一、前言 首先你要有一个域名&#xff0c;其次这个域名要托管到cloudfare&#xff0c;所以&#xff1a; 直接在cloudfare购买域名&#xff0c;方便省事!找其他免费域名&#xff0c;再托管到cloudfare&#xff0c;本着一分钱不花的目的&#xff0c;这里提供一个顶级免费公益域…

005 - STM32启动代码

常用汇编指令 指令名称作用EQU给数字常量取一个符号名&#xff0c;相当于C语言中的#define&#xff1b;AREA汇编一个新的代码段或者数据段&#xff1b;SPACE分配内存空间&#xff1b;PRESERVE8当前文件栈需要按照8字节对齐&#xff1b;EXPORT声明一个具有全局属性的标号&#…

聚观早报 | 小冰启动GPT克隆人计划;ofo创始人在美创业改做咖啡

今日要闻&#xff1a;小冰启动“GPT克隆人计划”&#xff1b;ofo创始人在美创业改做咖啡&#xff1b;OpenAI正准备新的开源AI模型&#xff1b;青年失业率首破20&#xff05;创新高&#xff1b;微软收购动视暴雪获批 小冰启动“GPT克隆人计划” 5 月 16 日&#xff0c;小冰公司…

Spring Boot + Mybtis-plus集成

目录 需求分析Maven 相关依赖配置文件相关流程MybatisPlus配置自动补全参数配置逻辑删除注解乐观锁注解 需求分析 Spring Boot和MyBatis-Plus是目前使用最广泛的Java web开发框架和ORM框架&#xff0c;它们可以很好地协同工作&#xff0c;提供高效和稳定的系统开发和数据操作。…

[答疑]UML精粹里和你视频里说的不太一样

DDD领域驱动设计批评文集>> 《软件方法》强化自测题集>> 《软件方法》各章合集>> 第五元素 2023-4-14 20:32 这是是UML精粹里的。潘老师&#xff0c;这个跟你视频里讲的是不是不太一样&#xff1f;还是我理解错了&#xff1f; UMLChina潘加宇 这个&#…

软件最后一步------打包

本文章主要是记将源代码打包成程序 Python 一、安装Pyinstaller (用于打包的库) pip install pyinstaller二、使用参数 参数介绍 选项参数参数解释-hhelp(帮助信息)-vversion(版本号)-c显示命令行窗口-w不显示命令行窗口-F生成结果是一个exe程序&#xff0c;所有依赖项被打…

计算机的基本工作原理

参考资料&#xff1a; L-1.6: Common Bus system| How basic computer works - YouTube 准备好内存单元、不同类型的寄存器&#xff0c;内存和寄存器、寄存器和寄存器之间都是通过总线连接(假设是直接把数据总线、控制总线、地址总线变成一条总线)。 使用多路复用器实现的总线&…

C语言—通讯录

通讯录 通讯录的创建通讯录的初始化通讯录添加联系人信息通讯录删除特定联系人信息通讯录查找特定联系人信息通讯录修改特定联系人信息通讯录排序联系人信息通讯录打印联系人信息通讯录整体代码 通讯录的创建 通讯录中是存放人的信息的&#xff0c;人的信息包括&#xff1a;姓…

数据结构—排序算法交换排序(冒泡快排)

目录 1.交换排序—冒泡排序 1.1冒泡排序基本思想 1.2冒泡排序的实现 2.交换排序—快速排序 1.1快速排序基本思想 1.2基准值划分—分析 1. hoare版&#xff1a; 2. 挖坑法&#xff1a; 3. 前后指针版本 1.3 hoare快排的具体实现 1.4 挖坑法快排的具体实现 1.5 前后指…

【Stable Diffusion WebUI】一篇文章教你如何安装和使用Stable Diffusion WebUI

文章目录 Stable Diffusion WebUI1. 安装1.1 下载 stable-diffusion-webui1.2 运行 webui.sh 2. 安装插件2.1 命令行安装2.2 extensions 安装2.3 常用插件 3. 使用教程3.1 页面布局3.3 快捷栏设置3.3.1 PNG Info3.3.2 Tagger Stable Diffusion WebUI 1. 安装 1.1 下载 stable…

Python中的集合介绍

集合set是一个无序的、不可重复的元素集合。 集合的创建 大括号 {} set() a {1, 2, 3, 4, 5} print(type(a))b set([1,2,3,4,5,6,7]) print(type(b),b)c set((1,2,3)) print(c) 运行结果&#xff1a;<class set> <class set> {1, 2, 3, 4, 5, 6, 7} {1, 2, 3} 集…

诺贝尔化学奖:酶分子“定向进化”

2018年&#xff0c;诺贝尔化学奖迎来了历史上第五位女性得主——加州理工学院的Frances H. Arnold教授&#xff0c;以表彰她在“酶的定向进化”这一领域的贡献。 1、“酶的定向进化”到底是什么&#xff1f; 这里有三个点&#xff0c;“酶”、“进化”还有“定向”&#xff1a…

windows10安装Qt

一、下载安装包 1、安装包下载路径调整 由于Qt公司的调整&#xff0c;从5.15版本开始原本下载的路径不再提供安装包 Index of /archive/qt 新安装包放在了official_releases里面了 Index of /official_releases/online_installers 2、安装方式调整 从5.9.0开始安装方式开始…

streamlit应用部署和streamcloud发布APP

文章目录 streamlit应用创建streamcloud创建APP注册streamcloud账号设置StreamLit许可发布APPstreamlit应用创建 streamcloud创建APP StreamCloud是一个用于部署StreamLit App 的平台。 注册streamcloud账号 点击https://share.streamlit.io/ ,进入StreamCloud 注册界面。…

在四维轻云平台中如何使用场景搭建功能?

四维轻云是一款轻量化的地理空间数据管理云平台&#xff0c;能够实现多种地理空间数据的在线管理、编辑及分享。目前&#xff0c;平台具有项目管理、成员管理、场景搭建、在线分享、素材库等功能&#xff0c;支持多用户在线协作管理&#xff0c;实现了轻量化、便捷化的空间数据…

chatgpt赋能Python-pythonda

Python在SEO优化中的作用 简介 SEO&#xff08;Search Engine Optimization&#xff09;即搜索引擎优化&#xff0c;是指通过优化网站目标关键词的排名来提高网站的曝光率和流量。Python是一种高级编程语言&#xff0c;在SEO领域中有着广泛的应用。 Python在SEO中的应用 网…

AudioGPT推出!音频领域都不放过,ChatGPT这是杀疯了!

大家好&#xff0c;我是千与千寻&#xff0c;你们可以叫我千寻哥&#xff0c;算一算写ChatGPT的技术文章已经写到第四篇了&#xff01; 今天和大家介绍的一个项目属于音频领域的ChatGPT的应用实践。真没想不到&#xff0c;在音频领域&#xff0c;ChatGPT都没有放过&#xff0c…

maven聚合工程详解

目录 一、Maven继承二、idea搭建父子工程三、可继承的 POM 元素四、Maven聚合五、idea搭建聚合工程六、继承和聚合的关系七、dependencyManagement八、pluginManagement 本篇文章重点针对这几个问题进行讲解&#xff1a; Maven继承使用IDEA搭建Maven父子工程使用IDEA搭建Maven…