




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、C语言程序设计 2022-4-2512022-4-252第六章 函数主讲主讲: : 计算机学院计算机学院 吴敏吴敏2022-4-253内容提要2022-4-252022-4-253 32022-4-2542022-4-252022-4-254 4大家想一想 如果每个printf()函数由20行代码替换,每个scanf()函数由50行代码替换,那么你见过的程序会是什么样子? 读多少行的程序能让你不头疼?怎么团队合作? 如果所有代码都在main()当中,2022-4-2552022-4-252022-4-255 5数学函数 我们可以将像sin(x)那样的数学函数想象成一个黑盒子,或一个小机器。如果
2、你在它的上面放入一个“值”,在它的下面就会掉出“结果” 对应于程序函数,上面的值称为参数,下面的值称为返回值2022-4-2562022-4-252022-4-256 6调用sin(x)函数 如果我们改变了输入的参数,函数就能返回不同的值。 图中我们将调用4次sin的结果加起来,并将其和存入变量total中。2022-4-2572022-4-252022-4-257 7函数的本质 函数是这样一种运算: 函数名说明运算规则 参数是运算的操作数 返回值是运算的结果x =x =a + b + c;add(a, b, c);int add(int a, int b, int c)return a+b+
3、c; 2011年3月23日星期三2022-4-2582022-4-252022-4-258 8函数的分类函数生来平等,没有高低贵贱之分,只有main()函数作为入口函数稍微特殊一点世界上只有10种函数,一种是别人写的,一种是自己写的2011年3月23日星期三2022-4-2592022-4-252022-4-259 9别人写的函数 库函数 ANSI C定义的标准库函数符合标准的C语言编译器必须提供这些函数I/O、数学、字符字符串、图形、内存、时间、. 第三方库函数有其它厂商自行开发的C语言函数库不在标准范围内,能扩充C语言的功能2011年3月23日星期三2022-4-25102022-4-25
4、2022-4-251010自己写的函数 自定义函数 包装后,也可以成为库函数,供别人使用 注意:“自己”和“别人”是相对而言的2011年3月23日星期三2022-4-2511函数概述2022-4-252022-4-2511 11 在在C语言中,往往把程序需要实现的一些功能分别编写成若语言中,往往把程序需要实现的一些功能分别编写成若干个函数,在不同情况下,调用不同的模块。干个函数,在不同情况下,调用不同的模块。按层次组织模块按层次组织模块主模块主模块模块模块1模块模块2模块模块3模块模块4模块模块5模块模块6需要指出总任务需要指出总任务分别指出各自的子任务分别指出各自的子任务精确描述精确描述怎么
5、做怎么做2022-4-25122022-4-252022-4-251212函数的作用 分解问题,使程序结构更加清晰在解决复杂问题时,先将问题划分或化解成一些子问题分别加以解决,从而降低问题的复杂度。在程序实现时可针对这些子问题分别编程实现和测试。 避免重复劳动在解决不同的实际问题时,常常需要用到许多相同的子方法或子技术。它们对于不同问题可能只是选择参数的不同,而内部功能完全相同。如果能将这些子方法或子技术形成一个经过测试的优化的固定程序模块,让用户在解决问题时直接调用,就会比较方便。2022-4-25132022-4-252022-4-251313学习函数的三个要素函数的声明、定义与调用201
6、1年3月23日星期三2022-4-25142022-4-252022-4-251414#include #include void void ()() int max(int int max(int ,int int ) ); int int ,;,; scanfscanf(,);(,); (,);(,); printfprintf( ,);,); int max(int ,int )*定义有参函数max * int ; ?; return(); 运行情况如下:运行情况如下:, 2022-4-25152022-4-252022-4-251515通过函数调用,可使两个函数中的数据发生联系。202
7、2-4-25162022-4-252022-4-251616函数声明2011年3月23日星期三2022-4-25172022-4-252022-4-251717函数声明返回值类型标志符参数表类型 函数名(类型 参数1, 类型 参数2, .);int max(int x, int y);例:2022-4-25182022-4-252022-4-251818函数声明注意事项 C语言是一门编译语言,它在使用某个函数之前,必须知道函数在哪里,即编译器需要看到该函数的声明或定义 不同的编译器处理函数声明的方式不同Textmate工具: warningDev-cpp工具:error2011年3月23日星期
8、三2022-4-25192022-4-252022-4-251919函数定义2011年3月23日星期三2022-4-25202022-4-252022-4-252020函数定义(函数的实现)类型 函数名(类型 参数1, 类型 参数2,.).return 表达式;int max(int x, int y) int max;if(xy) max =x;elsemax =y;return max; 2011年3月23日星期三2022-4-25212022-4-252022-4-252121函数定义(函数的实现)类型 函数名(类型 参数1, 类型 参数2,.).返回值类型标志符参数表.return 表
9、达式;函数出口返回值int max(int x, int y) int max;if(xy) max =x;elsemax =y;return max; 2011年3月23日星期三2022-4-25222022-4-252022-4-252222函数定义的三种形式类型 函数名(类型 参数1, 类型 参数2,.).return 表达式;类型 函数名().return 表达式;void 函数名().有参函数无参函数空函数2011年3月23日星期三2022-4-25232022-4-252022-4-252323请点评#include int main()int a,b;scanf(%d %d, &
10、amp;a, &b);printf(%dn, max(a,b);return 0;/求最大值函数int max(int x, y)int max;if(xy) max =x; elsemax =y;return max;max.c2011年3月23日星期三2022-4-25242022-4-252022-4-252424函数的定义:对函数功能的确立,包括指定函数名,函数值类型、形参名称及其类型、函数体等,它是一个完整的、独立的函数单位。l 函数的声明:则是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查。 2022-4-2525202
11、2-4-252022-4-252525函数的返回值 函数通过return语句将函数计算结果返回 当函数执行到return语句或时,函数的运算停止。程序从当此调用函数的地方int max(int x, int y)if(xy) return x; elsereturn y; int max(int x, int y)int max;if(xy)max =x;elsemax =y;return max; 继续执行 函数可以有多个return, 但最好只有一个且放在最后一行2011年3月23日星期三2022-4-25262022-4-252022-4-252626不返回任何值的函数空函数(void)
12、 有时某些函数没有返回值,调用过程的输出已经在被调函数体内完成,这时要用void定义这些“无返回值”类型的函数void print_star()printf(*n,);void print_message()printf(how are u?n); 此时,return语句可以省略2011年3月23日星期三2022-4-25272022-4-252022-4-252727请点评#include void print_message( ) printf(How are u?n);int main() char str20= How do u do?;str20 = print_message();
13、printf(%s,str);return 0;void_demo.c2011年3月23日星期三2022-4-25282022-4-252022-4-252828(1 1)函数的返回值通过函数中的)函数的返回值通过函数中的returnreturn语句获得。语句获得。 一个函数中可以有一个以上的一个函数中可以有一个以上的returnreturn语句,执语句,执行到哪一个行到哪一个returnreturn语句,哪一个语句起作用。语句,哪一个语句起作用。(2 2)函数的返回值应当属于某一个确定的类型,在)函数的返回值应当属于某一个确定的类型,在定义函数时指定函数返回值的类型。定义函数时指定函数返回值
14、的类型。注意:注意:凡凡不加不加类型说明的函数,自动按类型说明的函数,自动按整型整型处理。处理。函数类型一般应该和函数类型一般应该和returnreturn语句中的表达式类型语句中的表达式类型一致一致,否则否则以函数类型为准以函数类型为准。对于对于不带回值不带回值的函数,函数类型为的函数,函数类型为“voidvoid”2022-4-25292022-4-252022-4-252929函数调用2011年3月23日星期三2022-4-25302022-4-252022-4-253030函数名(参数1,参数2,.)函数调用 函数调用的形式:int main() int a,b;scanf(%d %d
15、,&a, &b);printf(%dn, max(a,b);return 0;2011年3月23日星期三2022-4-25312022-4-252022-4-253131函数嵌套调用实例#include int bar(int c, int d) int res = c + d; printf(bar:%dn,res); return res;int foo(int a, int b) int res = bar(a, b); printf(foo:%dn,res); return res;int main() printf(main:startn); int res = fo
16、o(2, 3); printf(main:%dn,res); main()调用foo()结束()foo()bar()调用bar()returnreturn return 0;foo_bar.c2011年3月23日星期三2022-4-25322022-4-252022-4-253232函数调用的示意图老婆洗菜烧水入锅炒起锅操作系统做菜主函数切菜炒菜子函数子函数2011年3月23日星期三2022-4-25332022-4-252022-4-253333函数调用的注意事项调用一个函数之前,先要对其返回值类型、函数名和参数进行声明或定义调用函数时,提供的参数(实际参数)和该函数定义中的参数(形式参数)
17、必须匹配数目一致类型一一对应(会发生自动类型转换)把实际参数的值复制给形式参数foo_bar.c2011年3月23日星期三2022-4-25342022-4-252022-4-253434函数参数传递2011年3月23日星期三2022-4-25352022-4-252022-4-253535int bar(int c, int d) int res = c + d; return res;int foo(int a, int b) int res = bar(a, b); return res;int main()函数参数 函数参数:就是一个变量,它随着使用者的不同而发生变化。 形参:函数定义
18、中的形式参数。 实参:就是在函数调用时,传递给函数的参数,也就是参数的实际值foo(2, 3);return 0;2011年3月23日星期三2022-4-25362022-4-252022-4-253636 函数参数:就是一个变量,它随着使用者的不同而发生变化。 形参:函数定义中的形式参数。 实参:就是在函数调用时,传递给函数的参数,也就是参数的实际值int bar(int c, int d) int res = c + d; return res; a,bint foo(int a, int b)为形参2, 3 为实参 int res = bar(a, b); return res;a,b的
19、值为实参int main()foo(2, 3);return 0;函数参数c,d 为形参2011年3月23日星期三2022-4-25372022-4-252022-4-253737形参、实参的注意事项 在定义函数中指定的形参变量,在未出现函数调用时,它们并不占内存单元。只有在发生函数调用时函数中的参数才被分配内存单元。在调用结束后,形参所占的内存单元才被释放。 在被定义的函数中,必须指定形参的类型。 实参和形参类型应一致,实参可以是整型、实型、字符型或表达式,但要求它们有确定的值。2011年3月23日星期三2022-4-25382022-4-252022-4-253838请点评#include
20、 /* 形参和实参swap演示 */void Swap(int x, int y);int main()int a=123;int b=456; Swap(a,b);/交换a,b的值 return 0;/求最大值函数void Swap(int x, int y)int tmp;tmp = x;x = y;y= tmp;swap.c2011年3月23日星期三2022-4-25392022-4-252022-4-253939请点评#include /* 形参和实参swap演示 */void Swap(int x, int y);int main()int a=123;int b=456; Swap
21、(a,b);/交换a,b的值 return 0;/求最大值函数void Swap(int x, int y)int tmp;tmp = x;x = y;y= tmp;swap.c2011年3月23日星期三2022-4-25402022-4-252022-4-254040int main()int a=123; int b=456;printf(VartAddresstValuen);printf(-n);printf(at%pt%dn, &a, a);printf(bt%pt%dn, &b, b);Swap(a,b); printf(-n); printf(at%pt%dn,
22、&a, a);printf(bt%pt%dn, &b, b);用火焰金睛看一看#include /* 通过内存地址观察形参和实参 */void Swap(int x, int y);void Swap(int x, int y)int tmp; printf(-n); printf(xt%pt%dn, &x, x);printf(yt%pt%dn, &y, y);tmp = x;x = y;y= tmp;printf(-n);printf(xt%pt%dn, &x, x);printf(yt%pt%dn, &y, y); return 0;swa
23、p_inside.c2011年3月23日星期三2022-4-25412022-4-252022-4-254141函数参数的传递 C语言规定,实参变量对形参变量的数据传递是“值传递”,即单向传递,只能由实参传给形参,而不能由形参传给实参,在内存中实参单元与形参单元是不同的单元。2011年3月23日星期三2022-4-25422022-4-252022-4-254242实参可以是常量、变量、表达式,只要有确定的值。在函数调用时才给形参分配存储空间,且调用结束后所占空间立即释放。实参和形参必须类型相同。若不同时,按赋值规定自动进行类型转换。(5 5)单向值传递)单向值传递: :(复印功能)(复印功能
24、)发生函数调用时,实参数值被复发生函数调用时,实参数值被复印传递给对应形参,从此形参的变化与实参无印传递给对应形参,从此形参的变化与实参无关关 2022-4-25432022-4-252022-4-254343函数设计原则2011年3月23日星期三2022-4-25442022-4-252022-4-254444函数的设计原则每个函数只完成一个功能对函数的功能可以用不含连词的一句话描述函数不能过长1986年IBM在OS/360的研究结果:大多数有错误的函数都大于500行1991年对于48,000行代码的研究表明:小于143行的函数比更长的函数更容易维护函数一定要对传进来的非法参数做点什么向调用
25、者提供错误信息2011年3月23日星期三2022-4-2545无参函数举例-P106例6.2l思考l(1) 删除语句return 对程序有无影响?l(2)区分函数的定义和函数的调用(函数名(实参表列) )l(2)如果将Star函数的定义放到main函数之后,编译时会有什么现象?不改变两个函数的定义位置,如何修改使程序正确?-函数声明2022-4-252022-4-2545452022-4-2546函数调用时控制流及数据流传输(1)为被调函数形参分配空间(2)主调函数将实参拷贝一份,传给对应形参(3)控制流转到被调函数起始位置,开始执行 (4)被调函数执行到return语句,系统根据函数返回值类
26、型创建一个该类型的临时变量,并将return后的表达式的值赋值给此临时变量,被调函数中形参和局部变量所分配的空间被回收,控制流返回主调函数中下一步语句; (5)主调函数从这个临时变量取值,然后临时变量被系统销毁。2022-4-252022-4-2546462022-4-2547课堂练习lP139 二、(3)l编程:定义一个求阶乘的函数,原型为l,并在主函数中调用它,求从键盘输入的一个任意正整数的阶乘2022-4-252022-4-2547472022-4-25482022-4-252022-4-254848#include stdio.h#include stdio.h“ main() / m
27、ain() /* *主函数主函数* */ / int m int m; long p(int)long p(int); scanf( scanf(“%d%d”,m);,m); printf( printf(d!=d!=ldn,m,p(m)ldn,m,p(m); 2022-4-2549函数定义与调用举例l(一)程序6.4:判断质数函数的定义与调用 l例4.7 已讲过如何判断一个整数为质数,回顾l本程序需要定义一个函数l(1)功能:判断一个整数是否为质数l(2)参数:一个整数,为待判断的数l(3)返回值:整型值,为质数返回1,否则返回0l(4)因此,函数原型为:int primeInt(int m
28、);2022-4-252022-4-2549492022-4-2550例4.7 核心代码2022-4-252022-4-255050k=(int)sqrt(m); for (i=2; prime &i=k;i+) if (m%i=0) prime=0; if (prime) printf(%d is a primen,m);else printf(%d is not a primen,m);程序程序6.4:6.4:int main( )int main( ) if (if (primeInt(m)primeInt(m) ) int primeInt(int m) return prim
29、e; 2022-4-25512022-4-252022-4-255151#include#includeint primeInt(int m); /判断质数函数声明int main( ) int m;scanf(%d,&m); if (primeInt(m) /判断质数函数调用 printf(%d is a primen,m);else printf(%d is not a primen,m);return 0;int primeInt(int m)int primeInt(int m) return prime; return prime; 2022-4-2552函数定义与调用举例l
30、(四)程序6.7:查找一个数组元素的函数的定义与调用l程序5.9:查找数组元素的主函数形式,回顾l本程序需要定义一个函数l(1)功能:查找一个元素是否在数组中l(2)参数:三个参数,第一个参数是指针,用来接受待查找的数组的首地址,第二个参数,接受待查找的值,第三个参数,整型值,接受待查找的元素个数l(3)返回值:整型值, 存在则返回在数组中的下标,否则返回-1。l(4)因此,函数原型为:lint Find(int* pa,int x,int n); 2022-4-252022-4-2552522022-4-2553例5.9 核心代码2022-4-252022-4-255353 scanf(%d
31、,&x); p=a; while(in) if (x=*(p+i)break;i+; if(in) printf(value=%d, index=%dn,x,i);elseprintf(Not present!n);return 0;程序程序6.76.7函数原型:函数原型: int Find(intint Find(int* * pa,int x,int n); pa,int x,int n); 2022-4-25542022-4-252022-4-255454#include int Find(int* pa,int x,int n); /查找数组元素函数声明int main() i
32、nt a10,n=10,x,*p,i; printf(Input %d elements:n,n);for (p=a;pa+10;p+) scanf(%d,p); printf(Input x be searched:n,n);scanf(%d,&x); i=Find(a,x,n); /查找数组元素函数的调用if(in&i!=-1) printf(value=%d, index=%dn,x,i);elseprintf(Not present!n);return 0;2022-4-2555 2022-4-252022-4-255555 根据实参传递给形参值的不同,通常有值传递方式
33、和根据实参传递给形参值的不同,通常有值传递方式和地址传递方式两种。地址传递方式两种。 方式方式: 函数调用时函数调用时, ,为形参分配单元为形参分配单元, ,并将实参的值复制到并将实参的值复制到形参中;调用结束,形参单元被释放,实参单元仍保形参中;调用结束,形参单元被释放,实参单元仍保留并维持原值。留并维持原值。 特点:特点: 形参与实参占用不同的内存单元形参与实参占用不同的内存单元 单向传递单向传递2022-4-25562022-4-252022-4-2556567x11y 调用#include #include void swap (int a, int b);void swap (int
34、 a, int b); void main ( )void main ( ) int x = 7, y = 11; int x = 7, y = 11; printf (before swapped: ); printf (before swapped: ); printf (x=%d, y=%dn, x, y); printf (x=%d, y=%dn, x, y); swap (x, y); swap (x, y); printf (after swapped: );printf (after swapped: ); printf (x=%d, y=%dn, x, y); printf (
35、x=%d, y=%dn, x, y);void swap (int a, int b)void swap (int a, int b) int temp; int temp; temp = a; temp = a; a = b; a = b; b = temp; b = temp;7x11y 调用前 swap7x11y7a11btemp2022-4-25572022-4-252022-4-255757 方式:方式: 函数调用时,将函数调用时,将数据的存储地址数据的存储地址作为参数传递给形参作为参数传递给形参 特点:特点: 形参与实参占用同样的存储单元形参与实参占用同样的存储单元 双向传递双向传
36、递 实参和形参必须是地址常量或变量实参和形参必须是地址常量或变量注意以下几点:注意以下几点: 形参数组和实参数组的形参数组和实参数组的类型必须一致类型必须一致,否则将引起错误。,否则将引起错误。 形参数组和实参数组的形参数组和实参数组的长度可以不相同,因为在调用时,长度可以不相同,因为在调用时,只传送首地址而不检查形参数组的长度。只传送首地址而不检查形参数组的长度。 2022-4-25582022-4-252022-4-255858float float average(float array10)average(float array10),并在主函数中调用,并在主函数中调用它求一维数组它求
37、一维数组scorescore(从键盘输入(从键盘输入1010个学生成绩)个学生成绩)的平均成绩。的平均成绩。 float average(float array10)float average(float array10) int i; int i; float aver,sum=array0; float aver,sum=array0; for(i=1;i10;i+) for(i=1;i10;i+) sum=sum+arrayi; sum=sum+arrayi; aver=sum/10; aver=sum/10; return(aver); return(aver); 2022-4-255
38、92022-4-252022-4-255959#include void 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); printf(average score is %5.2fn,aver);2022-4-25602022-4-252022-4-256060 编写一个函数,用来分别求数组编写一个函数,用来分别求数组sc
39、ore_1score_1(有(有5 5个个元素)和数组元素)和数组score_2score_2(有(有1010个元素)各元素的平个元素)各元素的平均值均值 。分析:分析: 要求两个不同大小的数组中元素的要求两个不同大小的数组中元素的均值,均值,在函数中设一个整型形参接受调用时在函数中设一个整型形参接受调用时传递过来的元素个数传递过来的元素个数; 用数组名作函数的实参时,用数组名作函数的实参时,传递数传递数组的首地址,使形参数组与实参数组占用同组的首地址,使形参数组与实参数组占用同一段内存单元。一段内存单元。当形参数组元素的值变化时,当形参数组元素的值变化时,对应的实参数组元素的值也发生了改变。
40、对应的实参数组元素的值也发生了改变。2022-4-25612022-4-252022-4-256161#include void main() float average(float array ,int n); float score_15=98.5,97,91.5,60,55; float score_210=67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5; printf(The average of class A is %6.2fn,average(score_1,5); printf(The average of class B is %6.2fn
41、,average(score_2,10); float average(float array ,int n) int i; float aver,sum=array0; for(i=1;in;i+) sum=sum+arrayi; aver=sum/n; return(aver);2022-4-2562函数调用与变量的存储类别 l自定义函数引出了两个问题:l第一,不同函数的变量(包括实参与形参)如果同名,是否会发生冲突?l第二,一个函数的变量空间在内存中存在多长时间。要有效地利用系统空间资源,这段时间就不能太长。l这两个问题分别引出了变量作用域和变量生命周期的概念。2022-4-252022
42、-4-2562622022-4-2563变量的存储方式和生存期2022-4-252022-4-256363从变量的从变量的作用域作用域(即从空间)角度来分,可以分为(即从空间)角度来分,可以分为全局变量和局部变量。全局变量和局部变量。从变量值的从变量值的生存期生存期(即存在的时间)角度来分,又(即存在的时间)角度来分,又可以分为静态存储方式和动态存储方式。可以分为静态存储方式和动态存储方式。2022-4-25642022-4-252022-4-256464 一是数据类型:一是数据类型: 如整型如整型(int)(int)、实型、实型(float)(float)、字符型、字符型(char)(cha
43、r) 等。等。 二是数据的存储类型:二是数据的存储类型: 分为自动类型分为自动类型(auto)(auto)、静态类型、静态类型(static)(static)、寄存器类型、寄存器类型(register)(register)、外部类型、外部类型(extern)(extern)。数据的存储类别决定了该数据的。数据的存储类别决定了该数据的存储区域。存储区域。默认默认供用户使用的内存空间可以分为三部分:2022-4-25652022-4-252022-4-256565数据分别存放在静态存储区和动态存储区。其中:数据分别存放在静态存储区和动态存储区。其中: 在动态存储区存放:在动态存储区存放:在静态存储
44、区存放全部在静态存储区存放全部全局变量和静态变量全局变量和静态变量。在程序开始执行时为其分配存储空间,程序执行完毕就释放。在程序执行的整在程序开始执行时为其分配存储空间,程序执行完毕就释放。在程序执行的整个过程中始终占固定的存储单元。个过程中始终占固定的存储单元。 函数的形参函数的形参 调用函数时为形参分配存储空间调用函数时为形参分配存储空间 函数中定义的未加函数中定义的未加staticstatic的变量的变量 函数调用时的现场保护和返回地址等函数调用时的现场保护和返回地址等2022-4-25662022-4-252022-4-256666 自动变量自动变量 函数中的局部变量,如不专门声明函数
45、中的局部变量,如不专门声明staticstatic存储类存储类别,都是动态地分配存储空间的,数据存储在动态存别,都是动态地分配存储空间的,数据存储在动态存储区中。储区中。函数中的形参和在函数中定义的变量函数中的形参和在函数中定义的变量( (包括在包括在复合语句中定义的变量复合语句中定义的变量) ), 在调用函数时系统会给它在调用函数时系统会给它们分配存储空间,在函数调用结束时就自动释放这些们分配存储空间,在函数调用结束时就自动释放这些存储空间。存储空间。局部变量的存储类别局部变量的存储类别例如:例如:int fint f(int int ) auto int auto int , ,; ; 2
46、022-4-2567自动局部变量 2022-4-252022-4-256767n自动局部变量的作用域与生命期:自动局部变量的作用域与生命期:n从执行其定义语句时创建,同时开始了它的作用域。从执行其定义语句时创建,同时开始了它的作用域。n当函数执行结束,其自变量空间被撤销,当函数执行结束,其自变量空间被撤销,n生命周期和作用域同时结束。生命周期和作用域同时结束。可以使用的范围存在的时间2022-4-2568自动局部变量l程序6.10 自动局部变量的生存周期和作用域示例 l思考下列问题:l(1)动态演示显示自动局部变量的生存周期起止为?l(2)main中的自动局部变量生命期与作用域一致吗?l(3)
47、为什么a,b的地址与n,m的地址相同?l(4)如果将AB和NM函数中的输出语句复制到main函数中,程序还正确吗?为什么?l(5)如果将AB和NM函数中的变量名统一都改为int x,y;程序还正确吗?为什么?2022-4-252022-4-2568682022-4-2569静态局部变量 l静态局部变量:存储类别static(不可缺省) 表示l生命期:只在函数第1次被调用时分配空间并初始化(初值若未指定,自动为0),程序结束时生命期结束l存储位置:在内存数据区的静态存储区域 l作用域:它所在的函数,只有该函数被调用时起作用,其余时候处于“休眠”状态,保持其当前值(“记忆”)l程序6.12 定义函
48、数fac求n! ,主函数调用该函数输出1!至7!并求阶乘之和。l此题充分利用静态局部变量的记忆能力,函数fac无需通过循环语句就可以计算n!。 2022-4-252022-4-2569692022-4-2570#include double fac(int n)static double f=1.0; f=f*n; return f;int main( )int i; double t,sum=0.0; t=fac(i);printf(“nsum=%10.0fn”,sum); return 0;2022-4-252022-4-2570702022-4-25712022-4-252022-4-2
49、57171教学进程教学进程寄存器变量寄存器变量registerregister变变量量 变量的值是存放在内存中的。变量的值是存放在内存中的。 当程序中用到哪一个变量的值时,当程序中用到哪一个变量的值时,由控制器发出指令将内存中该变量的由控制器发出指令将内存中该变量的值送到运算器中。值送到运算器中。 经过运算器进行经过运算器进行运算,如果需要存数,再从运算器将运算,如果需要存数,再从运算器将数据送到内存存放。数据送到内存存放。寄存器变量2022-4-25722022-4-252022-4-257272如果有一些变量使用频繁,为提高执行效率,语如果有一些变量使用频繁,为提高执行效率,语言允许将局部
50、变量的值放在言允许将局部变量的值放在CPUCPU中的寄存器中,需中的寄存器中,需要用时直接从寄存器取出参加运算,不必再到内存要用时直接从寄存器取出参加运算,不必再到内存中去存取。中去存取。2022-4-25732022-4-252022-4-257373 三种局部变量的存储位置是不同的:三种局部变量的存储位置是不同的:自动变量存储在动态存储区;自动变量存储在动态存储区;静态局部变量存储在静态存储区;静态局部变量存储在静态存储区;寄存器存储在寄存器存储在CPUCPU中的寄存器中。中的寄存器中。2022-4-2574外部变量 l外部变量:为克服两种局部变量的作用域只在某一个函数内的缺陷,若变量定义
51、在所有函数之外则为外部变量,也称为全局变量l生命期:从编译阶段开始,直到程序结束 l存储位置:在内存数据区的静态存储区域 l作用域:从其定义点开始以下的所有函数中去掉同名局部变量所在的部分。l优点:多个函数之间可以方便地实现数据共享l缺点:各个函数之间的数据独立性减弱,通用性降低.l程序6.13 外部变量与局部变量的作用域示例 l注意:外部变量在同名局部量所在的部分不起作用,其余部分连续变化! 2022-4-252022-4-2574742022-4-2575课堂练习lP137 -138 (一)1-6lP138 二 (2,4)2022-4-252022-4-2575752022-4-2576递
52、归的思想 2022-4-252022-4-257676从前有座山,山上有座庙,庙里有一个老和尚从前有座山,山上有座庙,庙里有一个老和尚和一个小和尚,老和尚正在给小和尚讲故事。和一个小和尚,老和尚正在给小和尚讲故事。讲的是什么故事呢?他说,从前讲的是什么故事呢?他说,从前2022-4-25772022-4-252022-4-257777void tell_story( )void tell_story( ) int old_monk, young_monk; int old_monk, young_monk; tell_story ( ); tell_story ( ); / / tell_st
53、ory tell_story 函数的递归调用函数的递归调用 封闭的递归调用循环,真正的递归程序中,一封闭的递归调用循环,真正的递归程序中,一般度会有一些条件语句进行判断,当满足某个般度会有一些条件语句进行判断,当满足某个条件时就会终止这个递归调用,以免陷入无休条件时就会终止这个递归调用,以免陷入无休止的死循环中止的死循环中2022-4-25782022-4-252022-4-257878函数的嵌套调用有一个特例,即递归调用,也就函数的嵌套调用有一个特例,即递归调用,也就是说,在调用一个函数的过程中,又出现了直接是说,在调用一个函数的过程中,又出现了直接或间接地去调用该函数本身。或间接地去调用该
54、函数本身。函数的递归调用函数的递归调用用小整数的阶乘计算大整数的阶乘用小整数的阶乘计算大整数的阶乘:n!=:n!=用小实数的乘幂计算大实数的乘幂用小实数的乘幂计算大实数的乘幂:xn=:xn=2022-4-25792022-4-252022-4-257979在语法上(简单)J递归即为普通的函数调用。在算法上(难)J如何找到递归形式?J如何找到递归边界?如何编写递归程序?如何编写递归程序? 2022-4-2580分而治之2022-4-252022-4-258080分而治之(分而治之(divide-and-conquerdivide-and-conquer)的算法)的算法设计思想:设计思想:1.1.
55、DivideDivide:把问题划分为若干个子问题;:把问题划分为若干个子问题;2.2.ConquerConquer:以同样的方式分别去处理各:以同样的方式分别去处理各个子问题;个子问题;3.3.CombineCombine:把各个子问题的处理结果综:把各个子问题的处理结果综合起来,形成最终的处理结果。合起来,形成最终的处理结果。2022-4-25812022-4-252022-4-258181如何编写基于分治策略的递归程序?J在算法分析上,要建立分治递归的思维方式。J在编程实现上,要建立递归信心(To turst the recursion, Jerry Cain, stanford)。20
56、22-4-25822022-4-252022-4-258282如何建立分治递归的思维方式?J基本原则:目标驱动!J计算n!:n! = n * (n-1)!,且1! = 1。递归形式递归形式递归边界递归边界2022-4-25832022-4-252022-4-258383void main( ) int n; printf(请输入一个整数:请输入一个整数:); scanf(%d, &n); printf(%d! = %d n, n, fact(n);int fact(int n) if(n = 1) return(1); else return(n * fact(n-1);请输入一个整数
57、:请输入一个整数:33! = 62022-4-25842022-4-252022-4-258484分析?J函数的递归调用到底是如何进行的呢?在递归调用时,执行的是不是相同的代码?访问的是不是相同的数据?如果是的话,那么大家会不会相互干扰、相互妨碍?2022-4-25852022-4-252022-4-258585main的栈帧m3void main( ) int m; printf(请输入一个整数:请输入一个整数:); scanf(%d, &m); printf(%d! = %dn, m, fact(m);int fact(int n) if(n = 1) return(1); els
58、e return(n * fact(n-1);3nfact的栈帧2nfact的栈帧1nfact的栈帧2022-4-25862022-4-252022-4-258686调用和返回的递归示意图调用和返回的递归示意图 B Bfact(2)fact(2)=2=2* *fact(1)fact(1)=2=2* *1 1=2=2返回返回 D DA Afact(3)fact(3)=3=3* *fact(2)fact(2)=3=3* *2 2=6=6E E返回返回 C Cfact(1)fact(1)=1=1调用调用调用调用2022-4-25872022-4-252022-4-258787调用调用调用调用fact
59、(3)fact(3)fact(2)fact(2)fact(1)fact(1)2022-4-2588递 归 l递归避免死循环:有明确的递归终止条件,每一层递归参数在每次递归调用时的取值是不同的,而且它的取值变化可以保证递归调用在有限次之后停止l递归包含两个过程:2022-4-252022-4-2588882022-4-25892022-4-252022-4-258989玛特露什卡玛特露什卡2022-4-25902022-4-252022-4-259090调用调用调用调用调用调用调用调用调用调用调用调用2022-4-2591课堂练习一lP138 二(1)l 2022-4-252022-4-2591
60、912022-4-2592课堂练习2l 编程:在main函数中定义一个一维数组,定义下列函数并在主函数中对各函数进行调用和测试,各函数原型如下:l (1)输入函数 void input(int array,int lenth)l (2)打印函数void print(int array,int lenth)l (3)int GetMax(int array,int lenth)l (4)int Retrieve(int array,int length,int x)l (5)void sort(int array,int lenth)l double average(int array,int lenth)2022-4-252022-4-2592922022-4-25932022-4-252022-4-259393#include#includevoidvoid I
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030年中国型煤(型焦)行业运行态势及发展规划分析报告
- 2025-2030年中国吹瓶机行业现状分析与竞争战略研究报告
- 2025-2030年中国厨房饮用净水机行业发展趋势与十三五规划分析报告
- 2025-2030年中国卡钉产业运行状况及运营规模分析报告
- 2025-2030年中国便携式自动导航系统PND行业运行态势及发展可行性分析报告
- 2025-2030年中国仿象牙筷市场发展状况及投资战略研究报告
- 科技创新在农业领域的深度应用报告
- 施工场地租赁合同
- 小学普通话教学的优化计划
- 旅游行业信息技术能力提升方案
- 口服降糖药物分类详解
- 2024年潍坊工程职业学院单招职业适应性测试题库完美版
- 六年级下册综合实践活动教案-跟着节气去探究 全国通用
- 停车场巡视记录表
- 森林防火安全责任书(施工队用)
- 《汽车性能评价与选购》课程设计
- 35kV绝缘导线门型直线杆
- 水库应急抢险与典型案例分析
- 49式武当太极剑动作方位
- 工程成本分析报告(新)
- 国际学术会议海报模板16-academic conference poster model
评论
0/150
提交评论