哈尔滨无障碍网站建设/抖音seo排名优化公司
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&…...

汽车EDI:如何与Stellantis建立EDI连接?
Stellantis 是一家实力雄厚的汽车制造公司,由法国标致雪铁龙集团(PSA集团)和意大利菲亚特克莱斯勒汽车集团(FCA集团)合并而成,是世界上第四大汽车制造商,拥有包括标致、雪铁龙、菲亚特、克莱斯勒…...

【SCI征稿】1区计算机科学类SCI, 自引率低,对国人友好~
一、【期刊简介】 JCR1区计算机科学类SCI&EI 【期刊概况】IF: 7.0-8.0,JCR1区,中科院2区; 【终审周期】走期刊系统,3-5个月左右录用; 【检索情况】SCI&EI双检; 【自引率】1.30% 【征稿领域】发表人工智能…...

Vue.js优化策略与性能调优指南
导语:Vue.js是一款出色的前端框架,但在处理大规模应用或复杂场景时,性能问题可能会出现。本文将介绍一些Vue.js优化策略和性能调优指南,帮助您提升应用的性能和用户体验。 延迟加载:将应用的代码进行按需加载ÿ…...

HEVC环路后处理核心介绍
介绍 为什么需要环路后处理技术 hevc采用基于快的混合编码框架,方块效应、振铃效应、颜色偏差、图像模糊等失真效应依旧存在,为了降低此类失真影响,需要进行环路滤波技术; 采用的技术 去方块滤波DF,为了降低块效应…...

从组件化角度聊聊设计工程化
目录 设计系统 设计系统的定义 设计系统的优势 设计系统存在的问题 设计工程化 设计系统探索 设计系统落地实践 Design Token Design Token 实践 设计工程化理想方案构想 展望 参考文献 近几年围绕业务中台化的场景,涌现出了许多低代码平台。面对多组件…...

apache的配置和应用
文章目录 一、httpd服务支持的虚拟主机类型包括以下三种:二、构建Web虚拟目录与用户授权限制三、日志分割 虚拟Web主机指的是在同一台服务器中运行多个Web站点,其中每一个站点实际上并不独立占用整个服务器,因此被称为“虚拟”Web 主机。通过虚拟 Web 主…...

Buf 教程 - 使用 Protobuf 生成 Golang 代码和 Typescript 类型定义
简介 Buf 是一款更高效、开发者友好的 Protobuf API 管理工具,不仅支持代码生成,还支持插件和 Protobuf 格式化。 我们可以使用 Buf 替代原本基于 Protoc 的代码生成流程,一方面可以统一管理团队 Protoc 插件的版本、代码生成配置ÿ…...

Java 锁 面试题(ReentrantLock、synchronized)
Java 锁 面试题(ReentrantLock、synchronized) 1. 锁2. ReentrantLock2.1 ReentrantLock 的实现原理2.2 AQS 是什么?2.3 CAS 是什么? 3. synchronized3.1 synchronized 的实现原理3.2 synchronized 的锁升级过程3.2.1 无锁3.2.2 偏…...

Python中的缩进是什么意思?
在Python中,缩进是指在代码中使用空格或制表符来表示代码块的层次结构。Python使用缩进作为语法的一部分,以定义代码的逻辑结构和代码块的范围。缩进在Python中具有以下几个重要的方面和含义。 代码块的开始和结束: 缩进在Python中用于标识代…...

2023年9月数学建模:最小二乘优化、曲线拟合与函数逼近
2023年9月数学建模国赛期间提供ABCDE题思路加Matlab代码,专栏链接(赛前一个月恢复源码199,欢迎大家订阅):http://t.csdn.cn/Um9Zd 目录 1. 最小二乘优化 1.1 最小二乘优化的原理 1.2 最小二乘优化的方法...