C语言 函数

来源:互联网 发布:为什么衍生网络主播 编辑:程序博客网 时间:2024/06/05 06:26

为什么要使用函数

C程序中,如果程序的功能比较多,规模比较大,把所有的程序都写在一个主函数中(main函数),就会使主函数变得庞杂,头绪不清了,是阅读和维护程序比较困难。此外,有时候程序中要多次实现某一功能,就需要多次重复编写实现此功能的程序代码

因此,人们自然会想到采用“组装”的办法来简化程序设计的过程。就如同组装计算机一样,事先生产好各种部件,在最后组装机计算机时,用到什么就从仓库里面取出什么,而不是用到了在临时生产。这就是模块化程序设计的思路

可以事先编好一批常用的函数来实现各种不同的功能。“函数”是从英文“function”翻译过来的,其实,function 在英文中的意思既是“函数”,也是“功能”。从本质上来说,函数就是用来完成一定的功能的。这样,对函数的概念就很好理解了,所谓函数名就是给该功能起一个名字,如果该功能是用来实现数学运算的,就是数学函数。每一个函数用来实现一个特定的功能,函数的名字应反映其代表的功能

怎样定义函数

定义函数应包括一下几个内容:

(1):指定函数的名字,以便以后按名调用

(2):指定函数的类型,即函数返回值的类型

(3):指定函数的参数的名字和类型,以便在调用函数时向他们传递数据。对于无参函数不需要这项

(4)指定函数应当完成什么操作,也就是函数是做什么的,即函数的功能。这是最重要的,是在函数体中解决的

   定义函数的方法:

        1、定义无参函数:函数名后面的括号中是空的,没有任何参数。定义无参函数的一般形式为:

           类型名 函数名(){

函数体

类型名 函数名(void){

函数体

函数名后面括号内的void表示“空”,即函数没有参数

2、定义有参函数

   类型名 函数名(形式参数表列){

函数体

}                                                                                           3、定义空函数

          类型名 函数名(){}

为什么要定义空函数呢?在程序设计中往往根据需要确定若干个模块,分别由一些函数来实现。而在第一阶段只设计最基本的模块,其它一些功能或锦上添花的功能则在以后需要时陆续补上。在编写程序的开始阶段,可以在将来准备扩充的功能的地方写上一个空函数,只是这些函数暂时还没有编写好,先用空函数占一个位置,等以后扩充程序功能时用一个编号的函数代替它。这样,程序的结构清楚,可读性好,以后扩充新功能方便,对程序结构影响不大。空函数在程序设计中常常是有用的

调用函数:

定义函数的目的是为了调用此函数

1、调用函数的形式

a) 函数名(实参表列)如果是调用无参函数,则“实参列表”可以没有,但括号不能省略

b) 函数调用语句,把函数调用单独作为一个语句,不要求函数待会值,只要求函数完成一定的操作

c) 函数表达式,函数调用出现在另一个表达式中,如“c=max(a,b);",max(a,b)是一次函数调用,它是赋值表达式中的一部分,这时要求函数待会一个确定的值以参加表达式的运算。例如”c=2*max(a,b);

d) 函数参数:函数调用作为另一个函数调用时的实参

2、函数调用时的数据传递

a)  形式参数和实际参数:在调用有参函数时,主调函数和被调函数之间有数据传递关系。在定义函数时函数名后面括号中的变量名称中的参数称为|“形式参数(简称“形参”)”或“虚拟参数”。在主调函数中调用一个函数时,函数名后面括号中的参数成为“实际参数”(简称“实参”)。在实际参数中可以是常量、变量或表达式

b) 实参和形参之间的数据传递:在调用函数过程中,系统会把实参的值传递给被调用函数的形参。或,形参从实参得到一个值,该值在函数调用期间有效,可以参加该函数的运算

如下例:输入两个数,判断大小。

#include "stdafx.h"

int main()

{

int max(int x,int y);

int a,b,c;

printf("输入两个整数:\n");

scanf("%d,%d",&a,&b);

c=max(a,b);

printf("最大的是:%d",c);

return 0;

}

int max(int x,int y){

int z;

z=x>y?x:y;

return(z);

}

3、函数的调用过程

a)在定义函数中指定的形参,在为出现函数调用时他们并不占内存中的存储单元。在发生函数调用时,函数的形参被临时分配内存单元

b)将实参对应的值传递给形参

c)在执行函数期间,如形参已经有值,就可以利用形参进行有关的运算

d)通过return语句将函数值带回到主调函数,如果函数不需要返回值,则不需要return语句,这是函数单类型应该定义为void 类型

e)调用结束,形参单元呗释放。注意:实参单元仍保留并维持原值,没有改变。如果在执行一个被调用函数时,形参的值发生改变,不会改变主调函数的实参的值

f)实参想形参的数据传递是“值传递”,单向传递,只能由实参传递给形参,而不能由形参传递给实参。实参和形参在内存中占有不同的存储单元,实参无法得到形参的值

4、函数的返回值

a)函数的返回值是通过函数中的return语句获得的。Return语句将呗调用函数中的值带回到主函数中去。如果需要从被调函数待会一个函数值(供主调函数使用)被调函用函数中必须包含return语句。如果不需要从被调用函数待会函数值可以不要return语句

b)函数值的类型:既然函数有返回值,这个值当然应属于某一个确定的类型,应当在定义函数时指定函数值的类型

c)在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致。如果函数值的类型和return语句中表达式的值不一致,则以函数类型为准。对数值类型数据,可以自动进行类型转换

d)对于不带回值的函数,应当用定义函数为“void类型”(空类型)。这样,系统就保证不使用函数待会任何值,即进制在调用函数中使用被调函数的返回值。此时在函数体中不得出现return语句

对被调用函数的声明和函数原型

在一个函数中调用另一个函数需具备如下条件:

1)首先被调用的函数必须是已经定义的函数(库函数或用户自己定义的函数)

2)如果使用库函数,应该在本文件开头用#include指令将调用有关库函数时所需要得到的信息“包含”到本文件来,例如:#include<stdio.h>

3)如果使用用户自己定义的函数,该函数的位置在调用它的函数(即主调函数)的后面(同一个文件中),应该在主调函数中对呗调用的函数作声明。声明的作用是把函数名、函数参数的个数和参数类型等信息通知编译系统

如下例:输入两个整数,用一个函数求出他们只和

#include "stdafx.h"

int main()

{

int add(int x,int y);

int a,b,c;

printf("输入两个整数:\n");

scanf("%d,%d",&a,&b);

c=add(a,b);

printf("和是:%d",c);

return 0;

}

int add(int x,int y){

int z;

z=x+y;

return(z);

}

函数的嵌套调用·

C语言的函数定义是相互平行、独立的,即在定义函数时,一个函数内不能在定义另一个函数,也就是不能嵌套定义,但可以嵌套调用函数,即在调用一个函数的过程中,有调用另一个函数

如下:输入4个整数,找出其中最大的数。用函数嵌套处理

#include "stdafx.h"

int main()

{

int max4(int a,int b,int c,int d);

int a,b,c,d,max;

printf("输入四个整数:\n");

scanf("%d,%d,%d,%d",&a,&b,&c,&d);

max = max4(a,b,c,d);

printf("最大的是:%d",max);

return 0;

}

int max4(int a,int b,int c,int d){

int max2(int a,int b);

int m;

m=max2(a,b);

m=max2(m,c);

m=max2(m,d);

return(m);

}

int max2(int a,int b){

if(a>=b){

return a;

}else{

return b;

}

}

函数的递归调用

在调用一个函数的过程中又出现直接或间接调用该函数本身,称为函数的递归调用。C语言的特点之一就是允许函数的递归调用。

例:求n! (n<16)

#include "stdafx.h"

int main()

{

int fac(int n);

int n;

int y;

printf("输入一个整数\n");

scanf("%d",&n);

y=fac(n);

printf("%d!=%d\n",n,y);

return 0;

}

int fac(int n){

int f;

if(n<0){

printf("n<0,错误");

}else if(n==0||n==1){

f=1;

}else{

f=fac(n-1)*n;

}

return (f);

}

数组作为函数参数

调用有参函数时,需要提供实参》实参可以是变量、常量或表达式。数组元素的作用与变量相当,一般来说,凡事变量可以出现的地方,都可以用数组元素代替。因此,数组元素也可以用作函数实参,其用法与变量相同,想形参传递数组元素的值。此外,数组名也可以做实参和形参,传递的是数组第一个元素的地址

1)数组元素做函数实参:数组元素可以用作函数实参,不能用作形参。因为形参是在函数呗调用时临时分配存储单元的,不可能为一个数组元素单独分配存储单元(数组是一个整体,在内存中占连续的一段存储单元)。在用数组元素做函数实参时,把实参的值传给形参,是“值传递”方式。数据传递的方向是从实参传到形参,单向传递。

例:输入10个数,要求输出其中最大的元素和该数是第几个数

#include "stdafx.h"

int main()

{

int max(int x,int y);

int a[10],m,n,i;

printf("输入十个整数\n");

for(i=0;i<10;i++){

scanf("%d",&a[i]);

printf("\n");

}

for(i=1,m=a[0],n=0;i<10;i++){

if(max(m,a[i])>m){

m=max(m,a[i]);

n=i;

}

}

printf("最大数是%d\n是第%d个数\n",m,n+1);

return 0;

}

int max(int x,int y){

return(x>y?x:y);

}

2)数组名作函数参数:除了出租元素作为函数参数外,还可以用数组名作函数参数(包括实参和形参)。注意:用数组元素做实参时,向形参变狼传递的是数组元素的值,而用数组名做函数实参时,向实参(数组名或指针变量)传递的是数组首元素的地址

例:有一个一维数组score,输入10个学生成绩,求平均成绩

#include "stdafx.h"

int main()

{

float average(float array[10]);

float score[10],aver;

int i;

printf("输入十个数\n");

for(i=0;i<10;i++){

scanf("%f",&score[i]);

printf("\n");

}

aver = average(score);

printf("平均成绩是:%5.2f\n",aver);

return 0;

}

float average(float array[10]){

int i;

float aver,sum=array[0];

for(i=1;i<10;i++){

sum =sum+array[i];

}

aver = sum/10;

return(aver);

}

3)多维数组名做函数参数:多维数组元素可以做函数参数,可以用多位数组名做函数的实参和形参,在呗调用函数中对形参数组定义时可以指定每一维的大小,也可以省略第一位的大小说明

例:有一个 3*4的矩阵,求所有元素中的最大值

#include "stdafx.h"

int main()

{

int max_value(int array[][4]);

int a[3][4]={{1,3,5,7},{2,4,6,8},{12,23,32,13}};

printf("最大值是:%d\n",max_value(a));

return 0;

}

int max_value(int array[][4]){

int i,j,max;

max= array[0][0];

for(i=0;i<3;i++){

for(j=0;j<4;j++){

if(array[i][j]>max){

max=array[i][j];

}

}

}

return max;

}



原创粉丝点击