中国高校课件下载中心 》 教学资源 》 大学文库

《计算机程序设计基础》课程授课教案(C语言)第5章 模块化编程

文档信息
资源类别:文库
文档格式:PDF
文档页数:18
文件大小:405.44KB
团购合买:点击进入团购
内容简介
《计算机程序设计基础》课程授课教案(C语言)第5章 模块化编程
刷新页面文档预览

《计算机程序设计基础C语言》教案总学时36第29学时一第30学时授课内容第5章模块化编程一一函数的定义、声明、调用教学目的掌握函数定义、调用、声明;函数参数传递方式和要求了解函数递归调用重点:函数定义、调用、声明重点函数参数传递方式难点难点:函数参数传递方式-传址教引言学讲授安一、模块化程序设计排复杂问题的解决方法一般会是把原问题分解成若干个规模较小的问题加以解决,并可以类推的继续向下分解。结构化程序设计的基本思想之一是程序的"模块化"(module)。所谓"模块化"就是把一个较为复杂的大程序化分成若于个功能相对独立的程序块,每个程序块实现一个功能。在C语言中,这样的程序块被称为函数。函数是C程序的基本模块,C语言被称为函数式语言。从一个例子说起:求n个垫圈的面积总和。在这个程序中我们使用了3个函数。其中main(函数用于输入和输出,而计算求和以及垫圈面积分别用独立的函数sum()和area()完成。几点体验:·函数sum,area要先声明,后使用;·函数sum,area通过参数表中的参数n,d1,d2传递数据,以return语句从函数名sum,area获得返回的函数值。·函数的参数n,d1,d2都是有类型的

《计算机程序设计基础C语言》教案 总学时36 第 29学时 — 第 30学时 授课内容 第5章 模块化编程——函数的定义、声明、调用 教学目的 和要求 掌握函数定义、调用、声明;函数参数传递方式 了解函数递归调用 重点 难点 重点: 函数定义、调用、声明 函数参数传递方式 难点: 函数参数传递方式-传址 教 学 安 排 引言 讲授 一、模块化程序设计 复杂问题的解决方法一般会是把原问题分解成若干个规模较小的问题加以解 决,并可以类推的继续向下分解。 结构化程序设计的基本思想之一是程序的"模块化" (module)。所谓"模块化"就 是把一个较为复杂的大程序化分成若干个功能相对独立的程序块,每个程序块 实现一个功能。 在C语言中,这样的程序块被称为函数。 函数是C程序的基本模块,C 语言被称为函数式语言。 从一个例子说起:求n个垫圈的面积总和。 在这个程序中我们使用了3个函数。其中main()函数用于输入和输出,而计算 求和以及垫圈面积分别用独立的函数sum()和area()完成。 几点体验: ● 函数sum,area要先声明,后使用; ● 函数sum,area通过参数表中的参数n,d1,d2传递数据,以return语句从函数名 sum,area获得返回的函数值。 ●函数的参数n,d1,d2都是有类型的

·函数参数的传递遵循NOT原则Number、Order、Type必须一致二、函数的定义所有的函数定义,包括主函数mainO,都是平行的,函数可以嵌套调用或相互调用,但不能嵌套定义。调用者称为主调函数,被调用的函数称为被调函数。函数自己调用自己,称为递归调用main函数是主函数,它可以调用其它函数,而不允许被其它函数调用。C程序的执行总是从main函数开始,完成对其它函数的调用后再返回到main函数,最后由main函数结束整个程序C源程序中必须有,也只能有1个main函数。1函数的分类1.从用户角度分类:库函数:由C系统提供,用户无须定义,不必在程序中作类型说明,只需在程序前包含有该函数原型的头文件即可在程序中直接调用。如printfO、scanfO)、getcharo)、putcharo...用户定义函数:由用户按需要写的函数。对于用户自定义函数,不仅要在程序中定义函数本身,而且在主调函数模块中还必须对该被调函数进行类型说明,然后才能使用。如例中sum(intn)、area(floatd1,floatd2)2.从函数执行过程分类:有返回值函数,无返回值函数3.从函数定义形式分类:有参函数,无参函数函数的定义形式11.无参函数的定义形式类型标识符函数名0声明部分语句部分1类型标识符:说明函数返回值的数据类型;若缺省,则为int类型;若函数无值,则定义为void类型函数名:由用户自己命名,合法的标识符无参函数可以有也可以有返回值,但无返回值的较常见。无返回值函数的类型标识符是void。void lineOkprintf("~~~~ln");1【例】无返回值的无参函数举例#include#includevoid line(t无参函数定义printf("~~~~ln");

●函数参数的传递遵循NOT原则: Number、Order、Type必须一致 二、函数的定义 所有的函数定义,包括主函数main(),都是平行的,函数可以嵌套调用或相互 调用,但不能嵌套定义。 调用者称为主调函数,被调用的函数称为被调函数。 函数自己调用自己,称为递归调用。 main 函数是主函数,它可以调用其它函数,而不允许被其它函数调用。 C程序的执行总是从main函数开始,完成对其它函数的调用后再返回到main 函数,最后由main函数结束整个程序 C源程序中必须有,也只能有1个main函数。 l 函数的分类 1. 从用户角度分类: 库函数: 由C系统提供,用户无须定义,不必在程序中作类型说明,只需在程 序前包含有该函数原型的头文件即可在程序中直接调用。如 printf()、scanf()、 getchar()、putchar(). 用户定义函数:由用户按需要写的函数。对于用户自定义函数,不仅要在程序 中定义函数本身,而且在主调函数模块中还必须对该被调函数进行类型说明, 然后才能使用。 如例中sum(int n)、area(float d1,float d2) 2. 从函数执行过程分类: 有返回值函数,无返回值函数 3. 从函数定义形式分类: 有参函数,无参函数 l 函数的定义形式 1. 无参函数的定义形式 类型标识符 函数名(){ 声明部分 语句部分 } 类型标识符:说明函数返回值的数据类型;若缺省,则为 int 类型;若函数无 值,则定义为 void 类型 函数名:由用户自己命名,合法的标识符 无参函数可以有也可以有返回值,但无返回值的较常见。 无返回值函数的类型标识符是 void。 void line(){ printf("~~~~~~~~~~~~~~~\n"); } 【例】无返回值的无参函数举例 #include #include void line(){ // 无参函数定义 printf("~~~~~~~~~~~~~~~\n");

1mainOtprintf("Hello \n");line();/无参函数调用printf("Follow me!n");line(;getch);【例】有返回值的无参函数#include#include mainOtif(test0==1)printf(" return 1 In");elseprintf(" return 0 In");1inttestOtreturn 1;^2.有参函数的定义形式函数类型函数名(形参类型说明表)(说明部分语句部分1形参类型说明表:说明函数参数的个数和类型三、函数的参数和函数的返回值1.函数的形参和实参在定义函数时,有参函数名后面括弧中的变量名称为形式参数(formalparameter),简称形参;在调用函数时,函数名后面括弧中的表达式称为实际参数(actuaparameter),简称实参。主调函数和被调函数之间的信息交换可以通过实参与形参的结合和return语句来实现,称为按值调用(callbyvalue)

} main(){ printf(" Hello !\n"); line(); // 无参函数调用 printf(" Follow me !\n"); line(); getch(); } 【例】有返回值的无参函数 #include #include main(){ if(test() == 1) printf(" return 1 \n"); else printf(" return 0 \n"); } int test(){ return 1; } 2. 有参函数的定义形式 函数类型 函数名(形参类型说明表){ 说明部分 语句部分 } 形参类型说明表:说明函数参数的个数和类型 三、函数的参数和函数的返回值 1. 函数的形参和实参 在定义函数时,有参函数名后面括弧中的变量名称为形式参数(formal parameter),简称形参; 在调用函数时,函数名后面括弧中的表达式称为实际参数(actual parameter),简称实参。 主调函数和被调函数之间的信息交换可以通过实参与形参的结合和return语句 来实现,称为按值调用(call by value)

:形参与实参的特点:形参只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后,则不能再使用该形参。实参可以是常量、变量、表达式、函数调用等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋值、输入等方法使实参获得确定值。·函数参数表的一致性原则(NOT):函数调用中实参的数目(Number)必须与函数原型中形参的数目一致。:函数调用中实参的顺序(Order)必须与函数原型中形参的对应顺序一致。:函数调用中实参的数据类型(Type)必须与函数原型中对应形参的数据类型一致。:函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。在函数调用过程中,形参的值发生改变,而实参中的值不会变化。如果要将被调函数的结果返回主调函数,则应使用return语句并体现为主调函数名。2.函数的返回值返回语句形式:return表达式或return (表达式);功能:使程序控制从被调用函数返回到调用函数中,同时把返值带给调用函数。说明:函数中可有多个return语句,但只执行第一个,若无return语句,遇1时,自动返回调用函数,若函数类型与return语句中表达式值的类型不一致,按函数类型为准,自动转换--函数调用转换语句return0;结束main0程序运行,返回正常值(把控制权交还给操作系统)对函数返回值说明:1)函数的值只能通过return语句返回主调函数。2)函数值的类型和函数定义中函数的类型应保持一致。如果两者不一致,则以函数的类型为准,编译系统会自动进行类型转换。3)若不要求被调函数有返回值,可以不使用return语句,或在return后面只有一个分号,即写成return;4)对于不返回函数值的函数,函数类型可以明确定义为"空类型",即"void"。总结:函数的调用方式和被调用的函数必须具备的条件函数的调用方式语句方式如:line():用于void型函数表达式方式如:c=sum(a,b);参数方式如:m=max(c,max(a,b));

● 形参与实参的特点: 形参只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存 单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后,则不 能再使用该形参。 实参可以是常量、变量、表达式、函数调用等,无论实参是何种类型的量,在 进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此 应预先用赋值、输入等方法使实参获得确定值。 ● 函数参数表的一致性原则(NOT) ● 函数调用中实参的数目(Number)必须与函数原型中形参的数目一致。 ● 函数调用中实参的顺序(Order)必须与函数原型中形参的对应顺序一致。 ● 函数调用中实参的数据类型(Type)必须与函数原型中对应形参的数据类 型一致。 ● 函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参, 而不能把形参的值反向地传送给实参。在函数调用过程中,形参的值发 生改变,而实参中的值不会变化。如果要将被调函数的结果返回主调函 数,则应使用return语句并体现为主调函数名。 2. 函数的返回值 返回语句形式: return 表达式; 或 return (表达式); 功能:使程序控制从被调用函数返回到调用函数中,同时把返值带给调用函 数。 说明: 函数中可有多个return语句,但只执行第一个,若无return语句,遇 } 时,自动 返回调用函数,若函数类型与return语句中表达式值的类型不一致,按函数类 型为准,自动转换-函数调用转换 语句 return 0; 结束main()程序运行,返回正常值0(把控制权交还给操作系统) 对函数返回值说明: 1) 函数的值只能通过return语句返回主调函数。 2)函数值的类型和函数定义中函数的类型应保持一致。如果两者不一致,则 以函数的类型为准,编译系统会自动进行类型转换。 3)若不要求被调函数有返回值,可以不使用return语句,或在return后面只有 一个分号,即写成 return; 4)对于不返回函数值的函数,函数类型可以明确定义为"空类型",即"void"。 总结:函数的调用方式和被调用的函数必须具备的条件 ● 函数的调用方式 语句方式 如:line(); 用于void型函数 表达式方式 如:c=sum(a,b); 参数方式 如:m=max(c,max(a,b));

:被调用的函数必须具备的条件被调用的函数必须是已经存在的函数若调用库函数,应该在文件开头用#include命令将所需的信息包含到本文件中来。如:#include或#include"math.h"若使用自定义函数,该函数与主调函数应该在同一个文件中。一般应该在文件开头或主调函数中对被调函数进行说明。但有两个例外:①整型或字符型函数可以不说明②被调函数写在主调函数之前可以不说明四、函数的声明除int型或char型函数外,若主调用函数在被调用函数之前,必须在调用前用被调用函数的函数原型作声明。函数声明(declaration)的方式采用函数原型(Function Prototype)函数原型一般形式为:类型说明符被调函数名(类型形参,类型形参...);或为:类型说明符被调函数名(类型,类型...);例如:int max(int a,int b);也可以写为int max(int,int);函数定义与函数声明的区别:1函数定义是指对函数功能的建立,包括指定函数名、函数类型、形参及其类型、函数体等,它是一个完整的、独立的函数单位。2E函数声明的作用是在程序的编译阶段对被调函数的合法性进行全面检查,将函数名、函数返回值的类型以及形参的类型、个数和顺序通知编译系统,以便在调用时系统进行对照检查。3简而言之,函数的声明是将函数定义中的第1行(函数首部)复制后再加一个分号。·可以省略函数声明的几种情况1被调函数的函数定义出现在主调函数之前,在主调函数中可以不对被调函数声明而直接调用。2整型或字符型函数可以不加声明。系统将自动对被调函数返回值按整型处理。3如果在文件的开头对函数统一进行了声明,则在各调用函数中可不再对被调用函数加以声明。4调用库函数时不必进行声明,只需用#include包含相应的头文件(标准库函数的原型在系统提供的相应头文件中)。五、函数的调用C语言中,函数调用的一般形式为:函数名(实际参数表);。函数调用的方式1)函数语句:函数调用的一般形式加上分号即构成函数语句

● 被调用的函数必须具备的条件 被调用的函数必须是已经存在的函数 若调用库函数,应该在文件开头用#include命令将所需的信息包含到本文件中 来。 如:#include 或 #include "math.h" 若使用自定义函数,该函数与主调函数应该在同一个文件中。 一般应该在文件开头或主调函数中对被调函数进行说明。但有两个例外: ①整型或字符型函数可以不说明 ②被调函数写在主调函数之前可以不说明 四、函数的声明 除int型或char型函数外,若主调用函数在被调用函数之前,必须在调用前用被 调用函数的函数原型作声明。函数声明(declaration)的方式采用函数原型 (Function Prototype) 函数原型一般形式为: 类型说明符 被调函数名(类型 形参,类型 形参.); 或为: 类型说明符 被调函数名(类型,类型.); 例如: int max(int a,int b); 也可以写为: int max(int,int); ● 函数定义与函数声明的区别: 1 函数定义是指对函数功能的建立,包括指定函数名、函数类型、形参及 其类型、函数体等,它是一个完整的、独立的函数单位。 2 函数声明的作用是在程序的编译阶段对被调函数的合法性进行全面检 查,将函数名、函数返回值的类型以及形参的类型、个数和顺序通知编 译系统,以便在调用时系统进行对照检查。 3 简而言之,函数的声明是将函数定义中的第1行(函数首部)复制后再 加一个分号。 ● 可以省略函数声明的几种情况 1 被调函数的函数定义出现在主调函数之前,在主调函数中可以不对被调 函数声明而直接调用。 2 整型或字符型函数可以不加声明。系统将自动对被调函数返回值按整型 处理。 3 如果在文件的开头对函数统一进行了声明,则在各调用函数中可不再对 被调用函数加以声明。 4 调用库函数时不必进行声明,只需用#include包含相应的头文件(标准 库函数的原型在系统提供的相应头文件中)。 五、函数的调用 C语言中,函数调用的一般形式为: 函数名(实际参数表); ● 函数调用的方式: 1)函数语句:函数调用的一般形式加上分号 即构成函数语句

例如:printf("%d",a);scanf("%d",&b);2)函数表达式:函数调用作为表达式中的一项出现在表达式中,用函数返回值参与表达式的运算。这种方式要求函数是有返回值的。例如:returnx>y?x:y;z=max(x,y)3)函数实参:函数调用作为另1个函数调用的实际参数出现。这种情况是把该函数的返回值作为实参进行传送,因此要求该函数必须是有返回值的【例】函数调用作为另1个函数调用的实际参数,求4个数的最大值#include#includeint max(int x,int y);mainOtint a,b,c,d,e;printf("a=");scanf("%d",&a);printf("b=");scanf("%d",&b);printf("c=");scanf("%d",&c);printf("d=");scanf("%d",&d);e=max(max(max(a,b),c),d);//函数作为实参被调用printf("max is %din",e);getchO;1int max(int x,int y)return x>y?x:y;1「函数调用时的参数传递主调函数把实参值复制给被调函数形参的过程,称为参数传递。参数传递方式:如果使用普通变量作为函数的参数进行调用,这种方式称为按值调用(CallbyValue)。如果使用地址型数据作为函数参数进行调用,则称为按地址调用(CallbyReference)。1.按值调用(CallbyValue)1)变量作为函数参数当形参和实参是基本型变量时,参数传递的方式是按值调用(CallbyValue),形参和实参各自占用不同的存储单元。因此,函数中形参的数值变化不会导致实参的相应变化。函数只能通过return语句返回1个函数值

例如: printf("%d",a); scanf("%d",&b); 2)函数表达式:函数调用作为表达式中的一项出现在表达式中,用函数返回 值参与表达式的运算。这种方式要求函数是有返回值的。 例如: return x>y?x:y; z=max(x,y) 3)函数实参:函数调用作为另1个函数调用的实际参数出现。这种情况是把该 函数的返回值作为实参进行传送,因此要求该函数必须是有返回值的 【例】函数调用作为另1个函数调用的实际参数,求4个数的最大值 #include #include int max(int x,int y); main(){ int a,b,c,d,e; printf("a=");scanf("%d",&a); printf("b=");scanf("%d",&b); printf("c=");scanf("%d",&c); printf("d=");scanf("%d",&d); e=max(max(max(a,b),c),d); //函数作为实参被调用 printf("max is %d\n",e); getch(); } int max(int x,int y){ return x>y?x:y; } l 函数调用时的参数传递 主调函数把实参值复制给被调函数形参的过程,称为参数传递。 参数传递方式: 如果使用普通变量作为函数的参数进行调用,这种方式称为按值调用(Call by Value)。 如果使用地址型数据作为函数参数进行调用,则称为 按地址调用(Call by Reference)。 1. 按值调用(Call by Value) 1) 变量作为函数参数 当形参和实参是基本型变量时,参数传递的方式是按值调用(Call by Value),形参和实参各自占用不同的存储单元。因此,函数中形参的数值变 化不会导致实参的相应变化。函数只能通过return语句返回1个函数值

按值调用采用的就是一种“单向的值传递方式,2)数组元素作函数实参数组是一种构造类型,其中数组元素的使用等同于基本型变量,因此数组元素作函数实参时,实参和形参间也是“单向值传递。而函数的形参仍然用基本型变量,当函数调用时,把作为实参的数组元素的值传送给形参变量,从而实现单向的值传递。【例5-7】的程序段:.....int a[5],i;printf("input 5 numbersIn");for(i=0;i<5;i++)scanf("%d",&a[i]);nzp(a[]);12.按地址调用(CallbyReference)当形参和实参是地址变量、指针变量或者数组名时,实参到形参的参数传递是地址值的传递,称为按地址调用(CallbyReference)。按地址调用采用的就是一种"双向"的地址传递方式。形参和实参此时指向同一存储单元,函数中形参的数值变化直接导致了实参的相应变化,函数也可以无须通过return语句返回函数值了。1)指针作函数形参指针作函数形参时,表示形参接收的数据只能是一个地址值。写一个新的swapO函数来尝试交换x,y的值:swap(int *a, int *b)int t;t=*a, *a=*b, *b=t;1【例】用指针作函数参数实现两个数的交换。2)数组名作为函数参数用不带方括号的数组名作为实参调用函数,可以把一个数组传递给一个函数用数组名作实参实际上是将数组的首地址传给被调函数,使形参数组与实参数组具有相同的首地址,实际占用同一段存储单元

按值调用采用的就是一种"单向"的值传递方式。 2)数组元素作函数实参 数组是一种构造类型,其中数组元素的使用等同于基本型变量,因此数组 元素作函数实参时,实参和形参间也是"单向"值传递。而函数的形参仍然用基 本型变量,当函数调用时,把作为实参的数组元素的值传送给形参变量,从而 实现单向的值传递。 【例5-7】的程序段: . . int a[5],i; printf("input 5 numbers\n"); for(i=0;i<5;i++){ scanf("%d",&a[i]); nzp(a[i]); } 2 .按地址调用(Call by Reference) 当形参和实参是地址变量、指针变量或者数组名时,实参到形参的参数传递是 地址值的传递,称为按地址调用(Call by Reference)。按地址调用采用的就 是一种"双向"的地址传递方式。形参和实参此时指向同一存储单元,函数中形 参的数值变化直接导致了实参的相应变化,函数也可以无须通过return语句返 回函数值了。 1)指针作函数形参 指针作函数形参时,表示形参接收的数据只能是一个地址值。 写一个新的swap()函数来尝试交换x,y的值: swap(int *a, int *b){ int t; t=*a, *a=*b, *b=t; } 【例】用指针作函数参数实现两个数的交换。 2 ) 数组名作为函数参数 用不带方括号的数组名作为实参调用函数,可以把一个数组传递给一个函数 。 用数组名作实参实际上是将数组的首地址传给被调函数,使形参数组与实参数 组具有相同的首地址,实际占用同一段存储单元

【例】用数组名作函数参数实现数组元素平均值的求解1/数组a中存放了1个学生5门课程的成绩,求平均成绩floataver(floata[l)int i;float avr,s=a[0]for(i=1;i<5;i++)s=s+a[i];avr=s/5;return avr;mainOtfloat sco[5],avr;int i;printf("ninput 5 scores:In");for(i=0;i<5;i++)scanf("%f",&sco[i]);avr=aver(sco);printf("average score is %5.2f",avr);getch);使用数组名作为函数参数时还应注意以下问题:。形参数组和实参数组的类型必须一致,否则将引起错误。。因为在调用时,只传送首地址而不检查形参数组的长度。当形参数组的长度与实参数组不一致时,虽不至于出现语法错误(编译能通过),但程序执行结果将与实际不符。。在函数中为了防止对形参数组的赋值,可以在该形参数组声明中加限定词const。I/数组求和c=a+bvoid add(const int a[l,const int bl,int c,int n)int i;for(i=0;i<n;++i)c[]=a[]+b[];1mainOtint i,x[5]=[1,3,5,7,9],y[5]=[10,8,6,4,2],z[5];add(x,y,z,5);for(i=0;i<5;i++) printf("%4d",z[i]);getch();+

【例】用数组名作函数参数实现数组元素平均值的求解 //数组a中存放了1个学生5门课程的成绩,求平均成绩。 float aver(float a[]){ int i; float avr,s=a[0]; for(i=1;i<5;i++) s=s+a[i]; avr=s/5; return avr; } main(){ float sco[5],avr; int i; printf("\ninput 5 scores:\n"); for(i=0;i<5;i++) scanf("%f",&sco[i]); avr=aver(sco); printf("average score is %5.2f",avr); getch(); } 使用数组名作为函数参数时还应注意以下问题: ● 形参数组和实参数组的类型必须一致,否则将引起错误。 ● 因为在调用时,只传送首地址而不检查形参数组的长度。当形参数组的 长度与实参数组不一致时,虽不至于出现语法错误(编译能通过),但程 序执行结果将与实际不符。 ● 在函数中为了防止对形参数组的赋值,可以在该形参数组声明中加限定 词const。 //数组求和 c=a+b void add(const int a[],const int b[],int c[],int n){ int i; for(i=0;i<n;++i) c[i]=a[i]+b[i]; } main(){ int i,x[5]={1,3,5,7,9},y[5]={10,8,6,4,2},z[5]; add(x,y,z,5); for(i=0;i<5;i++) printf("%4d",z[i]); getch(); }

六、函数的嵌套调用和递归调用·函数的嵌套调用语言中不充许作嵌套的函数定义。但是C语言充允许在1个函数的定义中出现对另1个函数的调用。这样就出现了函数的嵌套调用。即在被调函数中又调用其它函数。【例】sum=1!+2!+3!+.....+10。mainO函数+sumO函数+facto函数6·函数的递归调用为了说明递归的含义,这里先举1个例子:有1排5个学生,老师依次询问他们的年龄。通常的回答该方式是每个同学都直接告诉老师自己的年龄,这样,老师只要询问5次就可以知道他们的年龄了。另外1种就是递归的方式了:老师问第1位学生时,回答说"我比第2个同学大2岁"。老师问第2位学生时,回答说"我比第3个同学小3岁"。老师问第3位学生时,回答说"我比第4个同学大4岁"。老师问第4位学生时,回答说"我比第5个同学大1岁"。老师问第5位学生时,如果他仍然是这样作答的话,显然就不能得出任何1个学生的年龄了!因此,最后这第5位学生必须告诉老师他的年龄了。假设他说的是我今年18岁了",那么根据前面同学的回答就可以一次算出第4到第1位学生的年龄分别是19岁、23岁、20岁、22岁。故事中,老师通过5次询问(回溯)和4次计算(递归),得到了这5个学生的年龄。其"运算次数"比第1种直接回答方式的5次多了1倍,并且要求老师准确地记住每个同学的回答,错记或忘记了1个就会导致之前同学年龄求不出来了,也就是说,“系统开销加大了递归算法是一个相对缓慢的过程,但是有些问题则只能用递归算法才能实现。典型的问题有Hanoi塔问题等。在C语言当中,可以充许函数直接或间接地调用自己,这种函数的调用方式称为递归调用。而含有递归调用的函数称为递归函数。在执行1个函数中出现所要调用的函数又是自己,称为直接递归调用。而通过别的函数来达到自己调用自己的方式称为间接递归调

六、函数的嵌套调用和递归调用 ● 函数的嵌套调用 语言中不允许作嵌套的函数定义。但是C语言允许在1个函数的定义中出现对 另1个函数的调用。这样就出现了函数的嵌套调用。即在被调函数中又调用其 它函数。 【例】sum=1!+2!+3!+.+10!。 main()函数 + sum()函数 + fact()函数 ● ● 函数的递归调用 为了说明递归的含义,这里先举1个例子: 有1排5个学生,老师依次询问他们的年龄。通常的回答该方式是每个同学都直 接告诉老师自己的年龄,这样,老师只要询问5次就可以知道他们的年龄了。 另外1种就是递归的方式了: 老师问第1位学生时,回答说"我比第2个同学大2岁"。 老师问第2位学生时,回答说"我比第3个同学小3岁"。 老师问第3位学生时,回答说"我比第4个同学大4岁"。 老师问第4位学生时,回答说"我比第5个同学大1岁"。 老师问第5位学生时,如果他仍然是这样作答的话,显然就不能得出任何1个学 生的年龄了! 因此,最后这第5位学生必须告诉老师他的年龄了。 假设他说的是"我今年18岁了",那么根据前面同学的回答就可以一次算出第4 到第1位学生的年龄分别是19岁、23岁、20岁、22岁。 故事中,老师通过5次询问(回溯)和4次计算(递归),得到了这5个学生的 年龄。其"运算次数"比第1种直接回答方式的5次多了1倍,并且要求老师准确 地记住每个同学的回答,错记或忘记了1个就会导致之前同学年龄求不出来 了,也就是说,"系统开销"加大了。 递归算法是一个相对缓慢的过程,但是有些问题则只能用递归算法才能实现。 典型的问题有Hanoi塔问题等。 在C语言当中,可以允许函数直接或间接地调用自己,这种函数的调用方式称 为递归调用。而含有递归调用的函数称为递归函数。在执行1个函数中出现所 要调用的函数又是自己,称为直接递归调用。而通过别的函数来达到自己调用 自己的方式称为间接递归调

满足递归关系的函数要有:(1)函数初始条件;(2)初始条件个数不少于递归函数中表达式的个数。否则递归没有终结,程序出现死循环。递归算法的特点:(1)程序执行速度慢于递推算法;2n-2+1次(2)算法设计容易,程序可读性好。图解执行过程【例】用递归法计算n!#include#includemainOtlong fact(int)int n;printf("ninput n: ");scanf("%d",&n);printf("%d!=%ld)n",n,fact(n);getch();1

满足递归关系的函数要有: (1)函数初始条件; (2)初始条件个数不少于递归函数中表达式的个数。 否则递归没有终结,程序出现死循环。 递归算法的特点: (1)程序执行速度慢于递推算法;2 n-2+1 次 (2)算法设计容易,程序可读性好。 图解执行过程 【例】用递归法计算n! #include #include main(){ long fact(int); int n; printf("\ninput n: "); scanf("%d",&n); printf("%d!=%ld\n",n,fact(n)); getch(); }

共18页,试读已结束,阅读完整版请下载
刷新页面下载完整文档
VIP每日下载上限内不扣除下载券和下载次数;
按次数下载不扣除下载券;
注册用户24小时内重复下载只扣除一次;
顺序:VIP每日次数-->可用次数-->下载券;
相关文档