文章目录
前言
Hello,everyone! forever 近段时间有点忙,所以一直没有更新了,今天给大家带来的是函数的相关介绍和归纳!希望加深自己的记忆和理解,也望能够给出初学者带来帮助,更望大佬们多多指正和支持哦~
正文
一、C语言函数概述
在 C 语言中函数是程序的基本单位,每个程序都是具有独立功能的模块。利用函数,可以更加方便地实现程序规模化,同时使整个程序的组织、编写、阅读、调试、修改和维护更加方便,使程序机构清晰、易读、易于理解。函数的合理利用还可以大大提高程序的可重用性。在 C 中一定会包含一个主函数(main函数),在程序中都会使用到不同的库函数。因此,函数是必不可少的元素之一。
二、C程序的基本结构
1、结构介绍
上面已经介绍过,C 源程序是由函数组成的。虽然我们之前介绍过的一些简单程序都是只有一个主函数 main()(必不可少),但是实用程序往往是由多个函数组成的。在 C 源程序中,函数作为基本模块,特定功能的实现都是通过对相关函数模块的调用来实现的。C 语言中不仅提供了丰富的库函数,还允许用户自己定义函数,并且合理的调用使用函数。
2、具体程序剖析
示例:求两位数里的所有绝对素数,绝对素数是:一个素数经过任意次调换位,仍然为素数。
*/求两位数的所有绝对素数 绝对素数:一个素数经过任意次调换位,仍然是素数。如13和31*
#include<stdio.h>
int prime(int n);
int ko_prime(int m);
int prime(int n)//判断素数
{
int i = 0;
if (n <= 1)
{
return 0;
}
else
{
for (i = 2; i < n; i++)
{
if (n % i == 0)
{
return 0;
break;
}
}
if (n == i)
{
return 1;
}
}
}
int ko_prime(int m)//判断是否为绝对素数。
{
int a = 0;
a = (m % 10) * 10 + m / 10;
if (prime(m)==1 && prime(a)==1)
{
return 1;
}
else
{
return 0;
}
}
int main()//主函数 main()函数
{
for(int i = 10; i < 100; i++)
{
if (ko_prime(i)==1)
{
printf("%d ", i);
}
}
return 0;
}
运行结果:
以上程序执行过程如下:
(1)程序开始运行后首先执行 main 函数中的语句;
(2)main 函数中要判断绝对素数,所以调用了自己定义的 ko_prime() 函数,进入该函数开始执行该函数代码;
(3)该函数中需要判断素数,所以需要调用 prime() 函数,进入该函数开始执行,判断素数结束后,又将值返回到 ko_prime() 函数 ,此时执行后 ko_prime() 函数又将值返回到 main() 函数里;
(4)继续执行 main() 函数里后面的语句,一直到执行完毕。
该程序是由三个函数构成:main(),prime(),ko_prime(),从模块化的观点来看看这个程序由三个模块构成,每个模块都由函数构成。来看看下面的关系图:
3、关于函数的说明
(1)一个 C 源程序可以由一个或多个源文件构成,一个源文件又可以由一个或多个函数构成;
(2)一个 C 源程序中所有函数都是相互独立的,各个函数键可以相互调用,但任何函数均不可调用 main 函数;
(3)一个源程序总是从 main 函数开始执行的,直到 main 函数结束。
三、函数的分类
从不同角度看,可以有以下几种分类:
1、从用户使用的角度
(1)库函数,也称标准函数。这是由系统提供的,用户不必定义,只需要在程序前引用该库函数所在的头文件即可。在 C 编译系统中提供了很多库函数,不同的编译系统提供的库函数的功能完全不同。
(2)用户自定义函数。根据需要,在 C 语法规则内自己编写需要的函数。
2、从函数传参的角度
(1)有参函数。在函数定义时带有参数的函数。在函数定义时的参数称为形式参数;在相应的函数调用时也必须由参数,称为实际参数。在函数调用时,主调函数与被调函数之间通过参数进行数据传递。
(2)无参函数。在函数定义时没有形式参数的函数。在调用无参函数时,主调函数并不将数据传递给被调函数。
3、从函数使用范围角度
(1)内部函数。只允许在本源文件中使用的函数。
(2)外部函数。除了允许在本源文件中使用,还可以在其他源文件中使用的函数。
四、函数的声明和定义
1、函数的声明
函数声明形式:
函数类型 函数名(形参类型说明 形参1,形参类型说明 形参2,……);
一般在定义函数之前都会对函数进行声明,在复杂的程序面前,函数的声明有助于帮助他人较好的清楚该程序的逻辑,以及了解整个程序的架构。如在 VS2019 编译环境下,如未声明自定义函数且还将函数放到 main() 函数后面书写时,就会出现报错。这里上代码解释解释:
如下错误代码示例:
输出100-1000之间的水仙花数,例:153=13+53+33
//注意错误代码示例
#include<stdio.h>
#include<math.h>
//int water(int n); 这里将函数的声明注释掉
int main()
{
for (int i = 100; i <= 999; i++)
{
if (water(i)==1)
{
printf("%d ", i);
}
}
return 0;
}
int water(int n)
{
int a = 0, b = 0, c = 0, d = 0;
int sum = 0;
a = n % 10;
b = n / 10;
c = b % 10;
d = b / 10;
sum = pow(a, 3) + pow(d, 3) + pow(c, 3);
if (sum == n)
{
return 1;
}
else
{
return 0;
}
}
报错:
注意:以上代码示例就是在定义函数在主函数程序后且在函数定义前未声明,因此会出现报错,将以上代码函数定义注释那里取消注释就起到函数的声明作用了。
2、函数的定义
注意:函数不可以嵌套定义,但可以嵌套调用。
1.C 中函数定义的一般形式为:
类型名 函数名(形参类型说明 形参) //函数首部
{ //函数体
说明语句;
执行语句;
}
定义说明事项:
(1)函数名必须是一个合法的标识符,并且不能与其他函数或变量名重名。
(2)类型名指定函数返回值的类型。如果定义时候没有指定函数类型,就会默认为 int 类型。无返回值的函数应该定义为 void 类型。
(3)形参类型说明表又称为形参列表。一般格式为:
(数据类型名1 形参名1,数据类型名2 形参名2……)
如果无参函数,则该形参类型说明表可以省略。
(4)其中的说明语句和执行语句构成函数体。函数体可以暂时没有任何语句,此时表示占一个空间,但无任何需要执行语句,可以之后进行语句补充。
例如:
prime()
{}
这里没有函数类型说明,没有形参类型说明表,也没有函数体,是一个最简单的 C 语言合法的函数。实际上该函数不执行任何操作。
2.C 语言定义程序示例:
利用二分法查找数字
#include<stdio.h>//二分法查找数字
int search(int m, int sz1, int brr[]);//函数的声明
int search(int m, int sz1, int brr[])//函数的定义
{
int left = 0;
int right = sz1 - 1;
int mid = 0;
while (left <= right)
{
mid = (left + right) / 2;
if (m>brr[mid])
{
left = mid + 1;
}
else if (m < brr[mid])
{
right = mid - 1;
}
else
{
return mid;
break;
}
}
if (left > right)
{
return -1;
}
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
int sz = sizeof(arr) / sizeof(arr[0]);
int k = 0;
scanf("%d", &k);
int ret = search(k, sz, arr);
if (ret == -1)
{
printf("Sorry,not found!\n");
}
else
{
printf("Congratulations on finding!\nNumber %d\n", ret);
}
return 0;
}
程序运行结果:
那么我们把以上代码拿来分析分析吧!看看下面的图:
五、函数的参数以及调用
1、形式参数和实际参数
函数之间数据传递包括个方面:
(1)数据从主调函数传递给被调函数(通过函数的参数来实现)。
(2)数据从被调函数返回到主调函数(通过函数的返回值来实现)。
1.实际参数(实参):
真实传给函数的参数叫实参;实参可以是:常量、变量、表达式、函数等。无论他是何种类型的量,在进行函数调用时,都必须要有确定的值,以便于把这些值传递给形参。
2.形式参数(形参):
形式参数是指函数名后括号中的变量,形式参数是在被调用的过程中才分配内存单元,在被调用完后就直接自动销毁。所以对形参的修改不会影响到实参。
3.相关规则和说明如下:
(1)形参定义时编译系统并不为其分配存储空间,也无初始值,只有在函数调用的时候临时分配存储空间,接受来自实参的值。函数调用结束,内存空间释放,值消失。
(2)实参可以是常量、变量、表达式和函数,但必须在函数调用之前有确定的值。
(3)实参和形参之间的值是单向传递的。因此,实参和形参必须类型相同,个数相等,一一对应。
(4)当函数调用时,实参传给形参,形参其实是实参的一份临时拷贝,对形参的修改,不会影响到实参。
2、函数的调用
注意:函数不可以嵌套定义,但可以嵌套调用。
1.普通调用的一般形式
函数名(实参列表);
//例如 max(a,b);
注意:若对于无参函数调用时候实参列表可以为空,但 () 不能省略。
2.传值调用和传址调用
传值调用:
实际上是把主调函数里的值赋值给被调函数,相当于拷贝,这时对形参的修改不会影响实参的值。
传址调用:
实际上时传值的一种特殊方式,只是它通过传递这个值的地址从而将其地址里存的值传递出去。这时形参与实参就会公用相同的地址,相当于是一个整体了,这时对形参改变就会改变实参。
程序示例:利用函数交换 a 和 b 的值
3.使用传值调用示范 (错误示范)
#include<stdio.h>//利用传值调用交换两个数
void swap(int m, int n);
void swap(int m,int n)
{
int t = 0;
t = m;
m = n;
n = t;
}
int main()
{
int a = 8, b = 24;
swap(a, b);
printf("%d %d", a, b);
return 0;
}
运行结果示例:
当然啦!根据上面的介绍,这种交换方法当然是行不通的啦!
4.使用传值调用示范 (正确操作)
#include<stdio.h>//利用函数传址调用交换两个数
void swap(int* m, int* n);
void swap(int* m,int* n)
{
int t = 0;
t = *m;
*m = *n;
*n = t;
}
int main()
{
int a = 8, b = 24;
swap(&a, &b);
printf("%d %d", a, b);
return 0;
}
运行结果:
六、函数的嵌套调用和链式访问
1、函数的嵌套调用
在 C 语言中,所有的函数定义都是平行的,不存在上一级和下一级的包含关系,正如上面所说的函数不能嵌套定义,但是可以嵌套调用。即在某一个函数执行过程中又可以调用另一个函数。也就是说函数执行不是执行完一个函数再去执行另一个函数,而是可以根据需要随时对其他函数进行调用。如下函数的嵌套调用分析图:
函数的调用是逐级调用,逐级返回。
2、函数嵌套调用程序示例
求圆环的面积。
#include<stdio.h>//求圆环的面积
#include<math.h>
#define PI 3.1415926 //宏定义 将PI的值定为3.1415926
float area(float r);
float area_ring(float a, float b); //函数的声明
float area(float r) //求圆面积的函数的定义
{
return (PI * r * r);
}
float area_ring(float a, float b) //求圆环面积的函数的定义
{
float s = 0;
s = fabs(area(a) - area(b));//fabs函数是起到求绝对值的作用
return s;
}
int main()
{
float r1 = 0, r2 = 0;
scanf("%f %f", &r1, &r2);
float ret = area_ring(r1, r2);
printf("%.2lf\n", ret);
return 0;
}
运行结果:
以上程序中就实现了函数的嵌套调用:
(1)一共有 main()、area() 和 area_ring() 三个函数,都是平行关系。
(2)程序先从 main() 函数开始执行,接下来进入 area_ring() 函数,在area_ring() 函数中又调用 area() 函数,area() 执行完毕后返回 area_ring() 函数进行执行,结束后又返回主函数,继续执行主函数后面的程序。
3、函数的链式访问
这里以 printf 函数为例:
#include<stdio.h>
int main()
{
int a = 10;
printf("%d", printf("%d", printf("%d", 10)));
return 0;
}
运行结果:
这里先由内部的 printf(“%d”,a) 打印出10;接下来第二层就会打印 10 的字符长度 ,因此打印出 2 ;同理第三层就会打印 2 的字符长度为 1.最终打印的就是 1021 啦!
七、函数的返回值
函数的返回值是指函数被调用、执行完毕后返回给主调函数的值。
1、函数的返回语句
一般形式
return 表达式;
功能:将表达式的值返回给主调函数。
2、返回语句说明
(1)函数内可以有多条返回语句,但返回语句的返回值只有一个。
(2)当函数不需要指明返回值时可以写成:
return;
(3)为了明确表示不带返回值的函数,可以用 void 来声明和定义函数。
(4)函数中有多个 return 语句时,只会执行一个,无论执行哪一个,都会返回到主调函数,并带回返回值。
结语
目前就归纳总结到这里吧!希望这些内容能给一些初学者带来帮助,如有不足或错误之处,希望大佬批评指正哈!
谢谢观看!再见啦!
以上代码均可运行,所用编译环境为 vs2019 ,运行时注意加上编译头文件#define _CRT_SECURE_NO_WARNINGS 1