当前位置: 首页 > article >正文

NO.32十六届蓝桥杯备战|函数|库函数|自定义函数|实参|形参|传参(C++)

函数是什么

数学中我们其实就⻅过函数的概念,⽐如:⼀次函数 y = kx + b ,k和b都是常数,给⼀个任意的x ,就得到⼀个 y 值。其实在C/C++语⾔中就引⼊了函数(function)的概念,有些翻译为:⼦程序,⼦程序这种翻译更加准确⼀些。函数就是⼀个完成某项特定的任务的⼀⼩段代码,这段代码是有特殊的写法和调⽤⽅法的。
其实⼤家在前⾯学习的时候,就⻅过函数了,⽐如:main函数、scanf函数、printf函数、pow函数、sqrt函数等。C/C++语⾔程序其实是由若⼲个⼩的函数组合⽽成的,也可以说:⼀个⼤的计算任务可以分解成若⼲个较⼩的函数(对应较⼩的任务)完成。同时⼀个函数如果能完成某项特定任务的话,这个函数也是可以复⽤的,提升了开发软件的效率。

#include <iostream>  
using namespace std;  
int main()
{  
	int arr[10] = { 0 };  
	
	//打印数组的内容  
	//给数组的元素赋值为1~10  
	//打印数组  
	
	return 0;  
}

如果没有函数,我们能写出的代码如下的代码1,其中橙⾊部分的内容和绿⾊部分的代码是重复的,⽬的就是打印数组内容,那如果我能把这部分封装成⼀个函数,在需要的时候调⽤,就⽅便很多,这就是代码2

//代码1  
#include<iostream>  
using namespace std;  
int main()  
{  
	int arr[10] = { 0 };  
	//打印数组的内容  
	int i = 0;  
	for (i = 0; i < 10; i++)  
	{  
		cout << arr[i] << " ";  
	}  
	cout << endl;  
	//给数组的元素赋值为1~10  
	for (i = 0; i < 10; i++)  
	{  
		arr[i] = i + 1;  
	}  
	//打印数组  
	for (i = 0; i < 10; i++)  
	{  
		cout << arr[i] << " ";  
	}  
	cout << endl;  
	return 0;  
}
//代码2  
#include<iostream>  
using namespace std;  
void print_arr(int arr[])  
{  
	int i = 0;  
	for (i = 0; i < 10; i++)  
	{  
		cout << arr[i] << " ";  
	}  
	cout << endl;  
}  

int main()  
{  
	int arr[10] = { 0 };  
	//打印数组的内容  
	print_arr(arr);  
	//给数组的元素赋值为1~10  
	for (int i = 0; i < 10; i++)  
	{  
		arr[i] = i + 1;  
	}  
	//打印数组  
	print_arr(arr);
	  
	return 0;  
}

在代码2中 print_arr 就是我们⾃⼰定义的⼀个函数,使⽤函数能有什么好处呢?

  1. 模块化开发,⼀个⼤的功能,总能拆分成各种⼦功能,每个⼦功能都可以设计成⼀个函数,每个函数可以作为⼀个独⽴的模块存在,程序的逻辑更加清晰,逻辑关系更加明确。
  2. 代码可以复⽤,只要根据需要定义出⼀个函数,需要这个功能的地⽅,直接调⽤函数就⾏,降低了代码的冗余,提升了开发效率。
  3. ⽅便多个程序员之间协作开发,⽅便程序的多个模块之间互相交互。
  4. 熟悉函数的使⽤之后,代码的编写、阅读、调试、维护都变得更加容易。

函数的分类

在C/C++中,函数⼀般分为库函数和⾃定义函数

库函数

printf 、 scanf 都是库函数,库函数是标准库中提供的现成的函数,我们只要学习函数的功能,就能直接使⽤。有了库函数,⼀些常⻅的功能就不需要程序员⾃⼰实现了,⼀定程度提升了效率;同时库函数的质量和执⾏效率上都更有保证。
编译器的标准库中提供了⼀系列的库函数,这些库函数根据功能的划分,都在不同的头⽂件中进⾏了声明。
库函数的学习和查阅⼯具很多,⽐如:
C/C++官⽅参考⼿册:https://zh.cppreference.com/w/cpp/header
C/C++第三⽅⽹站:https://legacy.cplusplus.com/reference/
库函数中有数学相关的,有⽇期相关的,有算法相关的等等。这些库函数相关的信息都有⾃⼰对应的头⽂件,每⼀个头⽂件中都包含了相关的⼀组函数和类型等信息,库函数的学习不⽤着急⼀次性全部学会,慢慢学习,各个击破就⾏。
C++是兼容C语⾔,所以在C++中也包含了⼀些来⾃C语⾔的头⽂件,这些头⽂件的后缀是 .h ,如果需要也可以直接包含使⽤;有⼀些来⾃C语⾔的头⽂件,在C++中会在原来C语⾔的头⽂件进⾏了封装,在C++程序中更推荐C++的头⽂件写法,以下是常⻅C和C++对应的头⽂件:

解释C头文件C++头文件
常用数学函数<math.h><cmath>
浮点类型的极限<float.h><cfloat>
C风格输入输出<stdio.h><cstdio>
字符串处理<string.h><string>
库函数使⽤举例
sqrt
double sqrt (double x);
  • sqrt 是函数名
  • x 是函数的参数,表⽰调⽤ sqrt 函数需要传递⼀个 double 类型的值
  • double 是返回值类型,表⽰函数计算的结果是 double 类型的值
作用

Compute square root计算平⽅根
Returns the square root of x.(返回平⽅根)

头文件

库函数是在标准库中对应的头⽂件中声明的,所以库函数的使⽤,务必包含对应的头⽂件,不包含是可能会出现⼀些问题的。

#include <iostream>  
#include <cmath> //数学函数头⽂件,不包含则⽆法使⽤sqrt函数  
using namespace std;  
int main()  
{  
	double d = 16.0;  
	double r = sqrt(d);  
	cout << r << endl;  
	return 0;  
}

![[Pasted image 20250309151822.png]]

⾃定义函数

了解了库函数,其实库函数的功能是有限的,实际开发过程中还是得根据需要将代码封装成⾃定义的函数;⾃定义的函数就是⾃⼰设计和实现的函数

函数的语法形式
ret_type fun_name(形式参数)  
{ 

}
  • ret_type 是⽤来表⽰函数计算结果的类型,有时候返回类型可以是 void ,表⽰什么都不返回
  • fun_name 是为了⽅便使⽤函数;就像⼈的名字⼀样,有了名字⽅便称呼,函数有了名字⽅便调⽤,所以函数名尽量要根据函数的功能起的有意义。
  • 函数的参数就相当于⼯⼚加⼯需要的原材料,函数的参数也可以是 void ,明确表⽰函数没有参数。如果有参数,多个参数⽤逗号隔开,每个参数要分别交代清楚参数的类型和名字。
  • {} 括起来的部分被称为函数体,函数体就是完成计算的过程。
函数定义

写⼀个加法函数,完成2个整型变量的加法操作

#include<iostream>  
using namespace std;  
int main()  
{  
	int a = 0;  
	int b = 0;  
	//输⼊  
	cin >> a >> b;  
	
	//任务:调⽤加法函数,完成a和b的相加  
	//求和的结果放在r中  
	//to do  
	
	//输出  
	cout << r << endl;  
	return 0;  
}

给函数取名: Add ,函数 Add 需要接收2个整型类型的参数,函数计算的结果也是整型

#include<iostream>  
using namespace std;  
//这就是函数的定义  
int Add(int x, int y)  
{  
	int z = 0;  
	z = x + y;  
	return z;  
}  

int main()  
{  
	int a = 0;  
	int b = 0;  
	//输⼊  
	cin >> a >> b;  
	//调⽤加法函数,完成a和b的相加  
	//求和的结果放在r中  
	int r = Add(a, b);  
	//输出  
	cout << r << endl;  
	return 0;  
}

Add 函数也可以简化为

int Add(int x, int y)  
{  
return x + y;  
}

![[Pasted image 20250309152147.png]]

函数的参数部分需要交代清楚:参数个数,每个参数的类型是啥,形参的名字叫啥

函数参数和返回值

实参和形参

实际上,在函数定义和使⽤的过程中,函数的参数要被分为两种:

  • 实际参数,简称实参
  • 形式参数,简称形参
实参

实际参数就是真实传递给函数的参数。
在上⾯代码中,第4~6⾏是 Add 函数的定义,有了函数后,再第19⾏调⽤ Add 函数的。
我们把第19⾏调⽤ Add 函数时,传递给函数的参数 a 和 b ,称为实际参数,简称实参。

形参

在上⾯代码中,第4⾏定义函数的时候,在函数名 Add 后的括号中写的 x 和 y ,称为形式参数,简称形参。
为什么叫形式参数呢?实际上,如果只是定义了 Add 函数,⽽不去调⽤的话, Add 函数的参数 x 和 y 只是形式上存在的,不会向内存申请空间,不会真实存在的,所以叫形式参数。形式参数只有在函数被调⽤的过程中为了存放实参传递过来的值,才向内存申请空间,这个过程就是形式的实例化。

实参和形参的关系

虽然我们提到了实参是传递给形参的,他们之间是有联系的,但是形参和实参各⾃是独⽴的内存空间。
这个现象是可以通过调试来观察的。请看下⾯的代码和调试演⽰:

#include<iostream>  
using namespace std;  
int Add(int x, int y)  
{  
	int z = 0;  
	z = x + y;  
	
	return z;  
}
int main()  
{  
	int a = 0;  
	int b = 0;  
	
	//输⼊  
	cin >> a >> b;  
	//调⽤加法函数,完成a和b的相加  
	//求和的结果放在r中  
	int r = Add(a, b);  
	//输出  
	cout << r << endl;  
	
	return 0;  
}

![[Pasted image 20250309152421.png]]

我们在调试的可以观察到, x 和 y 确实得到了 a 和 b 的值,但是 x 和 y 的地址和 a 和 b 的地址不⼀样的,当 a 和 b 传参给形参x和y的时候, x 和 y 只是得到了 a 和 b 的值,他们得有⾃⼰独⽴的空间。所以我们可以理解为形参是实参的⼀份临时拷⻉。
![[Pasted image 20250309153212.png]]

函数传参

数组做函数参数

在使⽤函数解决问题的时候,难免会将数组作为参数传递给函数,在函数内部对数组进⾏操作。⽐如:写⼀个函数将⼀个整型数组的内容,全部置为 -1 ,再写⼀个函数打印数组的内容。

#inculude <iostream>  
using namespace std;  
int main()  
{  
	int arr[] = {1,2,3,4,5,6,7,8,9,10};  
	set_arr(); //设置数组内容为-1  
	print_arr(); //打印数组内容  
	return 0;  
}

这⾥的 set_arr 函数要能够对数组内容进⾏设置,就得把数组作为参数传递给函数,同时函数内部在设置数组每个元素的时候,也得遍历数组,需要知道数组的元素个数。所以我们需要给 set_arr传递2个参数,⼀个是数组,另外⼀个是数组的元素个数。仔细分析 print_arr 也是⼀样的,只有拿到了数组和元素个数,才能遍历打印数组的每个元素。

int main()  
{  
	int arr[] = {1,2,3,4,5,6,7,8,9,10};  
	int sz = sizeof(arr)/sizeof(arr[0]);  
	set_arr(arr, sz);   //设置数组内容为-1
	print_arr(arr, sz);   //打印数组内容
	return 0;
}

数组作为参数传递给了 set_arr 和 print_arr 函数了,那这两个函数应该如何设计呢?
这⾥我们需要知道数组传参的⼏个重点知识:

  • 函数的实参的名字和形参的名字可以相同,也可以不同
  • 函数的形式参数要和函数的实参个数匹配
  • 函数的实参是数组,形参也写成数组形式的
  • 形参如果是⼀维数组,数组⼤⼩可以省略不写
  • 形参如果是⼆维数组,⾏可以省略,但是列不能省略
  • 数组传参,形参是不会创建新的数组的
  • 形参操作的数组和实参的数组是同⼀个数组
void set_arr(int arr[], int sz)  
{  
	int i = 0;  
	for(i = 0; i < sz; i++)  
	{  
		arr[i] = -1;  
	}  
}  
void print_arr(int arr[], int sz)  
{  
	int i = 0;  
	for(i = 0; i < sz; i++)  
	{  
		cout << arr[i] << " ";  
	}  
	cout << endl;  
}
字符串做函数参数

那如果将字符串做函数参数呢?其实也很简单,直接在形参的部分使⽤字符串来接收就可以。这⾥的形参 s 也是实参 s 的⼀份临时拷⻉,对形参的修改不能影响实参。

void test(string s)  
{  
	cout << s << endl;  
}  
int main()  
{  
	string s("hello world");  
	test(s);  
}
全局变量不⽤传参

全局变量的作⽤域很⼤,在整个程序中都可以使⽤,那么只要把变量、数组等定义成全局变量,在函数中使⽤,是可以不⽤传参的,在竞赛中为了⽅便经常使⽤,但是在软件⼯程中很少这么使⽤

#include <iostream>  
using namespace std;  
int arr[10] = { 0 };  

void print_arr()  
{  
	int i = 0;  
	for (i = 0; i < 10; i++)  
	{  
	cout << arr[i] << " ";  
	}  
	cout << endl;  
}  

int main()  
{  
	//打印数组的内容  
	print_arr();  
	//给数组的元素赋值为1~10  
	for (int i = 0; i < 10; i++)  
	{  
	arr[i] = i + 1;
	}  
	//打印数组  
	print_arr();  
	return 0;  
}

有时候变量或者数组,定义成全局的时候,是不能解决问题,⽐如:递归等场景,这时候,就得考虑传参的问题


http://www.kler.cn/a/579009.html

相关文章:

  • 系统架构评估方法-ATAM方法
  • SQL根据分隔符折分不同的内容放到临时表
  • 【SpringBoot】深入剖析 Spring Boot 自动装配原理(附源码与实战)
  • vue3 vite项目安装eslint
  • python将目录下的所欲md文件转化为html和pdf
  • JVM常用概念之移动GC和局部性
  • k8s下部署ansible进行node-export二安装
  • electron builder打包时,出现errorOut=ERROR: Cannot create symbolic link
  • 【AVRCP】协议深入解析(1):从框架到数据单元
  • 负载均衡集群和高可用集群
  • 【神经网络】0.深度学习基础:解锁深度学习,重塑未来的智能新引擎
  • chatgpt完成python提取PDF简历指定内容的案例
  • 【2025深夜随笔】简单认识一下Android Studio
  • kafka单机部署实战
  • 10分钟看明白爆火的本地知识库! 掌握本地知识库基本概念与RAG的完整架构
  • C++学习之格斗小游戏综合案例
  • 6-5,web3浏览器链接区块链(react+区块链实战)
  • 【已解决】AttributeError: module ‘numpy‘ has no attribute ‘object‘.
  • css实现元素垂直居中显示的7种方式
  • Vue、React、原生小程序的写法对比差异