例
#include <stdio.h>
double fact(int n);
int main()
{
int i,n;
double sum;
printf("Enter n");
scanf("%d",&n);
sum=0;
for(i=1;i<=n;i++)
{sum=sum+fact(i);
}
printf("1!+2!+3!...+%d!=%.0f\n",n,sum);
return 0;
}
double fact(int n)
{
int i;
double result;
if(n<0){
return 0;
}
result=1;
for(i=1;i<=n;i++)
{result=result*i;
}
return result;
}
上面这个程序使用自定义函数,现在讨论自定义函数。
自定义函数
函数:函数是一个完成特定工作的独立程序模块,包括库函数和自定义函数两种。例如,scanf(),printf()等为库函数,由C语言系统提供定义,编程时只要直接调用即可;而上面程序中的fact()函数,需要用户自己定义,属于自定义函数。
函数定义的一般形式为:
函数类型 函数名字(形式参数表) //函数头
{ 函数实现过程
}
讨论:
1.函数头
函数头由函数类型,函数名和形式参数表(以下简称形参表)组成,位于函数定义的第一行。函数头中,函数名是函数整体的称谓,需要一个合法的标识符表示。函数类型指函数结果返回的类型,一般与return语句中的表达式的类型一致。形参表中给出函数计算所用的相关已知形式,以类似变量定义的形式给出,其格式为:
类型1 形参1,类型2 形参2.……,类型n 形参n
形参表中各个形参之间用逗号隔开,每个形参前面的类型必须分别写明。函数的形参的数量可以是一个,也可以多个,或者没有形参。
2.函数体
函数体体现函数的实现过程,由一对大括号内的若干条语句组成,用以计算,或完成特定工作,并用return语句返回运算的结果。
讨论,函数的调用
1.函数调用过程
任何C语言执行,首先从主函数main()开始,如果遇到某个函数调用,主函数被暂停执行,转而执行相应的函数,该函数执行完后将返回主函数,然后再从原先暂停的位置继续执行。
现在分析函数的调用过程。
(1)main()函数运行到
volume=cylinder(radius,height);
时,先调用函数cylinder()函数,暂停main()函数,将变量radius和height的值传递给形参r和h;
(2)计算机转到执行cylinder()函数,形参r和h接受radius和height的值;
(3)执行cylinder()函数中的语句,计算圆柱体积;
(4)函数cylinder()执行“return result:”,结束函数运行,带着函数的结果result,返回到main()函数中停止调用它的地方。
(5)计算机从先前暂停的位置继续执行,将返回值赋予给变量volume,输出体积。
2.函数的调用形式
函数的一般调用形式:
函数名(实际参数表)
实际参数(简称实参)可以是常量,变量和表达式。例如,cylinder()中,使用变量radius和height作为实参
对于实现计算功能的函数,函数调用通常有以下两种情况。
(1)赋值语句
volume=cylinder(radius,height);
(2)输出函数的参数
printf("%f",cylinder(radius,height) );
3.参数传递
定义函数时,位于其首部的参数被称为形参,如r和h。主调函数的参数被称为实参,如radius和height。形参除了能接受实参的值外,使用方法与普通方法类似。形参和实参必须一一对应,两者数量相同,类型尽量一致。程序运行到函数调用时,实参的值依次传给形参,这就是参数传递。
如:
double cylinder(double r,double h)
指明两个形参r和h。而main()函数中:
volume=cylinder(radius,height);
说明radius和height是实参。函数调用时,实参radius和height的值将被依次传给形参r和h。
函数的形参必须是变量,用于接收实参传过来的值;而实参可以是常量,变量或表达式,其作用是把常量,变量或表达式的值传给形参。如果实参是变量,它与所对应的形参是两个不同的变量。实参是主调函数的,形参是自定义函数,这两者可以同名,也可以不同名。
按照C语言的规定,在参数传递过程中,将实参传给形参。这种参数传递是单向的,只允许实参把值复制给形参,形参的值即使在函数中改变了,也不会反过来影响实参。
4.函数结果返回
函数结果返回的形式如下:
return 表达式;
先求解表达式的值,在返回其值。一般情况下表达值的类型与函数值类型相一致,如果两者不一致,以函数类型为准。return语句的作用有两个:一是结束函数的运行;二是带着运算结果(表达式的值)返回主调函数。
在主题函数中,return语句中的表达式反映了函数运算的结果,通过return语句将该结果回送给主调函数。但return语句只能返回一个值,如果函数产生了多个运算结果,将无法通过return送回。但在后面会介绍使用全局变量或指针实现函数的多个结果返回。
return语句只能返回一个值
5.函数原型声明
C语言要求函数先定义后使用,就像变量先定义后使用一样。如果自定义函数被放在主调函数后面,就需要在函数调用前,加上函数原型声明(或者函数声明)。
函数声明的目的的主要是说明函数的类型和参数的情况,以保证程序编译时能判断对该函数的调用是否正确。函数声明的一般格式为:
函数类型 函数名(参数表);
即与函数定义中的第一行(函数头)相同,并以分号结束。
虽然可以将主调函数放在被调函数的后面,从而不需做声明。但考虑到函数的执行顺序,在编程时一般都把主函数写到最前面,使整个程序的结构和功能开门见山地呈现在读者面前,然后通过函数声明解决函数先调用后定义的矛盾。
讨论变量
局部变量和全局变量
1.局部变量
C语言中把定义在函数内部的变量称为局部变量,局部变量的有效作用范围局限于所在的函数内部,形参是局部变量。
使用局部变量可以避免各个函数之间的变量相互干扰。如,函数complex_prod()和complex_add()使用了同名的形参,且与主函数实参变量也同名,但由于分属不同函数,它们有各自不同的变量实体和使用范围,不会相互干扰。
处理作用于函数的局部变量外,C语言还允许定义作用于复合语句中的局部变量,其有效作用范围被局限于复合语句中,一般作用小范围内的临时变量。
2.全局变量
定义在函数外而不属于任何含税的变量称为全局变量。全局变量的作用范围是从定义开始到程序所在文件的结束,它对作用范围内所有函数都起作用。
全局变量的定义格式与局部变量完全一致,只是定义位置不在函数内,它可以定义在程序的头部,也可以定义在两个函数中间或者程序尾部,只要在函数外部即可。
由于全局变量和局部变量的作用域不同,允许它们同名。当某函数的局部变量与全局变量同名时,在该函数中全局变量不起作用,而由局部变量起作用。对于其他不存在同名变量的函数,全局变量仍然有效。同样,当函数局部变量与复合语句的内部的局部变量同名时,则以复合语句为准。