一.学习目标:
学习完函数这部分内容我们应该掌握:
1.函数是什么
2.库函数
3.自定义函数
4.函数参数
5.函数调用
6.函数的嵌套调用和链式访问
7.函数的声明和定义
8.函数的递归
那么就让我们进入到函数的学习中吧
二.函数是什么?
在计算机科学中,子程序(英语:subroutine, subprogram, callable unit),是一个大型程序中的某部分代码,由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。
一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库。
以上是维基百科对函数(又称为:子程序)的解释,如我们常见的函数有printf(),scanf(),strlen()等,这些函数的作用有的是输出内容、接收用户输入的内容和计算字符串长度,当执行完成后函数就会返回应该结果给用户,我们来看一个之前我们写的自定义函数的求和的程序:
#include<stdio.h>
int Add(int x , int y){
int answer = x + y;
return answer;
}
int main(void){
int a = 10;
int b = 20;
int sum = Add(a,b);
printf("sum=%d\n",sum);
getchar();
return 0;
}
Add函数为用户自定义函数,该函数的作用就是对x与y进行求和然后将求和的结果赋值给变量answer,最后使用return语句返回answer,main()函数中a与b是两个待求和的变量,调用Add()函数将a与b的值传入Add()函数中,最后将Add()函数的返回值赋值给sum,以下是程序的运行结果:
三.库函数
1.什么是库函数?
库函数是C语言提供给我们的函数,在早期C语言还没有printf()函数这时候输出内容就变得很困难,所以当人们发现有些功能是需要频繁使用的时候就发明了库函数,从此当我们需要输出的时候我们再也不需要写一大串代码,只需要进行预处理指令然后调用相对应的函数即可实现功能
若需要了解具体某一个函数需要执行的预处理指令请访问 https://www.cplusplus.com 进行查询
2.C语言中的库函数有哪些?
(1.IO函数
(2.字符串操作函数
(3.字符函数
(4.内存操作函数
(5.时间/日期函数
(6.数学函数
(7.其他库函数
3.库函数的学习
下面我们以strcpy()与menset()这两个库函数作为示范
strcpy函数的原型
char* strcpy(char* destination , const char* source)
我们可以看到函数原型中char* 其代表着字符串指针,destination代表的是目的地,source则代表的是源,也就是将源中的内容拷贝到目标地址,这样我们就可以自己尝试使用这个库函数了,如以下代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main(void){
char arr1[] = "hello";
char arr2[] = "*****";
strcpy(arr2,arr1);
printf("arr[]=%s arr2[]=%s\n",arr1,arr2);
getchar();
return 0;
}
数组arr1中存放着 “hello”这个字符串,数组arr2中存放着 “*****”字符串,我们上面已经通过猜测了解了函数的大概用法,函数中第一个参数为拷贝的目标,第二个参数为拷贝源,随后我们为了验证我们的猜想我们将两个字符串通过printf()函数输出出来,结果如图所示:
程序输出的结果也证实了我们的猜想,数组arr1中的内容被成功拷贝到了数组arr2中,数组arr2中原有的内容被覆盖掉了
注意:使用strcpy()字符串拷贝函数的时候需要声明头文件<string,h>
思考一下那当arr2数组中字符串内容比arr1数组中多的时候会发生什么?如下面一段代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main(void){
char arr1[] = "hello";
char arr2[50] = "**************************";
strcpy(arr2,arr1);
printf("arr[]=%s arr2[]=%s\n",arr1,arr2);
getchar();
return 0;
}
这时候我们直接按下F5运行程序会发现程序输出的内容是hello,但是当我们按下F10进入调试,我们可以在监视窗口输入两个变量的名称(这里是arr1与arr2)进行观察我们可以发现arr1中的内容拷贝到arr2中的时候仅覆盖了6个字符(包括\0),如图所示:
思考一下如果目标数组中内容小于源数组中的内容会发生什么?
答案:会发生字符串溢出,这是很严重的一个bug,所以我们在使用的时候需要注意目标数组一定需要大于源数组,在使用这类字符串操作函数的时候也需要谨慎,防止出现错误
我们接下来再来看一下memset()函数的原型
void* memset(void *ptr , int value , size_t num)
这时候我们可能会比较难猜测这个函数的具体意思,这时候我们就需要查看文档,网址在上面,我们在网站中搜索memset,就可以看到函数的用法,由于网站是英文我就将已经翻译好的文章截图:
我们来看以下这段代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main(void){
char arr1[] = "hello my friend";
memset(arr1,'#',5);
printf("arr1=%s\n",arr1);
getchar();
return 0;
}
arr1数组中存储着一串字符串,我们想要将 hello 替换成 # 号,这时候我们就可以使用memset()函数
memset()需要三个参数,第一个参数是目标数组,第二个参数是你需要填充的内容,第三个值是填充多少个字节,这样我们就可以对数组arr1前5个字符进行了填充,当然可能我们会疑惑在函数原型中第二个参数不应该是int类型的吗,我们怎么传入了一个字符*号,其实所有传入的数据都会自动转换为ASCII码进行存储,而ASCII码都是整型的数字,正好对应了前面的int类型,当然我们也不能瞎传入东西,比如说传一个"hi"字符串,这也是不行的
2023/8/6
王起舟