
主函数是程序的入口,若主函数中调用了其它函数,将进入其它函数执行其功能,执行完毕之后再继续执行主函数中内容。程序执行流程如下图所示
1 函数调用的一般形式
格式:
函数名(实参表列)
说明:
(1) 如果调用无参函数,则实参列表没有,但是括号不可省略。
(2) 形参和实参之间为一一对应,故它们之间个数必须一致、类型一致或兼容,且实参之间以“,”隔开。
【例8.3.1】函数调用示例。
#include <stdio.h>
int f(int a,int b)
{
int c;
printf("a=%d,b=%d\n",a,b);
if(a>b) c=1;
else if(a==b) c=0;
else c=-1;
return(c);
}
void main( )
{
int i=2,p;
p=f(i,++i);
printf("%d\n",p);
return;
}
2 函数调用方式
函数调用的三种方式:
(1) 函数语句:将函数调用作为一条语句,函数不带返回值,只完成某项功能操作。
如第一节中提到的函数,执行时可以只有:printstar();其功能只是打印一系列’*’号。
(2) 函数表达式:函数出现在一个表达式中,函数带回一个确定值以参加表达式的运算。
c=2*max (a,b);
(3) 函数参数:函数调用作为一个函数的实参。如:
m=max (a,max (b,c));
或 printf(" %d",max(a,b));
3 对被调用函数的声明
在一个函数中调用另一个函数需要的条件:
(1) 被调用函数必须是已存在的函数;
(2) 如使用库函数,一般应在本文件开头用#include命令,如:#include "stdio.h";
(3) 如使用用户自己定义的函数,且该函数与调用它的函数在同一个文件中。但如果被调用函数的位置出现在主调用函数的后面,一般还应在主函数中对被调用函数作声明(说明)。声明的作用是把函数名、函数参数的个数和参数类型这些信息通知编译系统,以便对被调用函数据的编译检查。的返回值类型加以说明,例如:类型标识符、被调函数的函数名;
(4) 对第3条,以下几种情况可以不在调用函数中加类型说明,
①如函数的值是整型或字符型(系统按整型对待);
②如被调用函数的定义出现在主调函数之前,可以不加说明;
③如已在所有函数定义之前,在文件开头、函数的外部已说明了函数类型。
请看下面两个例子。
【例8.3.2】输入二个实数,求其和。
#include <stdio.h>
void main( )
{
float a,b,c;
scanf(" %f,%f ",&a,&b);
c=add(a,b);
printf(" sum is %f ",c);
return 0;
}
float add(float x, float y)
{
float z;
z=x+y;
return(z);
}
该程序在编译过程会报错,原因是程序进行编译时是从上到下逐行进行的,当编译到第5行时,编译系统不能确定add是否为函数名,因为具体的函数定义还在下面。
有二种方法可以避免这种情况发生。一是将add()函数定义放在主调用函数main()之前;二是在主调用函数main()内函数调用语句之前对被调用函数add()作声明。第二种情况程序调整如下:
#include <stdio.h>
void main( )
{
float a,b,c;
float add(float x, float y); //对被调用函数add()作声明
scanf("%f,%f",&a,&b);
c=add(a,b);
printf("sum is %f\n",c);
return ;
}
float add(float x, float y) //该行称为函数原型
{
float z;
z=x+y;
return(z);
}
运行结果:
![]()
可能发现,函数的声明就是函数定义的第一行后面加一个分号。我们把函数定义的首行称为函数原型。因为函数的形参名称只是一种形式名称,用哪一个名称都可以,所以对被调用函数的声明语句中,形参名还可省略。如上面的声明语句可以写为:
float add(float, float );
如果在文件的开头即所有函数之前,已对本文件中所调用的函数进行了声明,则在各函数中不必对其所调用的函数再作声明。
【例8.3.3】设计一个简单算术运算的演示程序,求两个整数的加、减和乘运算的结果。
解题思路:
分别设计三个函数用来实现求两个数的加、减和乘运算的结果,以及一个菜单功能函数void menu(),并将它们放在主函数的下面,在主函数上面增加对上述四个函数的原型声明(虽然前三个函数返回值都是整型,可以省略声明,但建议养成这样的习惯),在主函数设计循环语句实现完成对算术运算函数的调用,直到输入0退出并结束程序。
程序代码:
#include<stdio.h>
int add(intx,int y); //以下3行在所有函数之前,且在函数外部
int sub(intx,int y);
int mul(int x,int y);
void menu();
void main( ) //在main函数中要调用下面的三个函数,不必再对它们进行声明
{
int i,a,b;
menu();
printf("please choiceoperataion:");
scanf("%d",&i);
do
{
switch(i)
{
case 1:
printf("pleaseinput two integer:");
scanf("%d,%d",&a,&b);
printf("%d+%d=%d\n",a,b,add(a,b));
break;
case 2:
printf("pleaseinput two int:");
scanf("%d,%d",&a,&b);
printf("%d-%d=%d\n",a,b,sub(a,b));
break;
case 3:
printf("pleaseinput two int:");
scanf("%d,%d",&a,&b);
printf("%d*%d=%d\n",a,b,mul(a,b));
break;
}
menu();
printf("please choiceoperataion:");
scanf("%d",&i);
}while(i!=0);
return ;
}
void menu()
{
printf("1.add 2.sub 3.multply 0.quit\n");
}
int add(int x,int y)
{
int z;
z=x+y;
return(z);
}
int sub(int x,int y)
{
int z;
z=x-y;
return(z);
}
int mul(int x,int y)
{
int z;
z=x*y;
return(z);
}
运行结果:

4 嵌套调用
在调用一个函数的过程中,又调用另一个函数,这种现象称为函数的嵌套调用。
嵌套调用的形式
可以用下图来描述嵌套的调用。

在上图中,main函数调用了函数a,而函数a又调用了函数b,所以main函数相当于间接调用了b函数,这样就出现了函数的嵌套调用。在上图中,括号中的数字顺序也就是程序的执行流程顺序。
下面用例8.4.1来解释函数的嵌套调用。
【例8.4.1】用弦截法求方程的根。x3-5x2+16x-80=0

解题思路:
根据上图所示,按以下步骤进行:
(1) 先取两点x1,x2,计算f(x1)和f(x2),如f(x1)*f(x2)<0,则此两点间必有根,否则重新选取,直至满足此要求为止;
(2) 计算(x1,f(x1))和(x2,f(x2))连线与X轴交点x,计算f(x);
(3) 如f(x)*f(x1)<0,则根在x1与x之间,此时令x2=x,计算f(x2),返回上步(2);否则根在x与x2之间,令x1=x,计算f(x1),返回上步(2);
(4) 重复2、3,直至|f(x)|<10-6为止,至此可认为此时的x为所求。
程序代码:
#include <stdio.h>
#include "math.h"
float f(float x)
{
float y;
y=((x-5.0)*x+16.0)*x-80.0;
return(y);
}
float xpoint(float x1,float x2)
{
float y;
y=(x1*f(x2)-x2*f(x1))/(f(x2)-f(x1));
return(y);
}
float root(float x1,float x2)
{
float x,y,y1;
y1=f(x1);
do
{
x=xpoint(x1,x2);
y=f(x);
if(y*y1>0)
{
y1=y;
x1=x;
}
else x2=x;
}while(fabs(y)>=0.0001);
return(x);
}
void main()
{
float x1,x2,f1,f2,x;
do
{
printf(" input x1,x2:\n ");
scanf("%f,%f",&x1,&x2);
f1=f(x1);f2=f(x2);
}while(f1*f2>=0);
x=root(x1,x2);
printf(" A root of equation is %8.4f\n " ,x);
return ;
}
本例中除main函数外又定义了f( )、xpoint( )、root( )三个函数,其功能分别是求函数值、弦与x轴的交点、求根的迭代过程。这里main( )函数调用root函数,而root函数调用xpoint函数,xpoint函数又调用f函数。
关于函数嵌套调用的几点说明:
(1) 各函数是相互独立的,并不相互从属。
(2) 程序从main( )函数开始执行。
(3) 如自定义函数定义在main( )之前,则在main( )中不必对这些函数作进行声明。
*EASYX图形编程.用函数来实现高效率的绘图
实际中有许多类似的图案,如果一一单独绘制,太麻烦。于是,我们需要一个公用的绘制过程,就是函数。
例如,我们需要画5个三角形,位于不同的位置。我们可以将绘制单个三角形的过程写成函数,函数内是一个独立的程序段,这个绘制过程很简单。
然后,在需要绘制的时候,调用这个函数即可。可以通过参数来解决细微差异(图案的坐标、颜色等),例如:
#include<graphics.h>
#include <conio.h>
// 在坐标 (x,y) 处,用颜色 c 绘制三角形
void sanjiaoxing(int x, int y, int c)
{
// 设置画线颜色
setcolor(c);
// 画三角形的三条边
line(x, y, x+50, y);
line(x, y, x, y+50);
line(x+50, y, x, y+50);
}
void main()
{
initgraph(640, 480); // 初始化图形窗口
sanjiaoxing(100, 100, RED);
sanjiaoxing(120, 160, BLUE);
sanjiaoxing(140, 220, GREEN);
sanjiaoxing(160, 120, BLUE);
sanjiaoxing(160, 160, GREEN);
sanjiaoxing(220, 140, GREEN);
getch(); // 按任意键继续
closegraph(); // 关闭图形窗口
}
再结合循环等控制条件,就能绘制更复杂漂亮的图案了。试试运行下面程序,理解一下函数的用处:
#include<graphics.h>
#include <conio.h>
void sanjiaoxing(intx, int y, int color)
{
// 设置画线颜色
setcolor(color);
// 画三角形的三条边
line(x, y, x+10, y);
line(x, y, x, y+10);
line(x+10, y, x, y+10);
}
void main()
{
initgraph(640, 480); // 初始化图形窗口
for(int x=0; x<640; x+=10)
for(int y=0; y<480; y+= 10)
sanjiaoxing(x, y, RGB(x*255/640, y*255/480, 0));
getch(); // 按任意键继续
closegraph(); // 关闭图形窗口
}

