数学中我们常见到函数的概念;但是你了解C语言中的函数吗?
维基百科中对函数的定义:子程序
在计算机科学中,子程序(英语:subroutine、procedure、function、routine、method、subprogram、callable unit),是一个大型程序中的某部分代码,由一个或多个语句块组成。
它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。
一般会有输入参数并且返回值,提供对过程的封装和细节的隐藏。
这些代码通常被集成为软件库。
C语言中函数的分类:
1、库函数
2、自定义函数
库函数:
为什么会有库函数?
1、我们知道在学习C语言编程的时候,总是在一个代码编写完成之后,迫不及待的想要知道结果,想把这个结果打印到我们的屏幕上看看。
这个时候,我们会频繁的使用一个功能:将信息按照一定的格式打印到屏幕上(printf)。
2、在编程的过程,我们会频繁的做一些字符串的拷贝工作(strcpy)。
3、在编程中,我们也会计算,总是会计算n的k次方这样的运算。(pow)
像上面我们描述的基础功能,它们不是业务性的代码。
我们在开发的过程中每个程序员都可能用得到,为了支持可移植性和提高程序的效率,所以C语言的基础库中提供一系列类似的库函数,方便程序员进行软件开发。
C语言本身提供给我们的函数叫库函数。
了解学习库函数?
推荐网站:www.cplusplus.com
输入strcpy
出现 C library——指c库
右边为头文件,打开头文件往下滑,就能看到库函数,点开就能看到详细信息。
头文件包括很多库函数(将函数放到头文件里)
要想了解C语言的全部库函数,就要从头文件开始,一个一个去了解。
<stdio.h>标准输入输出头文件里的函数都是IO函数。
简单的总结,C语言常用的库函数都有:
1、IO函数(输入输出函数)Input output
2、字符串操作函数(比如:strlen函数求字符串长度)
3、字符操作函数(比如:判断字符大小写,或将大小写转换)
4、内存操作函数(如:memset函数)
5、时间\日期函数
6、数学函数
7、其他函数
我们参照文档,学习几个库函数:
strcpy——string strcpy——字符串拷贝
在cplusplus网站中搜索strcpy,跳出介绍界面。
function——意思是它是一个函数;函数名叫strcpy
关于函数的细节(格式):
char* strcpy(char* destination,const char* source);
char*——指针类型(指针用来存放地址)
destination——目的地
source——源头
整体意思是:将源头拷贝到目的地这个意思。
strcpy拷贝字符串包括“\0”。
验证方法:F10+监视窗口。
(在补充一些关于cplusplus中文档的意思:outout——运行结果;parameters——参数(对形参的描述);return value——返回值;example——举例)
举例——
#include<string.h>
int main(){
char arr1[]="bit";
char arr2[]="#####"
strcpy(arr2,arr1);
printf("%s\n",arr2);
return 0;
}
【注:strcpy函数对应的头文件是——#include<string.h>】
这里 strcpy(arr2,arr1);中arr2是目的地,arr1是源头
打印结果为:bit
有一个问题:那竟然吧arr1[ ]里的内容拷贝过来了,可为什么arr2[ ]却输出bit?bit后面的井号怎么没有打印出来?
这是因为strcpy在拷贝的时候连同\0也一起拷贝过来;且又因\0是字符串结束标志。(打印的时候也一样)
因此,在打印的时候,遇到“\0”就停止了,不会打印后面字符。
【注:使用库函数,必须包含#include对应的头文件。】
这里对照文档学习库函数,目的是掌握库函数的使用方法。
注意:原字符串比目=目标字符串长的时候,进行strcpy时会溢出。
这里作为程序员建议要保证目标字符串的空间足够大,能放下源头拷贝过来的数据,否则会出现bug。
这里在介绍一个函数:
memset——memroy (内存) set(设置)
打开文档搜索memset
对memset的描述:
void*memset(void*ptr,int value,size_t num);
void*——指针类型
ptr——内存块
value——设置值
size_t——要被设置的字节个数
num——值
Fill block of memory——填充内存块
意思是:把ptr所指向的那块空间前num个字节的内容设置成我们指定的value值。
int main(){
char arr[]="hello world";
memset(arr,'*',5);
printf("%s\n",arr);
return 0;
}
打印结果为:***** world
这里arr表示内存块,*表示改变值,5——字节个数
但要注意int value这里不能放字符串,但可以字符。
这是因为任何字符存储的时候,在内存存的是与之对应的ASCII码值;在传参的时候,其实传过去也是ASCII码值,而ASCII码值是整数。
【注意:如果没有练会阅读文档这样的能力,那在公司里面会非常吃亏的;公司里也有自己的库,不仅要学会C语言的库,也要学公司里的库(文档)】
如何学会使用库函数?不需要全部记住。
但要学会查询工具的使用:
MSDN(Microsoft Developer Network)
www.cplusplus.com
http://en.cppreference.com(en.英文版 ch.中文版)
最后,英文很重要;最起码得看懂文献。
自定义函数
如果库函数能做所有事,那还要程序员干什么?
所以更加重要的是自定义函数。
自定义函数和库函数一样,有函数名、返回值类型和函数参数;但是不一样的是这些都是我们自己来设计的;这给程序员一个很大的发挥空间。
函数的组成:
ret_type fun_name(para1,*){
statement; //语句项
}
ret_type——返回类型
fun_name——函数名
para1——函数参数
如:
int Add(int x,int y){
int z=0;
z=x+y;
return z;
}
int对应ret_type
Add对应fun_name
int x对应para1
int y对应 *
大括号里面叫做函数体,函数体交代的是函数的实现。
例如——创建get_max函数来获取最大值
int get_max(int x,int y){
if(x>y)
return x;
else
return y;
}
int main(){
int a=10;
int b=20;
int max=get_max(a,b);
return 0;
}
写一个函数可以交换两个整形变量的内容。
这里介绍一个函数——swap函数(用于交换)
void——空;无的意思(代表没有返回值)
检查方法:F10+监视窗口(输入值)
但对于想要检测的自定义函数,则要按F11。
void swap1(int x,int y){
int tmp=0;
tmp=x;
x=y;
y=tmp;
}
int main(){
int a=10;
int b=20;
printf("a=%d b=%d\n",a,b);
swap1(a,b);
printf("a=%d b=%d\n",a,b);
return 0;
}
打印结果为a=10,b=20;a=10,b=20
并没有得到我们想要的结果。
分析:首先,程序都是从主函数进入的,当我们来到
int a=10;
int b=20;
这里int a;int b是开辟两块空间用来存放值的。
但当我们来到——
swap1(a,b);
这一步时,因为两对空间的独立,实际上并没有影响到a,b的。
void swap1(int x,int y){
int tmp=0;
tmp=x;
x=y;
y=tmp;
}
在定义函数时,所建用来接收的变量,从另一意思来讲也是独立的;也就是说同样开辟了名为x和y的空间。
函数体确实会改变,但在swap1中x,y并没有影响到a,b。
这是因为形参在实例化之后,其实相当于实参的一份临时拷贝。
这里可以看到swap1函数在调用的时候,x,y拥有自己的空间,同时拥有了和实参一模一样的内容。
回顾指针的思路——指针用来存放地址
int main(){
int a=10;
int* pa=&a; //开辟一块空间用来存放a的地址
*pa=20; //解引用操作,改变原来a的值
printf("%d\n",a);
return 0;
}
这里int*——指针类型;pa——指针变量。
回顾上一题,既然我们用swap1的方法在开辟一块空间,最后形成两队相对独立互不影响的空间;
那不如将a,b的地址存放到一块空间(即大空间内有小空间),这样并集的思路,就可以改变a,b的值了。
即——
void swap2(int* pa,int* pb){
int tmp=0;
tmp=*pa;
*pa=*pb;
*pb=tmp;
}swap2(&a,&b);
上面swap1和swap2函数中的参数x,y;pa,pb;都是形式参数。
在main函数中传给swap1的a,b和传给swap2函数的&a,&b是实际参数。
当实参传给形参的时候,形参其实是实参的一份临时拷贝,对形参的修改是不会改变实参的。