第五章 程序设计初步
概述
本章前三节将通过一些具体的Pascal程序实例来帮助学生了解Pascal程序的基本结构,掌握程序的三种基本结构:顺序结构、选择结构、循环结构,了解使用用户自定义数据类型:枚举类型、子界类型及数组类型进行数据定义的方法。第四节,介绍了函数和过程的有关知识,包括函数和过程的递归调用以及其它一些基本算法,通过阅读程序和尝试编写简单程序让学生能够掌握定义、编写和调用函数和过程的方法。最后,在本章第五节中介绍了面向对象的程序设计,要求学生在前几节的内容上,进一步体会编写大型程序或复杂程序的困难性,从中领会面向对象设计思想的精髓所在。
本章的主要内容
节名 教学内容
顺序结构程序设计 通过一些具体的Pascal程序来介绍顺序结构程序设计的编程思想,其中着重介绍了赋值语句、输入语句、输出语句、复合语句的使用方法。
选择结构程序设计 通过一些具体的Pascal程序来介绍选择(分支)结构程序设计的编程思想,其中还针对IF语句、Case语句作了较为深入详细的介绍和比较。
循环结构程序设计 通过一些具体的Pascal程序来介绍循环(重复)结构程序设计的编程思想,其中详细介绍了三种循环语句:For语句、While语句、Repeat语句,本节后半部分还详细介绍了有关循环嵌套的知识及三种用户自定义数据类型:枚举类型、子界类型和数组类型。
函数和过程 通过一些具体的Pascal程序来对函数和过程作了较为详细深入的介绍,其中包括函数或过程调用时的形式参数、实际参数、和标示符的作用域等相关知识,最后,介绍了函数或过程的递归调用的使用方法。
面向对象程序设计 能够熟悉与面向对象方法有关的六个重要概念,能够了解当今比较流行的几种面向对象语言;学习程序示例是如何编写面向对象程序的。
第四节 函数和过程
一、教材分析
教学目标
目标 实现
知识 掌握在编程过程中自定义函数和过程的方法。 贯穿于整个教学活动过程中
掌握函数和过程在程序中的调用方法、理解形式参数和实际参数、标识符的作用域。 上机实践:学生练习为主,教师辅导为辅,结合上机实践。
掌握函数和过程的递归调用
技能 能够使用函数和过程编写pascal程序。 贯穿于整个上机实践的过程之中
能够运用函数和过程的递归调用解决实际问题 贯穿于整个教学活动过程中
情感态度价值观 培养严谨的程序编写的风格的习惯,体验编写pascal程序的过程,激发学生学习编写程序的兴趣和学习热情 贯穿于上机实践的整个过程之中
养成独立分析、善于归纳总结的习惯 贯穿于整个教学活动过程中。
教学重点与难点
在编写大型的程序时,需要将程序分解为几个小模块,这样,不仅有利于程序代码的编写、也会使程序代码显得清晰易于查错。在Turbo Pascal中,可以通过自定义函数和过程的方法来实现程序的模块化。通过本节的学习,就是要让学生学会运用自定义函数和过程的方法来编写程序代码,以及函数和过程调用的相关知识。本节的难点是如何运用函数和过程的递归调用来编写程序代码解决生活中的实际问题。
二、教学建议
课时安排建议
本节内容建议用2课时完成。第1课时学习自定义函数和过程的定义、调用方法;第2课时则通过实际操作和上机调试体会自定义函数、过程在程序中的作用和形式参数、实际参数、标识符的作用和区别。
教学准备
1.机房准备
编写pascal程序对机房的软硬件配置要求不高,操作系统选择Windows 98、Windows 2000或Windows XP均可,CPU为Pentium以上即可,内存为32M(Windows 98)以上,每位学生一台计算机。
2.教师准备
熟练掌握Turbo Pascal 7.0和一些基本的常用算法。搜集整理一些常用的算法分析题例放在教师机上;提供一些专业的算法分析和pascal程序设计网站的索引供学生学习使用。
3.学生准备
具备基本的信息技术操作技能,包括鼠标、键盘使用,文字输入等。
教学过程安排建议
1.导入新课,提出问题
在编写程序代码时,将程序分解为几个模块,这样,不仅有利于程序代码的编写、也会使程序代码显得清晰易于查错。在Turbo Pascal中,可以通过自定义函数和过程的方法来实现程序的模块化。教师可以展示几个使用自定义函数和过程的程序,让学生寻找其中的自定义函数和过程,发掘一下自定义函数和过程与常用的语句之间有什么差别和共通点。
2.学习自定义函数
(1)函数的定义:
Turbo Pascal语言除了提供标准函数供用户使用之外,还允许用户自定义函数。在Turbo Pascal语言中,函数说明形式具体如下
Function 函数名(形式参数表):函数类型;
说明部分;
Begin
语句1;
语句2;
……;
语句n;
End;
说明:函数分为两部分:函数首部和函数体。
函数首部由保留字Function、函数名(参数列表):函数类型组成,以分号表示结束。
Function 函数名(形式参数表):函数类型;
函数首部中包含了函数名、函数形式参数的信息及函数返回值的数据类型。
函数体由函数说明和函数执行两个部分组成。函数说明部分用于定义和说明函数中用到的数据,包括单元说明、标号说明、常量说明、类型说明、变量说明。
函数执行部分描述了函数要执行的操作,以保留字“Begin”作为函数开始的标识,以保留字“End;”表示函数结束。其间是一些执行具体操作的语句,并且以分号作为语句之间的分隔符。
和Turbo Pascal语言提供的标准函数一样,用户自定义函数也有一个函数的返回值。用户自定义函数的调用方式同标准函数一样,都是通过表达式的形式来调用函数。
(2)上机实践:
学生上机编写程序:用自定义函数的方法来定义n!。其中n!=1*2*3*…*n。
此过程的目的就是通过上机实践让学生能灵活自定义函数的方法进行程序的编写,也是学生将知识从理论转化为实践的过程,教师在此过程中应关注每一位学生知识的具体掌握情况,要有针对性地加以个别辅导,务必使每一位学生读能真正掌握自定义函数的语法格式,如何在函数中设置函数返回值的语句,在具体的编程过程中做到灵活自定义函数来简化程序,实现模块编程。
(3)小结:
在函数体中至少要有一条语句对函数名赋值。
3.学习过程
(1)定义
和函数一样,Turbo Pascal语言除了提供标准过程供用户使用之外,也允许用户自定义过程。在Turbo Pascal语言中,过程说明形式具体如下:
Procedure 过程名(形式参数表);
说明部分;
Begin
语句1;
语句2;
……;
语句n;
End;
说明:过程分为两部分:过程首部和过程体。
过程首部由保留字procedure、过程名(参数列表)组成,以分号表示结束。
Procedure 过程名(形式参数表);
过程首部中包含了过程名、过程形式参数信息。
过程体由过程说明和过程执行两个部分组成。过程说明部分用于定义和说明过程中用到的数据,包括单元说明、标号说明、常量说明、类型说明、变量说明。
过程执行部分描述了过程要执行的操作,以保留字“Begin”作为过程开始的标识,以保留字“End;”表示过程结束。其间是一些执行具体操作的语句,并且以分号作为语句之间的分隔符。
(2)上机实践:
学生上机编写程序:用自定义过程的方法来定义n!。其中n!=1*2*3*…*n。
此过程的目的就是通过上机实践让学生能灵活自定义过程的方法进行程序的编写,也是学生将知识从理论转化为实践的过程,教师在此过程中应关注每一位学生知识的具体掌握情况,要有针对性地加以个别辅导,务必使每一位学生读能真正掌握自定义过程的语法格式,在具体的编程过程中做到灵活自定义过程来简化程序,实现模块编程。
4.学习形式参数和实际参数、标识符的作用域
教师介绍函数和过程调用时的实行参数和实际参数的知识,学生主要应掌握值参数和变量参数,知道两者的区别,教师了借助表格的形式进行归纳,让学生易于理解和掌握。
学生应掌握如何在程序中定义和使用全局变量、局部变量,知道两者的区别,知道何时该使用全局变量、何时该使用局部变量。
5.学习递归
(1)概念
递归就是函数或过程调用其本身。递归分为两类:直接递归和间接递归。直接递归就是函数或过程直接调用自己。而间接递归就是函数或过程a调用函数或过程b,而b又调用a。
直接递归的调用过程可参考下图:
图 直接递归过程的执行流程
(2)上机实践:
楼梯有N阶,上楼可以一步上一阶,也可以一次上二阶。编一个程序,计算共有多少种不同的走法。
分析:
每次上楼可以一步上一阶,也可以一次上二阶。要到达第N阶楼梯,有以下两种走法:一种走法是从第N-1阶走一阶到达第N阶,还有一种走法就是从第N-2阶走二阶到达第N阶。若用s(N)表示到达第N阶的走法,s(N-1)表示到达第N-1阶的走法,s(N-2)表示到达第N-2阶的走法,则有如下等式:s(N)=s(N-1)+s(N-2),从这个等式中可以看出,计算到达第N阶的所有走法s(N)可归结为计算到达第N-1阶的所有走法s(N-1)和第N-2阶的所有走法s(N-2)的问题,然后只需将s(N-1)与s(N-2)相加就能计算出s(N),而计算第N-1阶的所有走法s(N-1)又可以归结为计算第N-2阶的所有走法s(N-2)和第N-3阶的所有走法s(N-3)就可以了,如此推理,就可以一直倒推到到达2阶的所有走法s(2)和到达1阶的所有走法s(1),根据题中所给的条件,到达第1阶的走法只有一种可能,,所以可以得出:s(1)=1,而到达第2阶有两种走法,一是先到第一阶,然后再走到第2阶,二是直接走到第2阶,所以,可以得出:s(2)=2,然后再反过来一次计算出到达第3阶的所有走法s(3),到达第4阶的所有走法s(4),……,直到最后求出到达第N阶的所有走法s(N)。
教师提供参考程序如下:
program upstairs;
var n:Integer;
function s(n:Integer):Longint;
begin
if (n=1)Or(n=2) then s:=n
else s:=s(n-1)+s(n-2);
end;
begin
repeat
write('N=');readln(n);
until n>0;
writeln('s=',s(n));
readln;
end.
学生上机模拟跟踪程序(n=5时)的整个运行过程,记录下各变量在程序运行过程中具体的数值。并尝试画出递归调用示意图。
递归调用示意图参考如下:
(3)上机练习:
在学生了解递归原理的基础上编写程序汉诺塔。教师在此过程中应关注每一位学生知识的具体掌握情况,要有针对性地加以个别辅导,务必使每一位学生读能真正掌握递归的原理和编程方法。
(4)小结:
递归算法是计算机程序设计中的一种非常重要的算法。用递归算法编写的程序一般较为简短,但运行时会占用比较多的资源,速度较慢。
在考虑使用递归算法编写程序时,应满足两点:1)该问题能够被递归形式描述;2)存在递归结束的边界条件。
6.课后上机练习
结合课后的上机练习题多加练习,巩固所学。
靶向练习
上机练习题:
1.编写一计算三角形面积的函数,利用这个计算五边形的面积。如图5-4-3所示:
参考程序:
program ex5401;
var
a,b,c,d,e,f,g,s:real;
function ts(a1,b1,c1:real):real;
var
p:real;
begin
p:=(a1+b1+c1)/2;
ts:=sqrt(p*(p-a1)*(p-b1)*(p-c1));
end;
begin
readln(a,b,c,d,e,f,g);
s:=ts(a,b,f)+ts(f,c,g)+ts(d,e,g);
writeln('area=',s:8:3);
end.
2.计算s。已知s=1!+2!+3!+…+10!
参考程序:
program ex5402;
var
i:integer;
s:longint;
function f(m:integer):longint;
begin
if m=0
then f:=1
else f:=f(m-1)*m;
end;
begin
s:=0;
for i:=1 to 10 do
s:=s+f(i);
writeln('1!+2!+...+10!=',s);
end.
3.用函数和过程两种方法来定义n!。 其中n!=1*2*3*…*n。
参考程序:
用函数来定义n!:
program ex540301;
var
n:integer;
function jiec(n:integer):longint;
var
i:integer;
s:longint;
begin
s:=1;
for i:=2 to n do
s:=s * i;
jiec:=s;
end;
begin
read(n);
writeln(jiec(n));
end.
用过程来定义n!:
program ex540302;
var
n:integer;
ans:longint;
procedure jiec(n:integer;var ans:longint);
var
i:integer;
begin
ans:=1 ;
for i:=1 to n do
ans:=ans*i;
end;
begin
writeln('N= ');
readln(n);
jiec(n,ans);
writeln(ans);
end.
4.利用递归调用手段编程计算N!。
参考程序:
program ex5404;
var
n:integer;
function f(m:integer):real;
begin
if m=0
then f:=1
else f:=f(m-1)*m;
end;
begin
write('n= ');
readln(n);
write(f(n):1:0);
end.
5.利用递归调用技术求菲波纳契数列的第N项。
参考程序:
program ex5405;
var
n:integer;
function f(m:integer):real;
begin
if m=0
then f:=0
else if m=1
then f:=1
else f:=f(m-1)+f(m-2);
end;
begin
write('n= ');
readln(n);
write(f(n):1:0);
end.
6.汉诺塔游戏:相传在古印度的布拉玛婆罗门圣庙的僧侣在进行一种被称为汉诺塔的游戏,其装置是一块铜板,上面有三根杆(编号A、B、C),A杆上自下而上、由大到小按顺序串上64个金盘(如图5-4-4所示)。游戏的目标是把A杆上的金盘全部移到C杆上,并保持原有顺序叠好。条件是每次只能移动一个盘,并且每次移动都不允许大盘移到小盘之上。现要求利用递归调用技术推导出N个盘从A杆移到C杆的移动过程。
图5-4-4 N阶汉诺塔
参考程序:
program ex5406;
var
total:integer;
procedure move(n,a,b,c:integer);
begin
if n=1
then writeln(a,'-->',c)
else
begin
move(n-1,a,c,b);
writeln(a,'-->',c);
move(n-1,b,a,c);
end;
end;
begin
readln(total);
move(total,1,2,3);
end.
7.某人写了n封信和n个信封,如果所有的信都装错了信封。求所有的信都装错信封共有多少种不同情况。
参考程序:
program ex5407;
var
a:array[1..100]of integer;
ok:array[1..100]of boolean;
tot:longint;
n:integer;
procedure sub(s:integer);
var i:integer;
begin
if s>n then inc(tot)
else
for i:=1 to n do
if (i<>s) and ok[i]then begin
ok[i]:=false;
sub(s+1);
ok[i]:=true;
end;
end;
begin
writeln('N=');
readln(n) ;
tot:=0;
fillchar(ok,sizeof(ok),true);
sub(1);
writeln(tot);
end.
8.设有2n个运动员要进行网球比赛。现要设计一个满足以下要求的比赛日程表:
(1)每个选手必须与其他n-1个选手各赛一次;
(2)每个选手每天只能参赛一次;
(3)循环赛在n-1天内结束。
参考程序:
9.数学宝塔,从最顶上走到最底层,每次只能走到下一层的左边或右边的数字,求出使所走到的所有数字之和为60的途径。
7
4 6
6 9 3
6 3 7 1
2 5 3 2 8
5 9 4 7 3 2
6 4 1 8 5 6 3
3 9 7 6 8 4 1 5
2 5 7 3 5 7 8 4 2
参考程序:
program ex5409;
var
a:array[1..9,1..9]of byte;
rou,i,j:integer;
ans:array[1..8]of char;
time:longint;
procedure print;
var
i:integer;
begin
if rou=60
then begin
inc(time);
write('Route ',time,': ');
for i:=1 to 7 do write(ans[i]);
writeln(ans[8]);
end;
end;
procedure sub(s,p:integer);
var
i:integer;
begin
if rou>60 then exit;
if s>8
then print
else for i:=0 to 1 do begin
inc(rou,a[s+1,p+i]);
if i=0 then ans[s]:='L'else ans[s]:='R';
sub(s+1,p+i);
dec(rou,a[s+1,p+i]);
end;
end;
begin
a[1,1]:=7;
a[2,1]:=4;
a[2,2]:=6;
a[3,1]:=6;
a[3,2]:=9;
a[3,3]:=3;
a[4,1]:=6;
a[4,2]:=3;
a[4,3]:=7;
a[4,4]:=1;
a[5,1]:=2;
a[5,2]:=5;
a[5,3]:=3;
a[5,4]:=2;
a[5,5]:=8;
a[6,1]:=5;
a[6,2]:=9;
a[6,3]:=4;
a[6,4]:=7;
a[6,5]:=3;
a[6,6]:=2;
a[7,1]:=6;
a[7,2]:=4;
a[7,3]:=1;
a[7,4]:=8;
a[7,5]:=5;
a[7,6]:=6;
a[7,7]:=3;
a[8,1]:=3;
a[8,2]:=9;
a[8,3]:=7;
a[8,4]:=6;
a[8,5]:=8;
a[8,6]:=4;
a[8,7]:=1;
a[8,8]:=5;
a[9,1]:=2;
a[9,2]:=5;
a[9,3]:=7;
a[9,4]:=3;
a[9,5]:=5;
a[9,6]:=7;
a[9,7]:=8;
a[9,8]:=4;
a[9,9]:=2;
rou:=a[1,1];
time:=0;
sub(1,1);
end.
10.顺序读入字符,以‘?’结束,然后以和输入相反的次序输出读入的字符,要求用递归实现。
参考程序:
program ex5410;
procedure main;
var c:char;
begin
read(c);
if c=' '
then exit
else begin
main;
write(c);
end;
end;
begin
main;
end.
a
b
c
d
e
f
g
图5-4-3 计算五边形的面积