C语言---函数
1、函数是什么
学习库函数网站:
- https://cplusplus.com/reference/
- http://en.cppreference.com
- http://zh.cppreference.com
我们参考文档,学习几个库函数
2、库函数
3、自定义函数
自定义函数和库函数一样,有函数名,返回值类型和函数参数
函数的组成:
ret_type fun_name(para1,*)
{statement; //语句项 //函数体
}ret_type //返回值类型
fun_name //函数名
para1 //函数参数
4、函数参数
4.1、创建函数实现两个整形变量交换值
通过下面有问题的代码,讲解实参和形参:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>void Swap(int x,int y)
{int z = 0;z = x;x = y;y = z;
}int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);printf("原数字:a=%d,b=%d\n", a, b);Swap(a,b);printf("原数字:a=%d,b=%d", a, b);return 0;
}
输出:
我们会发现,变量a、b的值并没有交换!!!
那问题出现在哪里呢?
经过调试后发现Swap()函数里面的x,y值没有转给a,b,所以a,b一直都是10,20。
原因总结:变量a,b叫做实参。变量x,y叫做形参。当实参传递给形参的时候,形参是实参的临时拷贝。对形参的修改不会影响到实参。
那知道了问题后,怎么解决呢?
利用我们前面学到的指针变量的方法:
int main()
{int a = 0;int* p = &a;a = 20; //直接修改a的值*p = 30; //间接修改a的值return 0;
}
也就是说我们可以利用a,b的地址,然后赋值进行修改,从而达到交换值得目的
代码实现:(好好体会)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>void Swap(int* px,int* py)
{int z = *px; //z = a*px = *py; //a = b*py = z; //b = a
}int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);printf("原数字:a=%d,b=%d\n", a, b);Swap(&a,&b);printf("原数字:a=%d,b=%d", a, b);return 0;
}
那下面我们再来实现一下两个函数的加法:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>Add(int x,int y)
{int z = 0;z = x + y;return z;
}int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);int c = Add(a, b);printf("%d\n", c);return 0;
}
提问:为什么实现两个变量值的交换需要传指针参数,而实现两个值相加不需要传指针参数呢?
那我们什么时候需要传指针参数,什么时候不需要呢?
- 当我们需要改变变量a,b的值时就需要使用指针变量
- 否则不需要
4.2、实际参数(实参)
真是传给函数的参数,叫实参。
实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的的量,在进行函数调用时,它们都必须有确定的值,一边把这些值传给形参。
4.3、形式参数(形参)
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成后就自动销毁了,因此形式参数只在函数中有效。
并且形参实例化后相当于实参的临时拷贝。
实参和形参的参数名可以相同也可以不相同。
5、函数调用
5.1、传值调用
函数的形参和实参分别占有不同的内存块,对形参的修改不会影响实参。
5.2、传址调用
- 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
- 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
Swap1(a,b) //传值调用Swap(&a,&b) //传址调用
6、函数的嵌套调用和链式访问
函数和函数之间可以根据实际的需求进行组合,也就是互相调用。
6.1、链式访问
把一个函数的返回值作为另一个函数的参数。特别注意:是一个函数的返回值作为另一个函数的参数
所以链式访问的前提是函数必须要有返回值。
那我们来看下面的代码:
#include <stdio.h>
int main()
{printf("%d", printf("%d", printf("%d", 43)));return 0;
}
输出:
分析:首先我们要知道printf()函数的打印和返回值不是一回事,printf()函数的返回值是返回数据的个数,比如这里:打印的是43,43是两个数字,所以printf()函数的返回值是2。那好,我们从左向右依次分析,首先最里面的printf()函数打印出43,并且返回2传给中间的那个printf()函数,那后中间的那个函数打印2,因为2是一个数字,所以中间的printf()返回值1并传给最左侧的printf()函数,然后左侧的printf()函数打印1。因此输出结果为4321。
7、函数的声明和定义
7.1、函数的声明
1、告诉编译器有一个函数叫什么,参数是什么,返回类型是什么,但是具体是不是不存在,函数声明决定不了。
2、函数的声明一般出现在函数的使用之前,要满足先声明后使用。
3、函数的声明一般要放在头文件中的。
我们在写两个数相加时,Add()函数就写在main()函数上面,但是如果我们将Add()函数写在main()函数下面,程序也可以运行,就是会警告,如果想取消警告我们就需要声明:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>//函数声明
int Add(int, int); //两种写法都可以
int Add(int x, int y);int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);int ret = Add(a, b);printf("%d", ret);return 0;
}//函数的定义
int Add(int x,int y)
{return x + y;
}
但是在实际业务中,我们不会这样写,我们会怎么办呢?我们可以创建个add.c源文件和add.h头文件。然后把Add()函数部分放进add.c源文件中,把函数声明—>int Add(int, int); 放进add.h头文件中,最后在main函数所在的.c源文件中,引入add.h头文件即可。(这里add.c和add.h文件不在演示创建,只演示引入头文件):
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include "add.h"; //引入add.h头文件int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);int ret = Add(a, b);printf("%d", ret);return 0;
}
7.2、函数的定义
函数的定义是指函数的具体实现,交代函数的功能实现。
8、函数递归和迭代
迭代就是非递归
8.1、什么是递归?
程序调用自身的编程技巧称为递归(recursion)。
递归作为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。
递归策略只需要少量的程序就可以描述出问题过程所需要的多次重复计算,大大的减少了程序的代码量。
递归的主要思考方式在于:把大事化小。
8.2、递归的两个必要条件
- 存在限制条件,当满足这个限制条件的时候,递归便不在继续。
- 每次递归调用之后越来越接近这个限制条件。
8.3、做几个例题
8.3.1、接收一个整型值(无符号),按照顺序打印它的每一位。
例如:
输入:1234,输出:1 2 3 4。
分析:要想分别拿到1 2 3 4我们可以这样做:将1234 % 10 ,会得到4,然后将1234 / 10会得到123,然后将123 % 10会得到3,然后将123 / 10会得到12,将12 % 10会得到2,将1 % 10会得到1,然后1 / 10会得到0。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>void print(unsigned int n)
{if (n > 9){print(n / 10);}printf("%d ", n % 10);
}int main()
{unsigned int num = 0;scanf("%d", &num);print(num);return 0;
}
我们想一下如果不加if语句,那就会死递归的调用print()函数,最终会导致栈溢出(stack overflow)。
因为每一次函数的调用都会在栈区申请空间,反复调用就会一直申请空间,最终导致栈溢出。
8.3.2、编写函数不允许创建临时变量,求字符串的长度
我们先来写个允许创建临时变量的代码:
#include <stdio.h>my_strlen(char* str)
{ int count = 0; //这个就是创建的临时变量while (*str != '\0'){count++;str++;}return count;
}int main()
{char arr[] = "1234";int len = my_strlen(arr);printf("%d\n", len);return 0;
}
但是现在要求不能创建临时变量,所以需要使用递归的方法来实现。
#include <stdio.h>my_strlen(char* str)
{if (*str != '\0'){return 1 + my_strlen(str + 1);}else{return 0;}
}int main()
{char arr[] = "1234";int len = my_strlen(arr);printf("%d\n", len);return 0;
}
8.3.3、使用递归实现n!
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>int fac(int x)
{if (x <= 1){return 1;}else{return x * fac(x - 1);}}int main()
{int n = 0;scanf("%d", &n);int ret = fac(n);printf("%d\n", ret);return 0;
}
8.3.4、求第n个斐波那契数
斐波那契数:1 1 2 3 5 8 13 21 34 55…
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>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);int ret = Fib(n);printf("%d", ret);return 0;
}
但是这个用递归就不太适合,当n=50时,会计算很长时间。那就用迭代的方法:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>int Fib(int n)
{int a = 1;int b = 1;int c = 0;int i = 0;if (n <= 2){return 1;}else{for (i=1; i <= n - 2;i++){c = a + b;a = b;b = c;}return c;}}int main()
{int n = 0;scanf("%d", &n);int ret = Fib(n);printf("%d", ret);return 0;
}
8.4、递归的几个经典问题
- 汉诺塔问题
- 青蛙跳台阶问题
相关文章:

C语言---函数
1、函数是什么 学习库函数网站: https://cplusplus.com/reference/http://en.cppreference.comhttp://zh.cppreference.com 我们参考文档,学习几个库函数 2、库函数 3、自定义函数 自定义函数和库函数一样,有函数名,返回值类…...

【JVM】什么是双亲委派机制?
一、为什么会有这种机制? 类加载器将.class类加载到内存中时,为了避免重复加载(确保Class对象的唯一性)以及JVM的安全性,需要使用某一种方式来实现只加载一次,加载过就不能被修改或再次加载。 二、什么是双…...

Vulkan Tutorial 7 纹理贴图
目录 23 图像 图片库 暂存缓冲区 纹理图像 布局转换 将缓冲区复制到图像上 准备纹理图像 传输屏障掩码 清除 24 图像视图和采样器 纹理图像视图 采样器 Anisotropy 设备特征 25 组合图像采样器 更新描述符 纹理坐标系 着色器 23 图像 添加纹理将涉及以下步骤&am…...
LinkedBlockingQueue阻塞队列
➢ LinkedBlockingQueue阻塞队列 LinkedBlockingQueue类图 LinkedBlockingQueue 中也有两个 Node 分别用来存放首尾节点,并且里面有个初始值为 0 的原子变量 count 用来记录队列元素个数,另外里面有两个ReentrantLock的独占锁,分别用来控制…...
面试-Redis 常见问题,后续面试遇到新的在补充
面试-Redis 1.谈谈Redis 缓存穿透,击穿,雪崩及如何避免 缓存穿透:是指大量访问请求在访问一个不存在的key,由于key 不存在,就会去查询数据库,数据库中也不存在该数据,无法将数据存储到redis 中…...

2023年上半年数据库系统工程师上午真题及答案解析
1.计算机中, 系统总线用于( )连接。 A.接口和外设 B.运算器、控制器和寄存器 C.主存及外设部件 D.DMA控制器和中断控制器 2.在由高速缓存、主存和硬盘构成的三级存储体系中,CPU执行指令时需要读取数据,那么DMA控制器和中断CPU发出的数据地…...
设计模式概念
设计模式是软件工程领域中常用的解决问题的经验总结和最佳实践。它们提供了一套被广泛接受的解决方案,用于处理常见的设计问题,并促进可重用、可扩展和易于维护的代码。 设计模式的主要目标是提高软件的可重用性、可扩展性和灵活性,同时降低…...
arcpy批量对EXCE经纬度L进行投点,设置为wgs84坐标系,并利用该点计算每个区域内的核密度
以下是在 ArcPy 中批量对 Excel 经纬度 L 进行投点,设置为 WGS84 坐标系,并利用该点计算每个区域内的核密度的详细步骤: 1. 准备数据: 准备包含经纬度信息的 Excel 数据表格,我们假设文件路径为 "C:/Data/locations.xlsx&qu…...

Yolov5训练自己的数据集
先看下模型pt说明 YOLOv5s:这是 YOLOv5 系列中最小的模型。“s” 代表 “small”(小)。该模型在计算资源有限的设备上表现最佳,如移动设备或边缘设备。YOLOv5s 的检测速度最快,但准确度相对较低。 YOLOv5m࿱…...

Bert+FGSM中文文本分类
我上一篇博客已经分别用BertFGSM和BertPGD实现了中文文本分类,这篇文章与我上一篇文章BertFGSM/PGD实现中文文本分类(Loss0.5L10.5L2)_Dr.sky_的博客-CSDN博客的不同之处在于主要在对抗训练函数和embedding添加扰动部分、模型定义部分、Loss函数传到部分…...
爬楼梯问题-从暴力递归到动态规划(java)
爬楼梯,每次只能爬一阶或者两阶,计算有多少种爬楼的情况 爬楼梯--题目描述暴力递归递归缓存动态规划暴力递归到动态规划专题 爬楼梯–题目描述 一个总共N 阶的楼梯(N > 0) 每次只能上一阶或者两阶。问总共有多少种爬楼方式。 示…...
浏览器如何验证SSL证书?
浏览器如何验证SSL证书?当前SSL证书应用越来越广泛,我们看见的HTTPS网站也越来越多。点击HTTPS链接签名的绿色小锁,我们可以看见SSL证书的详细信息。那么浏览器是如何验证SSL证书的呢? 浏览器如何验证SSL证书? 在浏览器的菜单中…...
Linux :: 【基础指令篇 :: 文件及目录操作:(10)】:: ll 指令 :: 查看指定目录下的文件详细信息
前言:本篇是 Linux 基本操作篇章的内容! 笔者使用的环境是基于腾讯云服务器:CentOS 7.6 64bit。 学习集: C 入门到入土!!!学习合集Linux 从命令到网络再到内核!学习合集 目录索引&am…...
Java字符集/编码集
1 字符集/编码集 基础知识 计算机中储存的信息都是用二进制数表示的;我们在屏幕上看到的英文、汉字等字符是二进制数转换之后的结果 按照某种规则, 将字符存储到计算机中,称为编码。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码。这里强调一下: 按照…...

Apache配置与应用
目录 虚拟web主机httpd服务支持的虚拟主机类型基于域名配置方法基于IP配置方法基于端口配置方法 apache连接保持构建Web虚拟目录与用户授权限制Apache日志分割 虚拟web主机 虚拟Web主机指的是在同一台服务器中运行多个Web站点,其中每一个站点实际上并不独立占用整个…...

API自动化测试【postman生成报告】
PostMan生成测试报告有两种: 1、控制台的模式 2、HTML的测试报告 使用到一个工具newman Node.js是前端的一个组件,主要可以使用它来开发异步的程序。 一、控制台的模式 1、安装node.js 双击node.js进行安装,安装成功后在控制台输入node …...
探索OpenAI插件:ChatWithGit,memecreator,boolio
引言 在当今的技术世界中,插件扮演着至关重要的角色,它们提供了一种简单有效的方式来扩展和增强现有的软件功能。在本文中,我们将探索三个OpenAI的插件:ChatWithGit,memecreator,和boolio,它们…...
linux irq
中断上下部 软中断、tasklet、工作对列 软中断优点:运行在软中断上下文,优先级比普通进程高,调度速度快。 缺点:由于处于中断上下文,所以不能睡眠。 相对于软中断/tasklet,工作对列运行在进程上下文 h…...
串口流控(CTS/RTS)使用详解
1.流控概念 在两个设备正常通信时,由于处理速度不同,就存在这样一个问题,有的快,有的慢,在某些情况下,就可能导致丢失数据的情况。 如台式机与单片机之间的通讯,接收端数据缓冲区已满࿰…...

kube-proxy模式详解
1 kube-proxy概述 kubernetes里kube-proxy支持三种模式,在v1.8之前我们使用的是iptables 以及 userspace两种模式,在kubernetes 1.8之后引入了ipvs模式,并且在v1.11中正式使用,其中iptables和ipvs都是内核态也就是基于netfilter&…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
Java多线程实现之Runnable接口深度解析
Java多线程实现之Runnable接口深度解析 一、Runnable接口概述1.1 接口定义1.2 与Thread类的关系1.3 使用Runnable接口的优势 二、Runnable接口的基本实现方式2.1 传统方式实现Runnable接口2.2 使用匿名内部类实现Runnable接口2.3 使用Lambda表达式实现Runnable接口 三、Runnabl…...

五、jmeter脚本参数化
目录 1、脚本参数化 1.1 用户定义的变量 1.1.1 添加及引用方式 1.1.2 测试得出用户定义变量的特点 1.2 用户参数 1.2.1 概念 1.2.2 位置不同效果不同 1.2.3、用户参数的勾选框 - 每次迭代更新一次 总结用户定义的变量、用户参数 1.3 csv数据文件参数化 1、脚本参数化 …...