《(6.1.6)--第7章C语言程序设计.ppt》由会员分享,可在线阅读,更多相关《(6.1.6)--第7章C语言程序设计.ppt(77页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、7 7 7 7用函数实现模块化程序设计第第第第章章章章为什么要用函数V VS.S.使用函数可使程序清晰、精炼、简单、灵活。函数就是功能。每一个函数用来实现一个特定的功能。函数名应反映其代表的功能。在设计较大程序时,往往把它分为若干个程序模块,每一个模块包括一个或多个函数,每个函数实现一个特定的功能。一个C程序可由一个主函数和若干个其他函数构成。由主函数调用其他函数,其他函数也可以互相调用。为什么要用函数【例7.1】想输出以下的结果,用函数调用实现。#include int main()void print_star();/声明print_star函数void print_message();/
2、声明print_message函数print_star();/调用print_star函数print_message();/print_message函数print_star();/调用print_star函数return 0;void print_star()/定义print_star函数printf(*n);/输出一行*号void print_message()/定义print_message函数printf(How do you do!n);/输出一行文字信息print_star和print_message都是用户定义的函数名,分别用来输出一排“*”号和一行文字信息。在定义这两个函数时指
3、定函数的类型为void,意为函数无类型,即无函数值,也就是说,执行这两个函数后不会把任何值带回main函数。在程序中,定义print_star函数和print_message函数的位置是在main函数的后面,在这种情况下,应当在main函数之前或main函数中的开头部分,对以上两个函数进行“声明”。函数声明函数声明的作用是把有关函数的信息(函数名、函数类型、函数参数的个数与类型)通知编译系统,以便在编译系统对程序进行编译时,在进行到main函数调用print_star()和print_message()时知道它们是函数而不是变量或其他对象。此外,还对调用函数的正确性进行检查(如类型、函数名、参
4、数个数、参数类型等是否正确)。为什么要用函数(1)一个C程序由一个或多个程序模块组成,每一个程序模块作为一个源程序文件。较大的程序,可分别放在若干个源文件中。这样便于分别编写和编译,提高调试效率。一个源程序文件可以为多个C程序共用。(2)一个源程序文件由一个或多个函数以及其他有关内容(如指令、数据声明与定义等)组成。一个源程序文件是一个编译单位,在程序编译时是以源程序文件为单位进行编译的,而不是以函数为单位进行编译的。(3)C程序的执行是从main函数开始的,如果在main函数中调用其他函数,在调用后流程返回到main函数,在main函数中结束整个程序的运行。(4)所有函数都是平行的,即在定义
5、函数时是分别进行的,是互相独立的。一个函数并不从属于另一个函数,即函数不能嵌套定义。函数间可以互相调用,但不能调用main函数。main函数是被操作系统调用的。(5)从用户使用的角度看,函数有两种。库函数,它是由系统提供的,用户不必自己定义,可直接使用它们。应该说明,不同的C语言编译系统提供的库函数的数量和功能会有一些不同,当然许多基本的函数是共同的。用户自己定义的函数。它是用以解决用户专门需要的函数。(6)从函数的形式看,函数分两类。无参函数。在调用无参函数时,主调函数不向被调用函数传递数据。有参函数。在调用函数时,主调函数在调用被调用函数时,通过参数向被调用函数传递数据。定义函数为什么定义
6、函数定义函数应包括以下几个内容:(1)指定函数的名字,以便以后按名调用。(2)指定函数的类型,即函数返回值的类型。(3)指定函数的参数的名字和类型,以便在调用函数时向它们传递数据。对无参函数不需要这项。(4)指定函数应当完成什么操作,也就是函数是做什么的,即函数的功能。这是最重要的,是在函数体中解决的。C语言要求,在程序中用到的所有函数,必须“先定先定义,后使用,后使用”。定义函数的方法类型名型名函数名函数名()函数体函数体函数名后面括号内的void表示“空”,即函数没有参数。函数体包括声明部分声明部分和语句部分句部分。在定义函数时要用“类型标识符”(即类型名)指定函数值的类型,即指定函数带回
7、来的值的类型。定义无参函数类型名型名函数名函数名(void)函数体函数体或类型名型名函数名函数名(形式参数表列形式参数表列)函数体函数体定义有参函数int max(int x,int y)int z;/声明部分z=xy?x:y;/执行语句部分return(z);类型名型名函数名函数名()定义空函数函数体为空,什么也不做。调用函数函数调用的形式函数名函数名(实参表列参表列)print_star();/调用无参函数c=max(a,b);/调用有参函数1.函数函数调用用语句句把函数调用单独作为一个语句。如printf_star();这时不要求函数带回值,只要求函数完成一定的操作。2.函数表达式函数表
8、达式函数调用出现在另一个表达式中,如c=max(a,b);这时要求函数带回一个确定的值以参加表达式的运算。3.函数参数函数参数函数调用作为另一个函数调用时的实参。如m=max(a,max(b,c);,又如:printf(%d,max(a,b);形式参数和实际参数在调用有参函数时,主调函数和被调用函数之间有数据传递关系。在定义函数时函数名后面括号中的变量名称为“形式参数形式参数”(简称“形参”)或“虚拟参数”。在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数参数”(简称“实参”)。实际参数可以是常量、变量或表达式,但要求它们有确定的值。实参与形参的类型应相同或赋值兼容。赋值兼容是
9、指实参与形参类型不同时能按不同类型数值的赋值规则进行转换。实参和形参间的数据传递【例7.2】输入两个整数,要求输出其中值较大者。要求用函数来找到大数。#include int main()int max(int x,int y);/对max函数的声明int a,b,c;printf(please enter two integer numbers:);/提示输入数据scanf(%d,%d,&a,&b);/输入两个整数c=max(a,b);/调用max函数,有两个实参。大数赋给变量cprintf(max is%dn,c);/输出大数creturn 0;int max(int x,int y)/定
10、义max函数,有两个参数int z;/定义临时变量zz=xy?x:y;/把x和y中大者赋给zreturn(z);/把z作为max函数的值带回main函数定义函数,名为max,函数类型为int。指定两个形参x和y,形参的类型为int。主函数中包含了一个函数调用max(a,b)。max后面括号内的a和b是实参。a和b是在main函数中定义的变量,x和y是函数max的形式参数。通过函数调用,在两个函数之间发生数据传递,实参a和b的值传递给形参x和y,在max函数中把x和y中的大者赋给变量z,z的值作为函数值返回main函数,赋给变量c。c=max(a,b);(main函数)int max(int x
11、,int y)(max函数)int z;z=xy?x:y;return(z);在调用函数过程中发生的实参与形参间的数据传递称为“虚虚实结合合”。函数调用的过程(1)在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元。在发生函数调用时,函数的形参才被临时分配内存单元。(2)将实参的值传递给对应形参。(3)在执行函数期间,由于形参已经有值,就可以利用形参进行有关的运算。(4)通过return语句将函数值带回到主调函数。应当注意返回值的类型与函数类型一致。如果函数不需要返回值,则不需要return语句。这时函数的类型应定义为void类型。(5)调用结束,形参单元被释放。注意:实参
12、单元仍保留并维持原值,没有改变。如果在执行一个被调用函数时,形参的值发生改变,不会改变主调函数的实参的值。因为实参与形参是两个不同的存储单元。注意实参向形参的数据传递是“值传递”,单向传递,只能由实参传给形参,而不能由形参传给实参。实参和形参在内存中占有不同的存储单元,实参无法得到形参的值。函数的返回值(1)函函数数的的返返回回值是是通通过函函数数中中的的return语句句获得得的的。一个函数中可以有一个以上的return语句,执行到哪一个return语句,哪一个return语句就起作用。return语句后面的括号可以不要,如“return z;”与“return(z);”等价。return后
13、面的值可以是一个表达式。(2)函数函数值的的类型。型。函数值的类型在定义函数时指定。(3)在定在定义函数函数时指定的函数指定的函数类型一般型一般应该和和return语句中的表达式句中的表达式类型一致。型一致。如果函数值的类型和return语句中表达式的值不一致,则以函数类型为准。对数值型数据,可以自动进行类型转换。即函数函数类型决定返回型决定返回值的的类型型。(4)对于于不不带回回值的的函函数数,应当当用用定定义函函数数为“void类型型”(或称“空类型”)。这样,系统就保证不使函数带回任何值,即禁止在调用函数中使用被调用函数的返回值。此时在函数体中不得出现return语句。通常,希望通过函数
14、调用使主调函数能得到一个确定的值,这就是函数函数值(函数的返回值)。int max(float x,float y)/函数值为整型char letter(char c1,char c2)/函数值为字符型double min(int x,int y)/函数值为双精度型函数的返回值【例7.3】将例7.2稍作改动,将在max函数中定义的变量z改为float型。函数返回值的类型与指定的函数类型不同,分析其处理方法。max函数的形参是float型,实参也是float型,在main函数中输入给a和b的值是1.5和2.6。在调用max(a,b)时,把a和b的值1.5和2.6传递给形参x和y。执行函数max中
15、的条件表达式“z=xy?x:y”,使得变量z得到的值为2.6。现在出现了矛盾:函数定义为int型,而return语句中的z为float型,要把z的值作为函数的返回值,二者不一致。怎样处理呢?按赋值规则处理,先将z的值转换为int型,得到2,它就是函数得到的返回值。如果将main函数中的c改为float型,用%f格式符输出,输出2.000000。因为调用max函数得到的是int型,函数值为整数2。#include int main()int max(float x,float y);float a,b;int c;scanf(%f,%f,&a,&b);c=max(a,b);printf(max
16、is%dn,c);return 0;int max(float x,float y)float z;/z为实型变量z=xy?x:y;return(z);对被调用函数的声明和函数原型在一个函数中调用另一个函数(即被调用函数)需要具备如下条件:(1)首先被调用的函数必须是已经定义的函数(是库函数或用户自己定义的函数)。(2)如果使用库函数,应该在本文件开头用#include指令将调用有关库函数时所需用到的信息“包含”到本文件中来。(3)如果使用用户自己定义的函数,而该函数的位置在调用它的函数(即主调函数)的后面(在同一个文件中),应该在主调函数中对被调用的函数作声明(declaration)。声明
17、的作用是把函数名、函数参数的个数和参数类型等信息通知编译系统,以便在遇到函数调用时,编译系统能正确识别函数并检查调用是否合法。对被调用函数的声明和函数原型【例7.4】输入两个实数,用一个函数求出它们之和。函数的声明和函数定义中的第1行(函数首部)基本上是相同的,只差一个分号(函数声明比函数定义中的首行多一个分号)。函数的首行(即函数首部)称为函数原型函数原型(function prototype)。因为在函数的首部包含了检查调用函数是否合法的基本信息(它包括了函数名、函数值类型、参数个数、参数类型和参数顺序),因此,在函数调用时检查函数原型是否与函数声明一致。这样就能保证函数的正确调用。#in
18、clude int main()float add(float x,float y);/对add函数作声明float a,b,c;printf(Please enter a and b:);/提示输入scanf(%f,%f,&a,&b);/输入两个实数c=add(a,b);/调用add函数printf(sum is%fn,c);/输出两数之和return 0;float add(float x,float y)/定义add函数float z;z=x+y;return(z);/把变量z的值作为函数值返回对被调用函数的声明和函数原型在函数声明中的形参名可以省写,而只写形参的类型。如果已在文件的开头
19、(在所有函数之前),已对本文件中所调用的函数进行了声明,则在各函数中不必对其所调用的函数再作声明。float add(float x,float y);float add(float,float);/不写参数名,只写参数类型float add(float a,float b);/参数名不用x,y,而用a,b。合法函数函数类型型 函数名函数名(参数参数类型型1 参数名参数名1,参数参数类型型2 参数名参数名2,参数参数类型型n 参数名参数名n);函数函数类型型 函数名函数名(参数参数类型型1,参数参数类型型2,参数参数类型型n);或注意对函数的“定义”和“声明”不是同一回事。函数的定义是指对函数
20、功能的确立,包括指定函数名、函数值类型、形参及其类型以及函数体等,它是一个完整的、独立的函数单位。而函数的声明的作用则是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查,它不包含函数体。char letter(char,char);float f(float,float);int i(float,float);/所有函数之前,且在函数外部进行函数声明int main()/在main函数中要调用letter,f和i函数,不必再对所调用的这3个函数进行声明char letter(char c1,char c2)/定义letter函数float f
21、(float x,float y)/定义f函数int i(float j,float k)/定义i函数函数的嵌套调用执行main函数的开头部分;遇函数调用语句,调用函数a,流程转去a函数;执行a函数的开头部分;遇函数调用语句,调用函数b,流程转去函数b;执行b函数,如果再无其他嵌套的函数,则完成b函数的全部操作;返回到a函数中调用b函数的位置;继续执行a函数中尚未执行的部分,直到a函数结束;返回main函数中调用a函数的位置;继续执行main函数的剩余部分直到结束。C语言的函数定义是互相平行、独立的,也就是说,在定义函数时,一个函数内不能再定义另一个函数,即不能嵌套定义,但可以嵌套调用函数,即
22、在调用一个函数的过程中,又调用另一个函数。main函数函数a函数函数b函数函数调用用a函数函数调用用b函数函数 结 束束函数的嵌套调用【例7.5】输入4个整数,找出其中最大的数。用函数的嵌套调用来处理。#include int main()int max4(int a,int b,int c,int d);/对max4的函数声明int a,b,c,d,max;printf(Please enter 4 interger numbers:);/提示输入4个数scanf(%d%d%d%d,&a,&b,&c,&d);/输入4个数max=max4(a,b,c,d);/调用max4函数,得到4个数中的最
23、大者printf(max=%d n,max);/输出4个数中的最大者return 0;int max4(int a,int b,int c,int d)/定义max4函数int max2(int a,int b);/对max2的函数声明int m;m=max2(a,b);/调用max2函数,得到a和b中的大者,放在m中m=max2(m,c);/调用max2函数,得到a,b,c中的大者,放在m中m=max2(m,d);/调用max2函数,得到a,b,c,d中的大者,放在m中return(m);/把m作为函数值带回main函数int max2(int a,int b)/定义max2函数if(a=b
24、)return a;/若ab,将a作为函数返回值elsereturn b;/若a=b?a:b);/返回条件表达式的值,即a和b中的大者m=max2(max2(max2(a,b),c),d);/把函数调用作为函数参数intmax4(inta,intb,intc,intd)intmax2(inta,intb);/对max2的函数声明returnmax2(max2(max2(a,b),c),d);函数的递归调用函数的递归调用程序中不应出现无终止的递归调用,而只应出现有限次数的、有终止的递归调用,这可以用if语句来控制,只有在某一条件成立时才继续执行递归调用;否则就不再继续。在调用一个函数的过程中又出
25、现直接或直接或间接地接地调用用该函数本身,称函数本身,称为函数的函数的递归调用用。int f(int x)int y,z;z=f(y);/在执行f函数的过程中又要调用f函数return(2*z);f函数调用f函数直接直接递归f1函数f2函数调用f2函数调用f1函数间接接递归函数的递归调用【例7.6】有5个学生坐在一起,问第5个学生多少岁,他说比第4个学生大2岁。问第4个学生岁数,他说比第3个学生大2岁。问第3个学生,又说比第2个学生大2岁。问第2个学生,说比第1个学生大2岁。最后问第1个学生,他说是10岁。请问第5个学生多大。解解题思路思路:age(n)=10(n=1)age(n)=age(n
26、-1)+2(n1)age(5)age(5)=age(4)+2=18age(4)age(4)=age(3)+2=16age(3)age(3)=age(2)+2=14age(2)age(2)=age(1)+2=12age(1)=10函数的递归调用【例7.6】有5个学生坐在一起,问第5个学生多少岁,他说比第4个学生大2岁。问第4个学生岁数,他说比第3个学生大2岁。问第3个学生,又说比第2个学生大2岁。问第2个学生,说比第1个学生大2岁。最后问第1个学生,他说是10岁。请问第5个学生多大。#include int main()int age(int n);/对age函数的声明printf(NO.5,a
27、ge:%dn,age(5);/输出第5个学生的年龄return 0;int age(int n)/定义递归函数int c;/c用作存放函数的返回值的变量if(n=1)/如果n等于1c=10;/年龄为10else/如果n不等于1c=age(n-1)+2;/年龄是前一个学生的年龄加2(如第4个学生年龄是第3个学生年龄加2)return(c);/返回年龄注意分析递归的终止条件。mainage(n)n=5age(n)n=4age(n)n=3age(n)n=2age(n)n=1age(5)输出age(5)c=age(4)+2c=age(3)+2c=age(2)+2c=age(1)+2c=10age(5)
28、=18age(4)=16age(3)=14age(2)=12age(1)=10函数的递归调用【例7.7】用递归方法求n!。#include int main()int fac(int n);/fac函数声明int n;int y;printf(input an integer number:);scanf(%d,&n);/输入要求阶乘的数y=fac(n);printf(%d!=%dn,n,y);return 0;int fac(int n)/定义fac函数int f;if(n0)/n不能小于0printf(n1时,n!=n*(n-1)return(f);mainfac(n)n=5fac(n)n
29、=4fac(n)n=3fac(n)n=2fac(n)n=1fac(5)输出fac(5)f=fac(4)*5f=fac(3)*4f=fac(2)*3f=fac(1)*2f=1fac(5)=120fac(4)=24fac(3)=6fac(2)=2fac(1)=1注意程序中的变量是int型,如果用Visual C+、GCC以及多数C编译系统为int型数据分配4个字节,能表示的最大数为2 147 483 647,当n=12时,运行正常,输出为479 001 600。如果输入13,企图求13!,是得不到预期结果的,因为求出的结果超过了int型数据的最大值。可将f,y和fac函数定义为float或doub
30、le型。函数的递归调用【例7.8】Hanoi(汉诺)塔问题。古代有一个梵塔,塔内有3个座A,B,C。开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个老和尚想把这64个盘子从A座移到C座,但规定每次只允许移动一个盘,且在移动过程中在3个座上都始终保持大盘在下,小盘在上。在移动过程中可以利用B座。要求编程序输出移动盘子的步骤。ABC解解题思路思路:老和尚会这样想:假如有另外一个和尚能有办法将上面63个盘子从一个座移到另一座。那么,问题就解决了。此时老和尚只须这样做:命令第2个和尚将63个盘子从A座移到B座;自己将1个盘子(最底下的、最大的盘子)从A座移到C座;再命令第2个和尚将6
31、3个盘子从B座移到C座。第2个和尚又想:如果有人能将62个盘子从一个座移到另一座,我就能将63个盘子从A座移到B座,他是这样做的:命令第3个和尚将62个盘子从A座移到C座;自己将1个盘子从A座移到B座;再命令第3个和尚将62个盘子从C座移到B座。ABC63个盘子ABC移动前解解题思路思路:为便于理解,先分析将A座上3个盘子移到C座上的过程:将A座上2个盘子移到B座上(借助C座)。将A座上1个盘子移到C座上。将B座上2个盘子移到C座上(借助A座)。其中第步可以直接实现。第步又可用递归方法分解为:将A座上1个盘子从A座移到C座;将A座上1个盘子从A座移到B座;将C座上1个盘子从C座移到B座。第步可
32、以分解为:将B座上1个盘子从B座移到A座上;将B座上1个盘子从B座移到C座上;将A座上1个盘子从A座移到C座上。将以上综合起来,可得到移动3个盘子的步骤为:AC,AB,CB,AC,BA,BC,AC。共经历7步。由此可推出:移动n个盘子要经历(2n-1)步。ABCABCABC解解题思路思路:由上面的分析可知:将n个盘子从A座移到C座可以分解为以下3个步骤:将A座上n1个盘借助C座先移到B座上;把A座上剩下的一个盘移到C座上;将n1个盘从B座借助于A座移到C座上。上面第步和第步,都是把n1个盘从一个座移到另一个座上,采取的办法是一样的,只是座的名字不同而已。为使之一般化,可以将第步和第步表示为:将
33、one座上n1个盘移到two 座(借助three座)。只是在第步和第步中,one,two,three和A,B,C的对应关系不同。对第步,对应关系是one对应A,two对应B,three对应C。对第步,是:one对应B,two对应C,three对应A。因此,可以把上面3个步骤分成两类操作:将n1个盘从一个座移到另一个座上(n1)。这就是大和尚让小和尚做的工作,它是一个递归的过程,即和尚将任务层层下放,直到第64个和尚为止。hanoi函数将1个盘子从一个座上移到另一座上。这是大和尚自己做的工作。move函数在本程序中,调用递归函数hanoi,其终止条件为hanoi函数的参数n的值等于1。显然,此时
34、不必再调用hanoi函数了,直接执行move函数即可。在本程序中move函数并未真正移动盘子,而只是输出移盘的方案(表示从哪一个座移到哪一个座)。#include int main()void hanoi(int n,char one,char two,char three);/对hanoi函数的声明int m;printf(input the number of diskes:);scanf(%d,&m);printf(The step to move%d diskes:n,m);hanoi(m,A,B,C);void hanoi(int n,char one,char two,char t
35、hree)/定义hanoi函数/将n个盘从one座借助two座,移到three座void move(char x,char y);/对move函数的声明if(n=1)move(one,three);elsehanoi(n-1,one,three,two);move(one,three);hanoi(n-1,two,one,three);void move(char x,char y)/定义move函数printf(%c-%cn,x,y);数组作为函数参数形式参数形式参数实在参数在参数变量常量、变量、表达式、数组元素数组数组数组元素作为函数实参数组元素可以用作函数实参,但是不能用作形参。因为形参
36、是在函数被调用时临时分配存储单元的,不可能为一个数组元素单独分配存储单元(数组是一个整体,在内存中占连续的一段存储单元)。在用数组元素作函数实参时,把实参的值传给形参,是“值传递”方式。数据传递的方向是从从实参参传到形到形参,参,单向向传递。数组元素作函数实参【例7.9】输入10个数,要求输出其中值最大的元素和该数是第几个数。从键盘输入10个数给a0a9。变量m用来存放当前已比较过的各数中的最大者。开始时设m的值为a0,然后依次将m与ai比,如果ai大于m,就以ai的值取代m的原值。下一次以m的新值与下一个ai比较。经过9轮循环的比较,m最后的值就是10个数的最大数。请注意分析怎样得到最大数是
37、10个数中第几个数。当每次出现以max(m,ai)的值取代m的原值时,就把i的值保存在变量n中。n最后的值就是最大数的序号(注意序号从0开始),如果要输出“最大数是10个数中第几个数”,应为n+1。因为数组元素序号从0开始。#include int main()int max(int x,int y);/函数声明int a10,m,n,i;printf(enter 10 integer numbers:);for(i=0;i10;i+)/输入10个数给a0a9scanf(%d,&ai);printf(n);for(i=1,m=a0,n=0;im)/若max函数返回的值大于mm=max(m,ai
38、);/max函数返回的值取代m原值n=i;/把此数组元素的序号记下来,放在n中printf(The largest number is%dnit is the%dth number.n,m,n+1);int max(int x,int y)/定义max函数return(xy?x:y);/返回x和y中的大者一维数组名作函数参数【例7.10】有一个一维数组score,内放10个学生成绩,求平均成绩。(1)用数组名作函数参数,应该在主调函数和被调用函数分别定义数组。(2)实参数组与形参数组类型必须一致。(3)在定义average函数时,声明形参数组的大小为10,但在实际上,指定其大小是不起任何作用的
39、,因为C语言编译系统并不检查形参数组大小,只是将实参数组的首元素的地址传给形参数组名。(4)形参数组可以不指定大小,在定义数组时在数组名后面跟一个空的方括号。#include int main()float average(float array10);/函数声明float score10,aver;int i;printf(input 10 scores:n);for(i=0;i10;i+)scanf(%f,&scorei);printf(n);aver=average(score);/调用average函数printf(average score is%5.2fn,aver);return
40、 0;float average(float array10)/定义average函数int i;float aver,sum=array0;for(i=1;i10;i+)sum=sum+arrayi;/累加学生成绩aver=sum/10;return(aver);float average(float array)注意用数数组元素元素作实参时,向形参变量传递的是数组元素的值,而用数数组名名作函数实参时,向形参(数组名或指针变量)传递的是数数组首元素的地址首元素的地址。一维数组名作函数参数【例7.11】有两个班级,分别有35和30名学生,调用average函数,分别求这两个班的学生的平均成绩。
41、#include int main()float average(float array,int n);float score15=98.5,97,91.5,60,55;/定义长度为5的数组float score210=67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5;/定义长度为10的数组printf(The average of class A is%6.2fn,average(score1,5);/用数组名score1和5作实参printf(The average of class B is%6.2fn,average(score2,10);/用数组名s
42、core2和10作实参return 0;float average(float array,int n)/定义average函数,未指定形参数组长度int i;float aver,sum=array0;for(i=1;in;i+)sum=sum+arrayi;/累加n个学生成绩aver=sum/n;return(aver);float average(float array)注意用数用数组名作函数名作函数实参参时,不是把数不是把数组元素的元素的值传递给形参,而是把形参,而是把实参数参数组的首元素的地址的首元素的地址传递给形参数形参数组,这样两个数两个数组就共占同就共占同一段内存一段内存单元。
43、元。a0a1a2a3a4a5a6a7a8a9起始地址10002468101214161820b0b1b2b3b4b5b6b7b8b9一维数组名作函数参数【例7.12】用选择法对数组中10个整数按由小到大排序。解解题思路思路:所谓选择法就是先将10个数中最小的数与a0对换;再将a1a9中最小的数与a1对换每比较一轮,找出一个未经排序的数中最小的一个。共比较9轮。选择排序法排序法算法算法a0a1a2a3a436194未排序时的情况16394将5个数中最小的数1与a0对换13694将余下的后面4个数中最小的数3与a1对换13496将余下的3个数中最小的数4与a2对换13469将余下的2个数中最小的数
44、6与a3对换,至此完成排序可以看到在执行函数调用语句“sort(a,10);”之前和之后,a数组中各元素的值是不同的。原来是无序的,执行“sort(a,10);”后,a数组已经排好序了,这是由于形参数组array已用选择法进行排序了,形参数组改变也使实参数组随之改变。#include int main()void sort(int array,int n);int a10,i;printf(enter array:n);for(i=0;i10;i+)scanf(%d,&ai);sort(a,10);/调用sort函数,a为数组名,大小为10printf(The sorted array:n);
45、for(i=0;i10;i+)printf(%d,ai);printf(n);return 0;void sort(int array,int n)int i,j,k,t;for(i=0;in-1;i+)k=i;for(j=i+1;jn;j+)if(arrayjarrayk)k=j;t=arrayk;arrayk=arrayi;arrayi=t;多维数组名作函数参数可以用多维数组名作为函数的实参和形参,在被调用函数中对形参数组定义时可以指定每一维的大小,也可以省略第一维的大小说明。在定义二维数组时,必须指定列数(即一行中包含几个元素),由于形参数组与实参数组类型相同,所以它们是由具有相同长度的
46、一维数组所组成的。不能只指定第1维(行数)而省略第2维(列数)。在第2维大小相同的前提下,形参数组的第1维可以与实参数组不同。例如,实参数组定义为int score510;而形参数组定义为int array 10;或int array810;均可以。这时形参数组和实参数组都是由相同类型和大小的一维数组组成的。C语言编译系统不检查第一维的大小。int array310;或int array10;/二者等价int array;或int array3;/必须指定列数多维数组名作函数参数【例7.13】有一个34的矩阵,求所有元素中的最大值。形参数组array第1维的大小省略,第2维大小不能省略,而且要
47、和实参数组a的第2维的大小相同。在主函数调用max_value函数时,把实参二维数组a的第1行的起始地址传递给形参数组array,因此array数组第1行的起始地址与a数组的第1行的起始地址相同。由于两个数组的列数相同,因此array数组第2行的起始地址与a数组的第2行的起始地址相同。aij与arrayij同占一个存储单元,它们具有同一个值。实际上,arrayij就是aij,在函数中对arrayij的操作就是对aij的操作。#include int main()int max_value(int array4);/函数声明int a34=1,3,5,7,2,4,6,8,15,17,34,12;
48、/对数组元素赋初值printf(Max value is%dn,max_value(a);/max_value(a)为函数调用return 0;int max_value(int array4)/函数定义int i,j,max;max=array00;for(i=0;i3;i+)for(j=0;jmax)max=arrayij;/把大者放在max中return(max);局部变量和全局变量每一个变量都有一个作用域问题,即它们在什么范围内有效。局部变量定义变量可能有3种情况:(1)在函数的开头定义;(2)在函数内的复合语句内定义;(3)在函数的外部定义。在一个函数内部定义的变量只在本函数范围内有
49、效,也就是说只有在本函数内才能引用它们,在此函数以外是不能使用这些变量的。在复合语句内定义的变量只在本复合语句范围内有效,只有在本复合语句内才能引用它们。在该复合语句以外是不能使用这些变量的,以上这些称为“局部局部变量量”。局部变量(1)主函数中定义的变量也只在主函数中有效。主函数也不能使用其他函数中定义的变量。(2)不同函数中可以使用同名的变量,它们代表不同的对象,互不干扰。(3)形式参数也是局部变量。只在定义它的函数中有效。其他函数中不能直接引用形参。(4)在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效,这种复合语句也称为“分程序分程序”或“程序程序块”。全局变量程
50、序的编译单位是源程序文件,一个源文件可以包含一个或若干个函数。在函数内定义的变量是局部变量,而在函数之外定义的变量称为外外部部变量量,外部变量是全全局局变量量(也称全程变量)。全局变量可以为本文件中其他函数所共用。它的有效范围为从定义变量的位置开始到本源文件结束。注意在函数内定在函数内定义的的变量是局部量是局部变量,在函数外定量,在函数外定义的的变量是全局量是全局变量。量。全局变量设置全局变量的作用是增加了函数间数据联系的渠道。由于同一文件中的所有函数都能引用全局变量的值,因此如果在一个函数中改变了全局变量的值,就能影响到其他函数中全局变量的值。相当于各个函数间有直接的传递通道。由于函数的调用