计算机C语言—第八章.ppt_第1页
计算机C语言—第八章.ppt_第2页
计算机C语言—第八章.ppt_第3页
计算机C语言—第八章.ppt_第4页
计算机C语言—第八章.ppt_第5页
已阅读5页,还剩117页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第8章 函数 8.1 概述 一个C程序,由一个主函数和若干其它函数组成,它们之间的关系是: 主函数可以调用其它函数,其它函数可相互调用。且一个函数可以被调用若干次 注:每个函数都是独立的,平等的! 函数:完成特定功能的程序段,通常由用户定义或系统定义 各函数可存放在一个文件中,也可以存放在不同的文件中。,某程序整体结构,,程序运行轨迹: maina d a e a main b f e f b g b h b main c h g h c i c main,举例:用常规、文件包含两种方法打印字符串 一、常规方法:各函数包含在一个文件中 例T8-1.c main( ) p1( ); p2( ); p1( ); p1( ) printf (“* n” ); p2( ) printf (“_ _ _ _ _How_do_you_do!n”) ;,运行结果: * _ _ _ _ _How_do_you_do! _ _ _ _ * *,二、文件包含的方法 在主函数所在的文件中使用文件包含预编译命令,将不在本文件而在其它文件中的函数进行预编译处理,把各文件中的函数包含到本文件中来,然后一起进行编译、连接、运行。 T8-1-3.c #include “T8-1-1.c” #include “T8-1-2.c” main( ) p1( ); p2( ) ; p1( ) ; 运行结果同上 友情提示:还可以用项目的方法,T8-1-1.c p1( ) printf (“* n”); ,T8-1-2.c p2( ) printf (“_ _ _ _ How_do_you_do! n”); ,说明: (1)一个文件可含多个函数,编译的单位是文件而不是函数; (2)一个完整的程序可由若干个文件组成,可用项目或文件包含的方法对其编译; (3)C执行总是从main函数开始执行,调用其它函数后又返回到main函数; (4)函数定义是独立的、平等的,不能嵌套定义(即函数里不能再定义函数)但可相互调用; (5)函数的类型: 标准库函数,由系统提供,用户直接使用 用户定义的函数 (6) 函数的形式: 无参函数 主调函数无数据传给被调函数,可带或不带返回值. 有参函数 主调函数与被调函数间有参数传递,主调函数可将实际参数传送给被调函数的形式参数,被调函数的函数值可传回主调函数。,8.2 函数定义的一般形式 1.无参函数的定义形式: 类型标识符 函数名( ) 声明部分 语句部分 注:无参函数一般不返回函数值,故类型标识符可省。 2.有参函数的定义形式: 类型标识符 函数名(形式参数表列) 声明部分 语句部分 ,其中: 类型标识符:指出函数返回值的数据类型 (int, float,char等),系统默认为int 函数名:合法的标识符; 形参表列:接收主调函数传递过来的实参,其中包括对形参类型的声明(老版本中形参类型进一步声明放在下一行)。 形参类型:与实参类型要一致。 :称函数体,包括 声明部分:定义局部变量的数据类型; 语句部分:完成函数功能的若干执行语句。,例: int max(int x,int y) int z; z= xy ? x : y ; return(z) ; ,3.空函数的定义形式 类型说明符 函数名( ) 例: p1( ) 空函数不作任何操作,但是合法,它对调试程序或以后在此处补充完整的函数体是 有作用的。,4.对形参声明的传统方式 传统方式中,形参类型说明在函数定义的第2行 如:传统形参声明形式 int max(x,y) int x,y; int z; z=xy ?x:y; return(z); ,新版本形参声明形式 int max(int x,int y) int z; z=xy ?x:y; return(z); ,以上两种定义形式在Turbo C中都认可,8.3 函数参数和函数的值 8.3.1 形式参数和实际参数 实际参数:主调函数中提供的数据。 可以是常量、变量、表达式等,是具体的数值。 形式参数:被调函数中用以接收主调函数数据的变量。 被调用函数名后面括号内的若干变量名。,例T8-2.c 调用函数时的数据传递 main( ) int a, b, c; scanf(%d%d”, ,输入:-100 200 Max is 200,关于形、实参的说明: 1.形参只有在函数调用时才分配存储单元,调用结束后,释放所分配的单元; 2.实参可以是常量、变量、表达式:max(3,a+b),总之要有确定的值,当函数调用时,将实参的值传递给形参,若是数组名,则传送的是数组的首地址。 3.被调函数中,形参类型必须指定,以便分配存储单元。,4.实参、形参的数据类型一致,赋值要兼容,顺序要一致。 如果形、实参类型不一致时,则按赋值规则进行。通常被调函数放在主调函数之前,以便编译系统对函数类型和形参类型作合法性检查。若被调函数在主调函数之后,一般要对被调函数作原型声明。 main() float a=4.5,b=4.5; int abc(int,int); abc(a,b); abc(int x,int y) printf(“x=%d,y=%dn”,x,y); 结果:x=4,y=4,5.若被调函数类型为非整形或实参形参类型不匹配,要在主调函数中对被调函数作原形声明。另外若被调函数在主调函数之前定义,则原形声明可省,因为编译系统已经知道被调函数的类型及其形参的个数、类型了。 6.实参对形参的数据传送是值传送,也是单向传送,当被调函数的形参发生变化时,并不改变主调函数实参的值。,例T8-2-1.c 形、实参占据的是不同的存储单元 main( ) int a=2,b=3; printf (“a=%d, b=%d n”,a, b); printf(“ ,运行结果: a=2,b=3 &a=ffd6,&b=ffd8 x=10,y=15 &x=ffd2,&y=ffd4 a=2, b=3 &a=ffd6,&b=ffd8,8.3.2 函数的返回值 调用一个函数一般都希望返回一个确定的值。 有关函数值的几点说明: 1.若需要返回值则用return语句; 2.被调函数中可用多个return语句,执行哪一个由程序执行情况来定。 例:函数中有如下语句 if(ab) return(a); else return(b); 3.return后面的括号可省,如:return a;,4.return 后的值可以是一个表达式,如:return(x y ? x : y); 5.函数值的类型是在定义函数时指定的 如: int max(x, y) float min(a,b) double abc(d1,d2) 6.语句return(a,b,c)是合法的,返回表达式c的值。 注意: (1)函数定义时,函数名的括号后无 “ ;” ; (2) 未加类型说明的函数自动按整型处理; (3) 定义函数时,函数值的类型一般与return 后面表达式的类 型一致,若不一致, 则以函数值为准。,例T8-3.c 函数值类型为整型,而返回值的类型是实型,最后以整型值返回。即以函数类型为准 main( ) int max(float,float);/*原型声明*/ float a, b; int c; scanf(“%f%f”, ,输入: 1. 5 2. 5 输出:max is 2,6.函数中无return 语句时,可能返回一个不确定或无用的值 例T8-3-1.c main( ) int a, b, c; a=p1( ); b=p2( ); c=p1( ); printf(“a=%d,b=%d,c=%d n”,a, b, c); p1( ) printf(“* n”); p2( ) printf(“ I am happy! n”); ,运行结果: * I am happy! * a=6,b=12,c=6,7.为明确表示不带返回值,可用void(无值,空类型)定义函数。 例T8-3-2.c main( ) int a,b,c; a=p1( ); b=p2( ); c=p1( ); printf(“a=%d, b=%d, c=%d n”,a, b, c); void p1( ) printf(“* n”); void p2( ) printf(“I am happy! n”); ,编译时指出: Type mismatch in redeclartion of p1 , p2 意即:在定义函数 p1, p2 时类型不匹配,8.4 函数的调用 主调函数:主动去调用其它函数 被调函数:被其它函数所调用 8.4.1 函数调用的一般形式 函数名(实参表列) 操作:把控制和实参传送给被调函数,当无参时,实参表列为空,但( )不能省。 函数名:是已存在的被调用的函数; 实参表列:有确定值的数据,当有多个实参时,实参间用“ ,”分隔,通常形实、参个数要相等,类型要一致,实参求值顺序在Turbo C中是从右向左。,例T8-4.c 实参求值顺序从右向左 main( ) int i=2, p; p=f(i, +i); printf(“p=%d, i=%d n”,p, i); int f(int a, int b) int c; if(ab) c=1; else if(a=b) c=0; else c=-1; return (c); ,运行结果: p=0, i=3 若将参数改为f(i,i+), 则结果为: p=1, i=3 思考:若从左至右呢? 回忆一下printf的求值顺序,8.4.2 函数的调用方法 1.函数语句:把函数调用作为一个单独的语句; 如:f1( ); 2.函数表达式:函数调用出现在表达式中,其函数返回的值参加整个表达式的运算。 如:c=max(a,b) + min(c,d); 3.函数参数:函数调用作为另一个函数的参数,如:m=max(a,max(b,c); printf(“%d”,max(a,b);,8.4.3 对被调用函数的声明和函数原型 被调函数应具备的条件 1.被调函数必须存在(标准或用户定义),如不在同一文件中,可用项目或文件包含的方法将各被调用函数连接起来。 2.若使用库函数,应在文件开头用#include命令将调用库函数时用到的宏定义信息包含到本文件中来。 如:#include “stdio.h” #include “math.h” 3.若主调和被调函数在同一文件中,一般应在主调函数中对被调函数的类型作声明,即向编译系统声明即将调用的函数 形式: 类型标识符 被调用函数名(类型 形参. );,例T8-5.c 在主调函数中,对被调函数的数据类型进行说明 main( ) float add( float x,float y ); /*声明:函数类型、名,形参类型等通知编译系统*/ 再看 float a, b, c; scanf(%f%f”, ,输入:3.6 6. 5 输出:sum is 10.10000,问题: (1)若不对函数类型进行声明,则指出:在重定义函 数add时,类型不匹配; (2)在声明时指出类型,若定义时没有指出类型,编译指出:定义add时类型不匹配(此处是实型)。 函数声明(原型):与函数首部一致。 顺序、个数、类型等都要相同 有关函数的定义、声明、返回值等概念 1.函数定义:对函数功能的确定,指定函数名、函数值类型、形参及类型、函数体等,它是完整的、独立的函数单位。,2.函数声明:也称函数原型,其作用是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便调用函数时进行对照检查。 函数声明(原型)的形式: (1)函数类型 函数名(参数类型1,参数类型2.); (2)函数类型 函数名(参数类型1 参数名1,参数类型2 参数名2.); 3.当函数返回的值为整型或字符型时,可不必声明。系统会默认把第一次碰到的函数视为INT 4.被调用函数在主调函数之前定义时,在主调函数中可不必声明。,友情提示1,函数的原型声明必须放在程序开始处或main之前,例T8-5-1.c被调函数出现在主调函数之前,则在主调函数中不必声明 float add(float x,float y) float z; z=x+y; return(z); main( ) float a, b, c; scanf(“%f%f”, ,输入:3.6 6.5 输出:sum is 10.100000,主调函数中没对被调函数的返回值进行类型声明,原因是: 编译系统已经预知定义的函数的类型,并进行自动处理。 5.如果在所有函数定义之前,在文件的开头,在函数的外部对函数的类型作了声明,则在各主调函数中不必对所调用的函数再作类型声明。 例T8-5-2.c 在文件的开头,在所有函数的外部对函数作类型声明 。 char a1(char x1,char x2 ); float a2(float y1,float y2 ); int a3( int m ); double a4( double n1,double n2 );,main( ) 返回 char c1=d, c2=a; int i=5; float f1=3.67, f2=5.56; double d1=11111111.111, d2=22222222.222; printf(“a1( )=%c n”, a1(c1, c2); printf(“a2( )=%f n”, a2(f1, f2); printf(“a3( )=%d n”, a3(i);printf(“a4( )=%lf n”, a4(d1, d2); char a1(char x1, char x2) return( x1x2 ? x1 : x2); float a2(float y1, float y2) float z; z=y1+y2; return( z ); int a3(int m) int i, s=1; for(i=1; i=m; i+) s=s*i; return(s) ; double a4(double n1,double n2) double n3; n3=n1+n2; return(n3); ,运行结果: a1( )=d a2( )=9.230000 a3( )=120 a4( )=33333333.333000 问题的提出: (1)不在文件开头,不在 函数外部说明,情况如何? (2)不在主调函数开始部 分说明,解决的办法?,友情提示2,不要将空函数和void函数弄混了,8.5 函数的嵌套调用,例T8-6 用弦截法求方程 x3 -5x2 +16x =0 的根(请仔细研究),方法与步骤: 2.连接f(x1),f(x2)两点成一直线(弦),此线交x轴于x。 X点的坐标求法: 连接f(x1),f(x2)两点的直线 f(x) 称商差(弦、斜率): 求x点的坐标 从x值得f(x) 3.若f(x)与f(x1)同号,则根必在(x,x2)区间,此时将x作新的x1; 若f(x)与f(x2)同号,则根必在(x1,x)区间,此时将x作新的x2; 4.重复步骤2,3直到| f(x) | 为止, 设 10-6 , 则 f(x)0,异号:x1,x2之间必有一根 1.取x1,x2两点 得f(x1), f(x2) 同号:改变x1, x2,直到f(x1), f(x2)异号为止。,用三个函数实现各部分的功能: f(x):用来求x的函数:x3 - 5x2 +16x-80 xpoint(x1,x2): 求f(x1)与f(x2)的连线(弦)与x轴交点x的坐标 root(x1, x2) :求(x1, x2)区间的实根 例T8-6.c 用弦截法求方程x3 - 5x2 +16x-80的根 #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); dox=xpoint(x1, x2); y=f(x); if(y*y1 0) y1=y; x1=x; else x2=x; while(fabs(y) =0.0001); return(x); main( ) float x1, x2, f1, f2, x; do printf(“input x1, x2: n”); scanf(“%f%f”, ,运行: input x1, x2: 2, 6 A root of equation is 5.0000,8.6 函数的递归调用 递归:在函数调用过程中,直接或间接的调用自身。 1.直接递归:在函数体内又调用自身,2.间接递归:当函数去调用另一函数时,而另一函数反过来又调用自身。 解决无终止递归调用的方法是:确定好结束递归的条件。,递归调用 定义:函数直接或间接的调用自身叫函数的递归调用,说明 C编译系统对递归函数的自调用次数没有限制 所以,必须要用if 语句限制递归的次数,以免无限递归下去了,int f(int x) int y,z; z=f(y); . return(2*z); ,例T8-7.c 有5个人在一起问年龄,第5个人比第4个人大2岁,第4个人比第3个人大2岁. . .第2个人比第1个人大2岁,第1个人为10岁。(回推+递推),T8-7.c 问年龄程序 age(int n) int c; if(n=1) c=10; else c=2+age(n-1); return(c); /*返回给主调函数*/ main( ) printf(“%d n”, age(5); ,运行结果:18,在递归调用过程中,有些信息被临时压入堆栈 回推到已知:结束 这里控制有限次递归的一个条件就是if (n=1),有些问题,可以用递推,也可以用递归的方法解决 递推:从一个已知的事实出发,按一定规律推出下一个事实,再从已知的新的事实,推出下一个新的事实. 例T8-7-1.c 用递推法求n! ,即从1开始, 乘2, 乘3一直到n main( ) int i, s=1; for(i=1;i=5;i+) s=s* i; printf(“s=%d n”,s); ,运行结果:s=120,递归:回推(问题先压入堆栈暂存)+递推 从哪里开始递推?从满足结束递归的条件处开始递推 如: 5!=5 x 4! 4!=4 x 3! 3!=3 x 2! 2!=2 x 1! 1!=1 0!=1,例T8-8.c 用递归法求4! float facto(int n) float s; if(n 0) printf(“ n 0 data error ! n”); else if(n=0 | n=1 ) s=1; else s=n*facto(n-1); return(s); main( ) int n; float y; printf(“input a integer number:”); scanf(%d”, ,facto(int n) int s; if(n= =0) s = 1; else s=facto(n-1); s=n*s; return(s); ,facto(int n),int s;,if(n= =0),facto(int n) int s; if(n= =0) s = 1; else s=facto(n-1); s=n*s; return(s); ,s=facto(n-1),facto(int n),int s;,if(n= =0),facto(int n) int s; if(n= =0) s = 1; else s=facto(n-1); s=n*s; return(s); ,s=facto(n-1),facto(int n) int s; if(n= =0) s = 1; else s=facto(n-1); s=n*s; return(s); ,facto(int n),facto(int n),int s;,int s;,if(n= =0),if(n= =0),s=facto(n-1),s = 1,return(1),s=n*s=2*1,return(2),return(6),s=n*s=3*2,s=n*s=4*6,return(24),1,2,3,4,3,2,1,N=4,N=3,N=2,N=1,facto(int n) int s; if(n= =0) s = 1; else s=facto(n-1); s=n*s; return(s); ,facto(int n),int s;,else,s=facto(n-1),2,N=4,main函数第 1次调用facto,(main),堆栈,(n=4),facto(int n) int s; if(n= =0) s = 1; else s=facto(n-1); s=n*s; return(s); ,N=3,facto(int n),int s;,else,s=facto(n-1),3,Facto1函数第 2次调用facto,(main),堆栈,(n=4),(n=3),facto(int n) int s; if(n= =0) s = 1; else s=facto(n-1); s=n*s; return(s); ,N=2,facto(int n),int s;,else,s=facto(n-1),4,Facto2函数调用 第3次facto,(main),堆栈,(n=4),(n=3),(n=2),facto(int n) int s; if(n= =0) s = 1; else s=facto(n-1); s=n*s; return(s); ,N=1,facto(int n),int s;,else,s=facto(n-1),4,Facto3函数第 4次调用facto,(main),堆栈,(n=4),(n=3),(n=2),(n=1),facto(int n) int s; if(n= =0) s = 1; else s=facto(n-1); s=n*s; return(s); ,s = 1,N=0,facto(int n),int s;,if(n= =0),Facto4函数第 5次调用facto,return(1),(main),堆栈,(n=4),(n=3),(n=2),(n=1),facto(int n) int s; if(n= =0) s = 1; else s=facto(n-1); s=n*s; return(s); ,s=facto(1-1)=0!=1,s=1*1,return(1),N=1,(main),堆栈,(n=4),(n=3),(n=2),恢复facto4 现场,40E2(n=1),0!= 1,facto(int n) int s; if(n= =0) s = 1; else s=facto(n-1); s=n*s; return(s); ,s=facto(2-1)=1!=1,s=2*1,return(2),N=2,(main),堆栈,(n=4),(n=3),恢复facto3 现场,40E2(n=2),1!= 1,facto(int n) int s; if(n= =0) s = 1; else s=facto(n-1); s=n*s; return(s); ,s=facto(3-1)=2!=2,s=3*2,return(6),N=3,(main),堆栈,(n=4),恢复facto2 现场,2!= 2,40E2(n=3),facto(int n) int s; if(n= =0) s = 1; else s=facto(n-1); s=n*s; return(s); ,return(24),N=4,s=facto(4-1)=3!=6,s=4*6,(main),堆栈,恢复facto1 现场,3!= 6,40E2(n=4),返回主函数,例T8-9.c hanoi (汉诺)塔问题(请仔细研究) 十九世纪未,欧洲珍奇商店出现一种汉诺塔游戏,并有推销材料,说是古代印度布拉玛庙里的僧侣们当时正在玩这种游戏,如果游戏结束,世界未日即来临。 一、规则及分析: n个盘子从一个座移到另一个座,每次只能移动一个盘子,不允许大盘在小盘上面。 共有三个座,n个盘子由A座移到C座,需移动的次数是2n -1, 若64个盘子移动的次数为: 264 - 1=18, 446, 744, 073, 709, 551, 615 一年的秒数是:365 x 24 x 60 x 60=31536000 1844674407370955161531536000 =584942417355年 即:5849亿年, 从能源角度推算, 太阳系寿命只有150亿年,二、方法与步骤 1.将A上n-1个盘子借助C座移到B座 2.把A上剩下一个盘子送到C座 3.将n-1个盘子从B座借助A座移到C座,三、实例:将A上3个盘子移到C 步骤:1.A座上两个盘子借助C座移到B座 2.A座上最后一个盘子移到C座 3.B座上两个盘子借助A座移到C座 第一步进一步分解: 1.1 A座上一个盘子从AC 1.2 A座上一个盘子从AB 1.3 C座上一个盘子从CB 第二步进一步分解: A座上最后一个盘子从AC 第三步进一步分解: 3.1 B座上一个盘子从BA 3.2 B座上一个盘子从BC 3.3 A座上一个盘子从AC,结论: 13步都是把n-1个盘子从一个座移到另一个座上,方法一样,只是座的名称不同而已,为使之一般化,将13步表示为:将one 座上的n-1个盘子移到two座,借助 three座,只是对应关系不同。 第一步对应关系:one A two B three C 第三步对应关系:one B two C three A,1.将 n - 1个盘子从一个座移到另一个座上(n - 1) 2.将 1个盘子从一个座移到另一个座上(n - 1),例T8-9.c 用递归的方法解决汉诺塔程序如下: void move(char x, char y) printf(“%c%c n”, x, y); void hanoi(int n, char one, char two, char three) if(n = 1) move(one,three); else hanoi(n-1, one, three, two); move(one, three); hanoi(n-1, two, one, three); main( ) int m; printf(“input the number of diskes:”); scanf(“%d”,运行: input number of diskes: 3 the step to moving 3 diskes: A C A B C B A C B A B C A C,8.7 数组作为函数参数 函数调用形式一:函数名(数组名)实参或形参 函数调用形式二:函数名(数组元素)实参 数组名作为参数:传递的是数组的首地址; 数组元素作实参时:传递的是数组元素的值, 是单向的值传送。,8.7 数组作为函数参数 函数调用形式一:函数名(数组名)实参或形参 函数调用形式二:函数名(数组元素)实参 数组名作为参数:传递的是数组的首地址; 数组元素作实参时:传递的是数组元素的值, 是单向的值传送。,数组元素作函数实参值传递,例 两个数组大小比较,n=0 m=0 k=0,a和b为有10个元素的整型数组 比较两数组对应元素 变量n,m,k记录aibi, ai=bi, aik,认为数组ab 若nk,认为数组ab 若n=k,认为数组a=b,2、数组名作为函数实参 此时,传送的是数组的地址,调用函数时,对形参数组元素的操作,实际上也是对实参数组元素的操作。 *地址传递 *在主调函数与被调函数分别定义数组,且类型应一致,例 求学生的平均成绩,#include float average(int stu10, int n); void main() int score10, i; float av; printf(“Input 10 scores:n“); for( i=0; i10; i+ ) scanf(“%d“, ,float average(int stu10, int n) int i; float av,total=0; for( i=0; in; i+ ) total += stui; av = total/n; return av; ,实参用数组名,形参用数组定义, int stu ,几点说明: 1.数组名作形、实参数时,应分别在主、被调函数中对其定义 2.数组名作参数时,传递的是地址,对形参数组的操作实际 上也是对实参数组的操作。两个数组是共用同一个内存单元则形参中的数据变化了实参也会变化这与变量做形参区别很大 3.作为形、实参数的数组,其类型要一致,大小一般相等,以保证形式上的对应; 4.当形参数组大小未指定时,用一实参将数组长度传递给形 参以便对数组进行操作; 5、字符串的传递同数组的传递字符串是用数组存储的,例8-12.c 求两组学生的平均成绩,形参数组长度缺省 float average(float a ,int n) int i; float aver, sum=a0; for(i=1;in;i+) sum=sum+ai; aver=sum/n; return(aver); ,main( ) float s15=98.5, 97, 91.5, 60, 60, 55; float s210=67.5, 89.5, 99, 69.5, 77, 89.5, 76.5, 54, 60, 99.5; printf(“the average of class A is %6.2f n”,average(s1,5); printf(“the average of class B is %6.2f n”,average(s2,10); ,the average of class A is 80.40 the average of class B is 78.20,例 数组元素与 数组名 作函数参数比较,#include void swap2(int x,int y) int z; z=x; x=y; y=z; main() int a2=1,2; swap2(a0,a1); printf(“a0=%dna1=%dn“,a0,a1); ,值传递,#include void swap2(int x) int z; z=x0; x0=x1; x1=z; main() int a2=1,2; swap2(a); printf(“a0=%dna1=%dn“,a0,a1); ,地址传递,例 数组元素与 数组名 作函数参数比较,例 数组排序-简单选择排序(请同学们自行思考),9,49,i=0,例 数组排序-简单选择排序,13,68,i=1,i=8,例 数组排序-简单选择排序,例 求二维数组中最大元素值,int max_value(int array34) int i,j,k,max; max=array00; for(i=0;imax) max=arrayij; return(max); main() int a34=1,3,5,7, 2,4,6,8,15,17,34,12; printf(“max value is %dn“,max_value(a); ,例 求二维数组中各行元素之和,get_sum_row(int x3, int result ,int row, int col) int i,j; for(i=0;irow;i+) resulti=0; for(j=0;jcol;j+) resulti+=xij; main() int a23=3,6,9,1,4,7; int sum_row2,row=2,col=3,i; get_sum_row(a,sum_row,row,col); for(i=0;irow;i+) printf(“The sum of row%d=%dn“,i+1,sum_rowi); ,18,12,8.8 局部变量和全局变量 8.8.1 局部变量 变量:按其作用域,可分为局部和全局 局部:作用域仅限于其所定义的函数或复合语句内部,离开该函数或复合语句则释放内存单元 特点: (1)在不同的函数中允许同名,它们占据不同的内存单元, 相互之间互不影响。 (2)形参属局部变量,只能在其所在的函数内部使用。,例T8-14-1.c f1( ) int a=10, b=25, c=30; printf(“f1: a=%d, b=%d, c=%d n”, a, b, c); f2( int a,int b ) int c; a=a+2; c=a+b+3; printf(“f2:a=%d, b=%d, c=%d n”,a,b,c); main( ) int a=1, b=2, c=5; /*abc也不例外,也是局部变量*/ printf(“1.main:a=%d, b=%d, c=%d n”,a, b, c); f1( ); printf(“2.main:a=%d, b=%d, c=%d n”,a, b, c); f2(a, b ); printf(“3.main:a=%d, b=%d, c=%d n”,a, b, c); ,运行结果: 1. main:a=1, b=2, c=5 f1:a=10, b=25, c=30 2.main:a=1, b=2, c=5 f2:a=3, b=2, c=8 3.main:a=1, b=2, c=5,例T8-14-2.c 复合语句中局部变量的例子 main( ) int a=1, b=2, c=3; int c; c=a-b; printf(“a=%d, b=%d, c=%d n”, a, b, c); printf(“a=%d, b=%d, c=%d n”, a, b, c) ; ,运行结果: a=1, b=2, c=-1 a=1, b=2, c=3,8.8.2 全局变量 全局变量:在一个文件的所有函数以外定义的变量称为外部或全局变量。 作用域:从定义变量的位置开始到源程序结束。所有该源文件中的函数公用,几点说明,在源程序开始定义的全局变量,对源程序中所有函数有效 在源程序中间定义的全局变量,仅对其后面的所有函数有效,几点说明2,在函数或复合语句中定义的局部变量若与全局变量同名,当该函数或复合语句被执行时,则局部变量优先,全局变量不起作用(被屏蔽)。,例T8-14-3.c 全局变量的作用域及其使用情况 int a=1; f1( ) int b; b=a+3; printf(“f1:a=%d, b=%d n”,a, b); f2( ) int a, b; a=5; b=a+3; printf(“f2: a=%d, b=%d n”,a, b); f3( ) int b; a=6; b=a+3; printf(“f3:a=%d, b=%d n”,a, b); main( ) int b=3; printf(“1.main : a=%d, b=%d n”,a, b); f1( ); printf(“2.main : a=%d, b=%d n”,a, b); f2( ); printf(“3.main : a=%d, b=%d n”,a, b); f3( ); printf(“4.main : a=%d, b=%d n”,a, b); ,运行: 1.main:a=1, b=3 f1:a=1, b=4 2.main:a=1, b=3 f2:a=5, b=8 3.main:a=1, b=3 f3:a=6, b=9 4.main:a=6, b=3,几点说明3,全局变量的使用,增加了函数间数据联系的渠道,同一文件中的所有函数都能引用全局变量的值,当某函数改变了全局变量的值时,便会影响其它的函数。,例T8-15.c 用一维数组存放10个学生的成绩,在函数中求最高分、最低分和平均值。 float max=0, min=0; (习惯上:Max,Min) float average(float array,int n) int i; float aver,sum=array0; max=min=array0; for(i=1; i max) max=arrayi; else if(arrayi min) min=arrayi; sum=sum+arrayi ; aver=sum/n; return(aver); ,main( ) float ave, score10; int i; printf(“input 10 numbers : n”); for(i=0; i10; i+) scanf(“%f”, 一个函数可以返回3个值了!,运行:input 10 numbers: 99 45 78 97 100 67.5 89 92 66 43 max=100.00 min=43.00 ave=77.65,float max,min; float average(float array, int n) int i; float sum=array0; max=min=array0; for(i=1;imax) max=arrayi; else if(arrayimin) min=arrayi; sum+=arrayi; return(sum/n); main() int i; float ave,score10; /*Input */ ave=average(score,10); printf(“max=%6.2fnmin=%6.2fn average=%6.2fn“,max,min,ave); ,外部(全局)变量的弊端: 1.建议非必要时不要使用全局变量: (1)整个程序中均占用存储空间 (2)函数可移植性差 2.程序可读性差,且一旦外部变量被改变将影响所有函数,int i; main() void prt(); for(i=0;i5;i+) prt(); void prt() for(i=0;i5;i+) printf(“%c”,*); printf(“n”); ,例 外部变量副作用,运行结果:*,变量的存储属性 概述 每个变量有两个基本属性:变量的数据类型!那么,变量的存储类型呢?,编译或函数调用时为其分配内存单元,10,程序中使用变量名对内存操作,变量的属性 数据类型:变量所持有的数据的性质(操作属性) 存储属性 存储器类型:寄存器、静态存储区、动态存储区 生存期:变量在某一时刻存在-静态变量与动态变量 作用域:变量在某区域内有效-局部变量与全局变量 变量的存储类型 auto -自动型 register-寄存器型 static -静态型 extern -外部型 变量定义格式: 存储类型 数据类型 变量表;,如: int sum; auto int a,b,c; register int i; static float x,y;,程序运行时,在内存中的存储情况: (1)静态存储方式:即程序运行期间为其分配的存储单元是固定的。直到文件执行完 (2)动态存储方式:程序运行期间根据需要为其分配存储单元。用完就释放,格式:auto int a; 说明符“auto”可以省略。 auto float pi; 说明: 1.说明自动变量必须在一个函数体的内部。 2.函数的形参也是自动变量。,作用域 函数内部,实质上是一个局部变量。只有在函数被调用时才存在,从函数中返回时即消失,其值仅限于说明它的函数。 由于自动变量具有局部性,所以在两个不同的函数中可以分别使用同名的变量而互不影响。,自动变量auto,8.9.2 auto变量 函数内部无static声明的局部量均为动态存储类别,被

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论