【C语言_15】自定义函数和math库函数详解篇!

时间:2022-10-05 19:56:09

一.函数的概念

1.什么是函数?

函数就是一段封装好的,可以重复使用的代码,它使得我们的程序更加模块化,不需要编写大量重复的代码。

函数可以提前保存起来,并给它起一个独一无二的名字,只要知道它的名字就能使用这段代码。还可以输入数据给函数,并根据数据的不同做出不同的操作,最后再把处理结果反馈给我们。

2.函数的分类

(1).系统函数

在各个数据库中,如果要使用,需要提前声明。

例:#include<math.h>  #include<string.h>

(2).自定义函数

自定义函数又分为无参函数和有参函数。

二.定义声明调用函数

1.无参函数的定义

无参函数是指在主调函数调用被调函数时,主调函数不向被调函数传递数据。无参函数一般用来执行特定的功能,可以有返回值,也可以没有返回值,一般没有返回值的居多。

void 函数名(){
做点什么
}
//void空类型没有返回值
//无参函数的定义
void print_h(){
printf(" * ");
printf(" * * ");
printf("* * *");
}

2.有参函数的定义

有参函数是指在主调函数调用被调函数时,主调函数通过参数向被调函数传递数据。在一般情况下,有参函数在执行被调函数时会得到一个值并返回给主调函数使用。

返回值类型 函数名(输入参数值){
做点什么
return 函数返回值;
}
//有参函数的定义
#include<stdio.h>
int add(int a,int b){
return a+b;
}

3.函数声明

编译器会从上向下阅读代码:

如果把add函数放在主函数之前,就不需要函数声明。因为当看见add函数时,编译器就知道定义了一个add函数。接着在主函数中需要使用到add函数。由于编译器已经知道了add定义,因此编译器可以正确调用add函数。编译器可以正常编译通过。

如果把add函数放在主函数之后,这时就需要声明函数,如果没有声明函数,当编译器在主函数中看见add函数时会报错。

#include<stdio.h>
int add(int a,int b);//声明函数
int main(){
int sum;
sum=add(2,3);
printf("sum=%d",sum);
return 0;
}
int add(int a,int b){
return 0;
}

4.调用函数

//调用无参函数
#include<stdio.h>
void print_h() {
printf(" * \n");
printf(" * * \n");
printf("* * *\n");
}
int main() {
print_h();
return 0;
}

运行结果:

【C语言_15】自定义函数和math库函数详解篇!

//调用有参函数
#include<stdio.h>
int add(int a,int b){
return a+b;
}
int main(){
int sum;
sum=add(2,3);
printf("sum=%d",sum);
return 0;
}
运行结果:

【C语言_15】自定义函数和math库函数详解篇!

5.函数应用(求三角形的面积)

#include<stdio.h>
#include<math.h>
double isTriangle(double a, double b, double c);
double areaofTriangle(double a, double b, double c);
int main() {
double a, b, c, s;
printf("请输入边长a,b,c:\n");
scanf("%lf %lf %lf", &a, &b, &c);
if (isTriangle(a, b, c) == 0) {
printf("It isn't triangle");
return 0;
}
s = areaofTriangle(a, b, c);
printf("该三角形的面积为:%lf", s);
return 0;

}
double isTriangle(double a, double b, double c) {
if (a + b > c && a + c > b && b + c > a)
return 1;
else
return 0;
}
double areaofTriangle(double a, double b, double c) {
double p, s;
p = (a + b + c) / 2;
s = sqrt(p * (p - a) * (p - b) * (p - c));
return s;
}

运行结果:

【C语言_15】自定义函数和math库函数详解篇!

三.封装函数优势

1:函数是C语言的模块,一块块的,有较强的独立性,可以相互调用,也就是说,可以在函数A中调用函数B,又可在函数B中调用函数C,不仅如此,还可以调用函数自身(函数递归)。

2:函数是完成一个个特定任务的语句集合,它能完成你所想要的某种特定任务,当你要用时,只需要调用它即可,在后续的修改或是维护过程中,只需要针对这一个进行修改即可。

3:在我们写代码的时候,有时候会重复写一段代码,而这段代码所执行的功能,操作是一样的,只是针对的数据不一样,这个时候,将这段功能写成一个函数模块,在需要用到的时候调用即可,进而避免了写重复的代码,避免了重复性操作。

4:方便代码的维护,当我们知道哪个部分出问题后,或者需要修改某个功能,那就只需要修改那部分的代码即可。

四.函数自动类型转换

#include<stdio.h>
int add(int a, int b) {
return a + b;
}
int main() {
int sum;
sum = add(2.2,3.3);
printf("sum=%d", sum);
return 0;
}

【C语言_15】自定义函数和math库函数详解篇!

运行结果:

【C语言_15】自定义函数和math库函数详解篇!

五.形参实参

#include<stdio.h>
int add(int a,int b){//a,b为形式参数,简称形参
return a+b;
}
int main(){
int sum;
sum=add(2,3);//2,3为实际参数,简称实参
printf("sum=%d",sum);
return 0;
}

六.形参和实参是相互独立

我们先看一下这个下面这个代码:交换a,b的值

#include<stdio.h>
int main(){
int a,b,m;
a=1;
b=2;
printf("a=%d b=%d\n",a,b);
m=a;
a=b;
b=m;
printf("a=%d b=%d\n",a,b);
return 0;
}

运行结果:

【C语言_15】自定义函数和math库函数详解篇!

我们再用函数来实现a,b的交换

#include<stdio.h>
void swap(int a,int b){
int m;
m=a;
a=b;
b=m;
}
int main(){
int a,b,m;
a=1;
b=2;
printf("a=%d b=%d\n",a,b);
swap(a,b);
printf("a=%d b=%d\n",a,b);
return 0;
}

运行结果:(我们可以看出a,b并没有交换,这是怎么回事呢?)

【C语言_15】自定义函数和math库函数详解篇!

原因:虽然swap函数和主函数中都是变量a,b,但是这两个函数中的a,b变量相互独立。无论swap函数中的变量a,b怎么变化。都不会影响主函数中的变量a,b。

七.不同函数的变量是相互独立的

  • 函数内声明的变量为局部变量
  • 不同函数内的局部变量相互独立
  • 一个局部变量在另一个函数中使用,可以把它当作一个参数,传递它的值到另一个函数中
#include<stdio.h>
void func() {
int a = 100;
printf("a=%d in func\n", a);
}
int main() {
int a = 0;
printf("a=%d in main\n", a);
func();
printf("a=%d in main\n", a);
return 0;
}

运行结果:

【C语言_15】自定义函数和math库函数详解篇!

八.函数递归

#include<stdio.h>
int func(int a) {
if (a <= 10) {
printf("%d\n", a);
func(a + 1);
}
else
return 0;
}
int main() {
func(1);
return 0;
}

运行结果:

【C语言_15】自定义函数和math库函数详解篇!

#include<stdio.h>
int func(int a) {
if (a <= 10) {
printf("before %d\n", a);
func(a + 1);
printf("after %d\n", a);
}
else
return 0;
}
int main() {
func(1);
return 0;
}

运行结果:(为什么会出现先打印完before %d再打印after %d的结果呢?大家可以在评论区留下自己的想法。)

【C语言_15】自定义函数和math库函数详解篇!


九.<math.h>库函数

函数原型:float fabs(float x)
功能:求浮点数x的绝对值

函数原型:int abs(int x)
功能:求整数x的绝对值

函数原型:float acos(float x)
功能:求x(弧度表示)的反余弦值

函数原型:float asin(float x)
功能:求x(弧度表示)的反正弦值

函数原型:float atan(float x)
功能:求x(弧度表示)的反正切值

函数原型:float atan2(float y, float x)
功能:求y/x(弧度表示)的反正切值

函数原型:float ceil(float x)
功能:求不小于x的最小整数

函数原型:float cos(float x)
功能:求x(弧度表示)的余弦值

函数原型:float cosh(float x)
功能:求x(弧度表示)的余弦值

函数原型:float cosh(float x)
功能:求x的双曲余弦值

函数原型:float exp(float x)
功能:求e的x次幂

函数原型:float floor(float x)
功能:求不大于x的最大整数

函数原型:float fmod(float x, float y)
功能:计算x/y的余数

函数原型:float frexp(float x, int *exp)
功能:把浮点数x分解成尾数和指数

函数原型:float ldexp(float x, int exp)
功能:返回x*2^exp的值

函数原型:float modf(float num, float *i)
功能:将浮点数num分解成整数部分和小数部分

函数原型:float hypot(float x, float y)
功能:对于给定的直角三角形的两个直角边,求其斜边的长度

函数原型:float log(float x)
功能:计算x的自然对数

函数原型:float log10(float x)
功能:计算x的常用对数

函数原型:float pow(float x, float y)
功能:计算x的y次幂

函数原型:float pow10(float x)
功能:计算10的x次幂

函数原型:计算10的x次幂
功能:计算x(弧度表示)的正弦值

函数原型:float sinh(float x)
功能:计算x(弧度表示)的双曲正弦值

函数原型:float sqrt(float x)
功能:计算x的平方根

函数原型:float tan(float x);
功能:计算x(弧度表示)的正切值

函数原型:float tanh(float x)
功能:求x的双曲正切值