文章目录
前言
这一篇我们讲讲C语言中的函数,供大家参考一下。我们在学习C语言时,看到函数,我们是否就会想起我们从小到大数学里面的“函数”,什么一次函数,二次函数,幂函数等等,都是x与y的关系,当我们给定x的值就可以得出y的值,反之同理。同样的我们C语言中的函数也有异曲同工之处,接下来我们进入正文。
提示:以下是本篇文章正文内容,下面案例可供参考
一、函数的概念
“函数”这个词我们并不陌生,不止我们学的数学里有我们的函数,在我们学习的C语言中也引入了函数(function)的概念。C语言中的函数就是一个完成某项特定任务的一段代码,每一段函数都可称为我们程序的子程序,这段代码是具有特殊的写法和调用方法的。我们整个程序可以分解成若干个函数来完成的,而且函数是可以复用的,大大的提升了开发软件的效率。
接下来我们要知道C语言中都有哪些函数?我们一般会见到的两类函数:
1、库函数
2、自定义函数
二、库函数
1.标准库和头文件
在C语言标准中规定了C语言的各种语法规则,C语言并不提供库函数;C语言的国际标准ANSI C规定了一些常用的函数的标准,被称为标准库,不同的编译器厂商根据ANSI提供的C语言标准给出了一系列函数的实现。这些函数就被称为库函数。
我们刚开始学习C语言时,都是从打印“Hello World!”开始的,我们直接使用的printf函数就是库函数,库函数也是函数,只不过这个函数是现成的,我们学会后便可以直接使用。有了这种库函数,一些常见的功能就不需要程序员自己实现了,“scanf”函数也是一样的。这在一定程度上提升了效率,并且库函数的质量和执行效率上都更有保证。
各种编译器的标准库中也提供了一系列的库函数,这些库函数根据功能的划分,都在不同的头文件中进行了声明。
库函数相关的头文件:https://zh.cppreference.com/w/c/header
里面有各种库函数相关的头文件,希望可以帮助到大家。
2.库函数的使用方法
我们对于库函数的学习和查看工具很多,比如:
C/C++官⽅的链接: https://zh.cppreference.com/w/c/header
cplusplus.com: https://legacy.cplusplus.com/reference/clibrary/
我们可以通过这些网站进行查询更详细的关于库函数的。
2.1 举例说明
接下来我们进行举例:sqrt函数 //计算平方根的函数
double sqrt (double x);
//sqrt 是函数名
//x 是函数的参数,表示当我们调用sqrt函数需要传递一个double类型的值
//double 是返回值的类型,表示函数计算的结果是double类型的值
其中库函数是在标准库中对应的头文件中声明的,所以当我们调用库函数的使用时,就要包含对应的头文件,如果不包含程序将会出现问题。
代码实践:
#include<stdio.h>
#include<math.h>
int main()
{
double a = 81.0;
double b =sqrt(a);
printf("%lf\n",b);
return 0;
}
运行结果:
到这里大概明白了如何去使用库函数,切记这里sqrt的返回值是double类型的,使用时要包含头文件。
如果我们想要了解更多的库函数,可以通过上面的链接进行查询,其次我们要知道库函数文档的一般格式:
1、函数原型
2、函数功能介绍
3、参数和返回类型说明
4、代码举例
5、代码输出
6、相关知识链接
三、 自定义函数
我们上面已经了解了关于库函数的一些知识,接下来我们了解一下自定义函数,自定义函数我们字面意思就是程序员在写程序时自己定义的一个函数,能给程序员写代码带来更多的创造性。
1、函数的语法形式
ret_type fun_name (形式参数)
{
}
1、ret_type 是函数返回类型(int、double、void等),用来表示函数计算结果的类型。
2、fun_mame 是函数名,我们对于不同的自定义函数都可以定义不同的函数名, 一般定义的函数名都比较要有意义,能让人一目了然,函数的作用,这样在我们调用时也比较方便。
3、括号中放的是形式参数,形式参数的类型要和我们传递的实参是同类型的,名字可以不同,但参数类型必须相同
4、{}里面是函数体,函数体是用来完成我们所需的计算过程的。
整个过程就是我们要对我们自定义函数进行传参(类似于加工的原材料),传递到函数中,函数进行计算(加工),然后在返回计算结果(成品)。
2、函数举例
举个例子:
我们自定义一个加法函数,完成两个数的相加。
#include<stdio.h>
int Add(int x,int y)
{
return x+y;
}
int main()
{
int a=0;
int b=0;
scanf("%d %d",&a,&b);
int c=Add(a,b);
printf("%d\n",c);
return 0;
}
运行结果:
我们根据我们的功能,定义了Add函数,其中Add(int x,int y)表示函数需要接收两个整形类型的参数,函数返回的结果也是整型。在我们自定义函数中,函数的参数部分需要交代清楚:参数的个数,类型,形参的名字。接下来我们说一下实参和形参:
1.实参
在我们上面给出的例子当中,我们调用的Add函数,我们需要给他传值,传递给Add函数的a和b就称为实际参数,简称实参。实际参数是真实传递给函数的参数。
2.形参
上述我们代码中的int Add(int x, int y)当中x,y称为形式参数,简称形参。如果只是定义了Add函数,而不去调用的话,Add函数的参数x和y只是形式上存在的,不会向内存申请空间,不会真实存在,所以教形式参数。只要在函数被调用的过程中为了存放实参传递过来的值,才会向内存申请空间,这个过程就是形参的实例化。
3.实参和形参的关系
虽然我们提到了实参是传递给形参的,他们之间是有联系的,但是形参和实参各⾃是独⽴的内存空间。我们可以理解为,形参是实参的一份临时拷贝。
四、数组做函数参数
如果我们想将数组作为参数传递给函数,在函数内部对数组进行操作,我们需要知道数组传参的几个重点知识:
1、函数的形式参数要和函数的实参个数匹配
2、函数的实参是数组,形参也是可以写成数组形式的
3、形参如果是一维数组,数组的大小可以省略不写
4、形参如果是二维数组,可以省略行,但不可以省略列
5、数字传参,形参是不会创建新的数组的
6、形参操作的数组和实参的数组是同一个数组
我们现在给定一个数组arr[]={9,8,7,6,5,4,3,2,1};我们想要让他所有数都重置为0,并逐个打印。那我们定义两个函数来进行操作,一个重置函数Set()一个打印函数Print()。
代码实现:
#include<stdio.h>
void Set(int arr[],int sz)
{
int i=0;
for(i=0;i<sz;i++)
{
arr[i]=0;
}
}
void Print(int arr[],int sz)
{
int i=0;
for(i=0;i<sz;i++)
{
printf("%d ",arr[i]);
}
}
int main()
{
int arr[]={9,8,7,6,5,4,3,2,1};
int sz=sizeof(arr)/sizeof(arr[0]);
Set(arr,sz);//重置数组都为0
Print(arr,sz);//打印重置后的数组内容
return 0;
}
运行结果:
五、嵌套调用和链式访问
1、 嵌套调用
嵌套调用就是函数之间的互相调用,只要我们自定义了函数,每个自定义函数内部都可以调用我们已经自定义的函数,函数的嵌套调用,可以让我们写代码更加的高效。
假设我们计算某年某月有多少天?想要利用函数实现,可以设计两个函数:
1、leap_year():根据年份确定是否为闰年
2、get_days_of_month():调⽤is_leap_year确定是否是闰年后,再根据⽉计算这个⽉的天数
代码实现:
#include<stdio.h>
int leap_year(year)//判断闰年的函数
{
if(((year%4==0)&&(year%100!=0))||(year%400==0))
return 1;
else
return 0;
}
int get_days_of_month(int year,int month)
{
//按照一般每个月有多少天进行初始化,第一个是0,那么数组下标就代表月份
int days[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int day=days[month];//通过我们输入的月份进行赋值
if(leap_year (year)&&month==2)
day+=1;//判断是否为闰年,闰年的2月为29天
return day;
}
int main()
{
int year=0;
int month=0;
scanf("%d %d",&year,&month);
int n=get_days_of_month(year,month);
printf("%d\n",n);
return 0;
}
运行结果:
当我们输入2000 2,则输出相对应的天数。
在这一段代码中,完成了一个独立的功能,其中反应了不少的函数调用:
1、main函数调用scanf、printf、get_days_of_month
2、get_days_of_month函数调用leap_year函数
2、链式访问
链式访问就是将一个数的返回值作为另外一个函数的参数,像链条一样将函数串联起来就是函数的链式访问。
例如:
#include <stdio.h>
int main()
{
printf("%d\n", strlen("asdfghj"));// strlen是求⼀个字符串的⻓度
return 0;
}
我们把strlen的返回值直接作为printf函数的参数,这就是一个链式访问的例子,通过strlen计算字符串的长度,计算出来的长度在作为printf函数的参数打印出来。
六、函数的声明和定义
1.函数的声明
从我们上面举的例子我们是否发现了我们定义的函数,都在main函数上面,那我们是否能定义在main函数的下面呢?
此时我们调换一下位置,在VS2022上则会发出警告。
如下:
所以函数的调用一定要满足先声明后使用,函数的定义也是一种特殊的声明,所以如果函数定义放在调用之前也是可以的
2、多个文件
我们刚开始学习C语言一般都是在一个文件里写的,但是一般在一些大型的程序中,我们一般不会把所有的代码都写在一个文件里面,我们往往要根据程序的功能,将代码拆分放在多个文件中。
一般情况下,函数的声明,类型的声明放在头文件(.h)中,函数的实现是放在源文件中的。
如下我们操作一下:
运行结果:
有了函数声明和函数定义,我们写代码就更加的方便和高效了。
总结
如有不足欢迎补充,大家一起学习!冲冲冲!