教师 (pascal 串讲 ) 培训讲习

154
教教 (PASCAL 教教 ) 教教教教

Upload: fadey

Post on 15-Jan-2016

214 views

Category:

Documents


0 download

DESCRIPTION

教师 (PASCAL 串讲 ) 培训讲习. 序言:信息学奥赛的发展. 1989 年 5 月首次举办国际信息学奥林匹克竞赛,简称 IOI ,成为继数学、物理、化学之后的又一门国际(中学生)奥林匹克竞赛。 1991 年起全国青少年计算机竞赛更名为全国青少年信息学(计算机)奥林匹克竞赛,简称 NOI 。由中国科学技术协会主管,中国计算机学会主办。 全国青少年信息学奥林匹克联赛,简称为 NOIP ,参加联赛是参加 NOI 的必要条件。. 信息学奥林匹克竞赛内容. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 教师 (PASCAL 串讲 ) 培训讲习

教师 (PASCAL 串讲 ) 培训讲习

Page 2: 教师 (PASCAL 串讲 ) 培训讲习

序言:信息学奥赛的发展序言:信息学奥赛的发展 1989 年 5 月首次举办国际信息学奥林匹克竞赛,简称 IOI ,

成为继数学、物理、化学之后的又一门国际(中学生)奥林匹克竞赛。

1991 年起全国青少年计算机竞赛更名为全国青少年信息学(计算机)奥林匹克竞赛,简称 NOI 。由中国科学技术协会主管,中国计算机学会主办。

全国青少年信息学奥林匹克联赛,简称为 NOIP ,参加联赛是参加 NOI 的必要条件。

Page 3: 教师 (PASCAL 串讲 ) 培训讲习

信息学奥林匹克竞赛内容信息学奥林匹克竞赛内容1.1. 程序设计知识。熟练使用一门程序设计语言程序设计知识。熟练使用一门程序设计语言

编写程序;熟悉常用的基本算法:如穷举法、编写程序;熟悉常用的基本算法:如穷举法、排序(冒泡)法、搜索法、回溯法、递归算排序(冒泡)法、搜索法、回溯法、递归算法,排列组合等。法,排列组合等。

2.2. 数据结构知识。简单变量、数组、队列、栈、数据结构知识。简单变量、数组、队列、栈、串、记录、指针、链表、树、图和文件。串、记录、指针、链表、树、图和文件。

3.3. 调试程序技能。调试程序技能。

Page 4: 教师 (PASCAL 串讲 ) 培训讲习

第 1 课 认识 PASCAL 语言Pascal 是一种计算机通用的、编译型的高级程

序设计语言。它由瑞士 Niklaus Wirth 教授于六十年代末设计并创立。是一种按结构化程序设计原则描述的高级语言。主要特点有:严格的结构化形式;丰富完备的数据类型;运行效率高;查错能力强。NOI( 全国奥林匹克信息学竞赛 ) 把 Pascal 语言定为唯一提倡的程序设计语言

Page 5: 教师 (PASCAL 串讲 ) 培训讲习

第 1 课 认识 PASCAL 语言让我们先来看一个 PASCAL 程序,通过这个程序了解 PASCAL 的规则。例 L1_1 已知半径,求圆周长和面积的程序。

Page 6: 教师 (PASCAL 串讲 ) 培训讲习

程序说明:PROGRAM circle(input,output); (* 第 1 行:程序首部 *)CONST(* 第 2 行:常量说明 *)PI=3.14159; VAR(* 第 4 行:变量说明 *)r,l,s:real; BEGIN(* 第 6 行:语句部分 *)read(r); (* 第 7 行:输入语句 *)l:=2*PI*r; (* 第 8 行:赋值语句 * ,计算周长 )s:=PI*r*r; (* 第 9 行:赋值语句 * ,计算面积 )write(r,l,s); (* 第 10 行:输出语句 *) END. (* 第 11 行:语句部分以 END. 结束 *)

Page 7: 教师 (PASCAL 串讲 ) 培训讲习

完整的 PASCAL 程序框架Program 程序名(程序参数表) ;

Label 标号说明; Const 常量说明; Type 类型说明; Var 变量说明; Function 函数说明; procedure 过程说明; begin 程序语句; …… end.

•在在 Free Pascal Free Pascal 中可省程序参数表。中可省程序参数表。• 在程序执行部分使用的标号、常在程序执行部分使用的标号、常量、类型、变量、记录、文件、过量、类型、变量、记录、文件、过程和函数,都必须在说明部分进行程和函数,都必须在说明部分进行说明。但并不是每个程序都必需的,说明。但并不是每个程序都必需的,根据需要而设。根据需要而设。• 程序执行部分是指程序执行部分是指 BeginBegin 开始到开始到最后一条最后一条 End. End. 结束语句的部分,结束语句的部分,是程序的核心。它由一系列语句组是程序的核心。它由一系列语句组成,语句之间用“;”隔开,允许成,语句之间用“;”隔开,允许一行写多个语句,也允许一个语句一行写多个语句,也允许一个语句写成几行。一般情况下一行只写一写成几行。一般情况下一行只写一个语句。个语句。

Page 8: 教师 (PASCAL 串讲 ) 培训讲习

1 、 PROGRAM写在最左边顶格;2、注释的大括号 {、和 CONST 、 VAR、 BEGIN 、

END等语句上下对齐,且它们比 PROGRAM向右移两个字符;3、各个语句和程序语句也是上下对齐,它们比第2点中的各语句又向右移两个字符;4、语句间多余空格与空行,编译时会忽略。

程序的书写格式:程序的书写格式:

Page 9: 教师 (PASCAL 串讲 ) 培训讲习

数制的转换1 、常用的进位计数制有:十进制、二进制、八进制、十六进制。

名称 基数 标志符

十进制

0, 1 , 2, 3,4, 5 , 6, 7,8 , 9 ,

D

二进制

0, 1 B

八进制

0, 1 , 2, 3,4, 5 , 6, 7

Q

十六进制

0, 1 , 2, 3,4, 5 , 6, 7,8 , 9 , A , B ,C , D, E , F

H

十进制D 二进制 B 八进制Q 十六进制H0 0000 0 0

1 0001 1 1

2 0010 2 2

3 0011 3 3

4 0100 4 4

5 0101 5 5

6 0110 6 6

7 0111 7 7

8 1000 10 8

9 1001 11 9

10 1010 12 A

11 1011 13 B

12 1100 14 C

13 1101 15 D

14 1110 16 E

15 1111 17 F

16 10000 20 10

22、常用进制对照表、常用进制对照表

Page 10: 教师 (PASCAL 串讲 ) 培训讲习

3、十进制与二进制的相互转换例 1 :将十进制数 20.6875转换成二进制数。( 1 )整数部分的转换:“除以 2倒序取余法”。2 20 0 2 10 0 2 5 1 2 2 0 2 1 1 0

( 2)小数部分的转换:“乘 2取整法”。 0.6875 0.3750 0.75 0.5 × 2 × 2 × 2 × 2 1.3750 0.75 1.5 1.0 1 0 1 1

正序取整

倒序取

余合在一起得:

( 20.6875 ) 10

=( 10100.1011 ) 2

Page 11: 教师 (PASCAL 串讲 ) 培训讲习

例 2:将( 11001.0101 ) 2转换成十进制数。

( 11001.1101 ) 2 = 1×24+1×23+0×22+0×21+1×20+1×2-1+1×2-2 +0×2-3+1×2-4 =16+8+1+0.5+0.25+0.0625 =( 25.8125 ) 10

十进制数和二进制数的转换可以推广 到十进制与八进制、十进制与十六进制数的转换。

如十进制数转换在八进制数的方法是:“除以 8倒取余法”;十进制小数转换成八进

制小数的方法是:“乘 8取整法”。

课堂作业:( 1 )( 1101101.101 ) 2 =( ) 10

( 2) ( 45.625 ) 10 =( ) 2

Page 12: 教师 (PASCAL 串讲 ) 培训讲习

第 2课 PASCAL 的数据类型、标识符、表达式、语句

数据对于一门程序语言是非常重要的,数据的一个非常重要的特征就是它的类型。 PASCAL 规定:程序中出现的变量必须先说明才能使用。

二个值 ,即

Page 13: 教师 (PASCAL 串讲 ) 培训讲习

整数类型 包括正整数( +号可略)、负整数和零。 1 , 204在会计统计中是允许的,但在 pascal 中是非法的。 整数类型的标识符为 integer, 取值范围为: -32768≤n ≤32767。 在 free pascal 中,允许整数采用十六进制(前加 $)或二进制 (前加%)表示。 如 x := %101, 相当于 x:=5 , y:=$10, 相当于 y:=16 整数的类型:

名称 类型标识符 数据范围短整型 Shortint -128~127

长整型 Longint -2147483648~2147483647

字节型 Byte 0~255

字型 Word 0~65535

整数类型 Int64 -9223372036854775808~9223372036854775807

无符号整数 Qword int64 0~18446744073709551615

注意: int64 不是有序类型。直接给一个 int64 类型的变量赋值一个超过 longint 范围的整数是非法的,这是因为 free pascal 在表达式的计算中默认最大类型为 longint 。

Page 14: 教师 (PASCAL 串讲 ) 培训讲习
Page 15: 教师 (PASCAL 串讲 ) 培训讲习

标识符 标识符是以字母开头的字母、数字组合,用来表示常

量、变量、类型、文件、函数、过程或程序的名字。 x, y , max, min , sum , a15 , a3b7都是合法的标识符。而

5x, x-y , α, π, ε, ex10.5 都是非法的标识符。 标识符的长度一般不要超过 8 个字符。 标识符的选取最好有一定意义,这样便于记忆,也增

加了程序的可读性。

Page 16: 教师 (PASCAL 串讲 ) 培训讲习

表达式和运算符 算术运算符 : + , - , * , /, div (整除) , mod (取余) 关系运算符: =, >, <, <=, >=, <>, 逻辑运算符: AND , OR , NOT

表达式就是将数据和运算符结合使用,组成一组有意义的运算式。 在 PASCAL 语言中规定,表达式按下列运算优先规则计算:1 、所有括起来的子表达式必须先计算,且子表达式必须从里到外计算;2 、在同一子表达式中的运算符按下列次序计算: ①函数;② NOT ;③ AND , * , / , DIV , MOD ; ④OR , + , - ; ⑤ < , <= , = , > , >= , <>3 、在同一个子表达式中,同一优先级的运算按从左到右的次序进行。4 、 MOD 运算结果的符号总是和被除数相同,而与模无关。 -15 mod 6 = -3 -15 mod (-6) = -3 15 mod (-6) =3

Page 17: 教师 (PASCAL 串讲 ) 培训讲习

PASCAL 程序中的运算优先规则

Page 18: 教师 (PASCAL 串讲 ) 培训讲习

常量与变量 常量定义格式: const <常量标识符 > = <常量 >;

要求如下:1 、要放在程序说明部分。2、必须遵循先定义后使用的

原则。3、不允许重复定义,或一次

定义多个常量。

例如: const a =1; a,b = 10; c = 1 or 2; d := 3;

变量定义格式: var <变量名表 > :类型标识符 ;

例如: var a,b :integer; x,y :real; ch :char; t: boolran;但下列说明是非法的:例如: var a,b =integer; ch :char; ch :boolean; a,b 后面不能用 =, ch 不能重复定义。变量一经说明,系统就为其分配内存。程序中使用该变

量时,就要在相应的内存单元读写数据,称为对变量的访问。

Page 19: 教师 (PASCAL 串讲 ) 培训讲习

常用函数常用函数与表达式与表达式

Page 20: 教师 (PASCAL 串讲 ) 培训讲习

顺序结构程序设计1 、赋值语句 赋值语句的格式: 变量标识符 : = 表达式; 功能: 赋值语句是先执行计算表达式的值,然后赋值给变量标识符。 说明:( 1 )” := “ 称为赋值号,不要与 ” = “ 混淆。赋值有方向性,左边只能是变量,

不能是表达式,如 – x := 1 是非法的。( 2)赋值号两边的类型必须相同,但是整型表达式可以赋值给实型,反之不成立。( 3)一个赋值语句只能给一个变量赋值,变量可以赋值多次,但只保留最后一次的值。

( 4)被赋值的变量可以作为表达式因子参与运算,如: i:=i+1; 是合法的。( 5 )对变量的赋值是对变量的存入访问。如 d:=a ;语句执行后, d 的变量内容就已经是 a 变量的内容,但是 a 变量的值并没有消失与改变。

在实际编程中,我们经常使用 a:=a+1;作为计数器,用 s:=s+x;作为累加器,用t:=t*n;作为累乘器。

Page 21: 教师 (PASCAL 串讲 ) 培训讲习

2、输入( read 、 readln) 语句输入语句格式:格式 1 : read <变量名表 >;格式 2: readln (<变量名表 >) ;功能:执行该语句时,程序进入等待状态,等待用户从键盘输入数据,输入的数据将依次赋给变量表中的变量,而后程序继续执行其他语句。

说明:( 1 )变量表中变量超过一个时,中间用逗号隔开。从键盘输入数据时,数据的个数不能少于变量个数,否则电脑一直处于等待状态。当数据多于变量个数时,对于 readln 语句将其忽略,对于 read 语句时,会补下一句 read 语句读入,如果没有输入语句,也将其忽略。

( 2)输入数值型数据时,必须用空格或回车键分隔,最后一定要用回车键。输入字符型数据时,不能有空格与回车键,必须连续输入,因为空格与回车键也会当作字符。

( 3)输入的数据必须是常量,且必须与对应的变量类型相一致。( 4) readln(); 可以没有变量名表,此时该语句等待从键盘输入回车键。

Readln (x) ; 等价于执行了二条语句: read(x); readln();

Page 22: 教师 (PASCAL 串讲 ) 培训讲习

3、输出(write 、writeln) 语句输出语句的格式:格式 1 write <输出项表 >;格式 2 writeln ( <输出项表 >);功能:按指定的格式将输出项的内容输出到屏幕上。说明:( 1 )输出项如果是多项时,各项间用逗号分隔。( 2)输出项可以是常量、变量、函数、表达式。常量直接输出,变量时输出变量的存储单元内容,遇到函数与表达式时,先计算、再输出。

( 3)write 语句输完最后一项时,不换行,等待下一条 write 语句继续输出。 Writeln 语句输完最后一项时换行,该语句允许没有输出项,起到换行作用。

writeln(x); 等价于执行了write(x); writeln();

Page 23: 教师 (PASCAL 串讲 ) 培训讲习

例: X:=2; y:=3; writeln(‘x=’,x,’y=’,y); writeln(x+y=’,x+y,’x*y=’,x*y)输出结果为:x=2 y=3x+y=5 x*y=6

writewrite 语句可以输出实型、语句可以输出实型、整型、字符型、布尔型值,整型、字符型、布尔型值,也可以输出字符串。若在也可以输出字符串。若在writewrite 语句中不加场宽说明,语句中不加场宽说明,则按标准场宽输出。在这则按标准场宽输出。在这里,场宽是指输出值的位里,场宽是指输出值的位数。数。

Page 24: 教师 (PASCAL 串讲 ) 培训讲习

自定义场宽( 1 )单场宽。用来控制整型、字符型、布尔型数据的输出格式,不能用于实数型。 格式: < 输出项 >: n 说明: n (正整数) 表示输出时所占的列数。单场宽一律右对齐,前用空格。

( 2)双场宽。用来控制实数的输出格式。 格式: < 输出项 >: n1 : n2 说明: ① n1 表示输出总占列数,包括符号位、整数部分、小数点和小数部分; n2表示小

数部分的列数。 ② 当数据突破场宽时,首先保证整数部分的有效性,小数部分按 n2 场宽进行四舍五入显示,但内存中仍是原来的精确度。

③ 单场宽右对齐,双场宽向小数点看齐,多余的小数位数补零。

Page 25: 教师 (PASCAL 串讲 ) 培训讲习

例 T2_1 :交换两个变量的值。

( 1 )利用中间变量 c ,实现交换。

Program T2_1_1;

Var

a,b,c :integer;

Begin

write(‘please input a,b=?’);

read(a,b);

write(‘before:’,’a=‘,a,’b=‘,b);

c := a;

a := b;

b := c;

writeln (‘after:’,’a=‘,a:8,’b=‘,b:8);

End.

( 2 )不用中间变量,也可实现交换。

Program T2_1_2;

Var

a,b :integer;

Begin

write(‘please input a,b=?’);

read(a,b);

write(‘before:’,’a=‘,a,’b=‘,b);

a := a+b;

b := a-b;

a := a-b;

writeln (‘after:’,’a=‘,a:8,’b=‘,b:8);

End.

Page 26: 教师 (PASCAL 串讲 ) 培训讲习

例 T2_2: 鸡兔同笼问题。已知鸡和兔的总头数是 H ,总腿数为 F ,求鸡和兔各多少只?

分析:设鸡为 C 只,兔为R 只,则

C+R=H

2*C+4*R=F

解得: C= ( 4*H-F ) /2 , R=H-C 。

程序为:Progrem T2_2; var h,f,c,r:real; begin readln(h,f); c:=(4*h-f)/2; r:=h-c; writeln(‘click:’,c); writeln(‘rabbit:’,r); end.

Page 27: 教师 (PASCAL 串讲 ) 培训讲习

例 T2_3: 随机产生一个三位自然数,求其百位、十位、个位上的数字。

分析:要产生随机数,必然用到随机函数。

Random 是随机函数能产生[ 0 , 1]之间的随机实数。

随机产生三位数的表达式为: trunc(random*900)+100

假设三位数 X ,百位数分另别为 A,B,C, 则存在如下关系:

A= X DIV 100B= (X-A*100) DIV 10C= X MOD 10

程序为:Program T2_3; VAR x,a,b,c:integer; begin randomize; { 它的作用是每次运行程序时, random 函数产生不同的随机数。起到埋种子作用。}

x:=trunc(random*900)+100; writeln(‘x=‘,x); a:=x div 100; b:=(x-a*100) div 10; c:=x mod 10; writeln(a:5,b:5,c:5);

End.

Page 28: 教师 (PASCAL 串讲 ) 培训讲习

例 T2_4 已知三角形的两边及夹角,求第三边及面积。

数学建模:设三角形的两边及夹角分别为

a , b , α,第三边为 c ,面积为 s 。

则 ,

若α以角度值输入,在计算 sin和 cos时应转换为弧度。角度转弧度的公式为:

弧度 =角度×

180

程序:程序:Program T2_4;Program T2_4; constconst pi=3.14159;pi=3.14159; var var a,b,alfa,c,s:real;a,b,alfa,c,s:real; beginbegin read (a,b,alfa);read (a,b,alfa); alfa:=alfa*pi/180;alfa:=alfa*pi/180; c:=sqrt(a*a+b*b-2*a*b*cos(alfa));c:=sqrt(a*a+b*b-2*a*b*cos(alfa)); s:=1/2*a*b*sin(alfa);s:=1/2*a*b*sin(alfa); write(‘alfa=‘,alfa,’c=‘:8,c,’s=‘:8,s);write(‘alfa=‘,alfa,’c=‘:8,c,’s=‘:8,s); end.end.

cos222 abbac

sin2

1abs

Page 29: 教师 (PASCAL 串讲 ) 培训讲习

例 T2_5: 输入一个字符,求其序号、前导(即前一字符)、后继(即后一字符)。

Program T2_5;Program T2_5; varvar ch,pch,sch:char;ch,pch,sch:char; num:integer;num:integer; beginbegin writeln;writeln; write (‘please input a character:’);write (‘please input a character:’); readln(ch);readln(ch); write(‘pch:’,pred(ch),’sch:’,succ(ch),’num:’,ord(ch));write(‘pch:’,pred(ch),’sch:’,succ(ch),’num:’,ord(ch)); readln();readln(); end.end. 测试删除倒数第二条语句测试删除倒数第二条语句 readln();readln(); 后,执行情况有何不同?后,执行情况有何不同?

Page 30: 教师 (PASCAL 串讲 ) 培训讲习

例 T2_6: 输入 x, y 。若在圆环内,输出 true ,若在圆环外;输出 false 。圆环如图所示。

讨论:如图所示,若下式1≤x2+y2≤4成立则在圆环内,否则在圆环外。设布尔变量 bool ,当x, y 在圆环内时,

让它取值为 true ,否则取值为 false 。

““ (( xx,, yy )若在圆环内”的表达)若在圆环内”的表达式:式: (x2+y2≥12)(x2+y2≥12)且且 (x2+y2≤22) (x2+y2≤22)

程序:程序: program T2_6;program T2_6; var var x,y :real;x,y :real; bool:boolean;bool:boolean; beginbegin writeln;writeln; write(‘x=?’);write(‘x=?’); readln(x);readln(x); write(‘y=?’);write(‘y=?’); readln(y);readln(y); bool:=(x*x+y*y>=1) and (x*x+y*y<=4);bool:=(x*x+y*y>=1) and (x*x+y*y<=4); write(bool);write(bool); readln;readln; end.end.

Page 31: 教师 (PASCAL 串讲 ) 培训讲习

作业: XT1_1 写一程序读入三角形的三个边 a , b , c ,计算并打印三角形的面积 S 。可利用下列公式计算。

其中:

XT1_2 输入一个三位整数,将它们反向输出。例如输入 127,输出应为 721 。

))()(( cpbpappS )(

2

1cbap

XT1_3 XT1_3 由键盘输入两组由键盘输入两组 xx,, yy值,值,

由程序根据它们是否在示意图中的斜线由程序根据它们是否在示意图中的斜线

区域内,输出不同的值。若在斜线区域区域内,输出不同的值。若在斜线区域

内,输出内,输出 truetrue ,否则输出,否则输出 falsefalse 。。

Page 32: 教师 (PASCAL 串讲 ) 培训讲习

第 3课 选择结构程序设计 PASCAL 中有两个语句可实现选择结构: IF 语句(条件语句)和 CASE 语句(情况语句)

3.2.1 IF 语句的两种形式

IF 语句又称如果语句(或称条件语句)。它的一般形式是IF (条件) THEN (语句 1 ) ELSE (语句 2)• 其中“条件”实际上是一个布尔表达式,它的值可以是真( true )或假( false )。在条件为真时,执行语句 1 ,否则(条件为假)执行语句 2。• 可以利用流程图来描述选择结构。• 在流程图中用菱形框表示要执行的判定,其余步骤用矩形框表示,箭头表示执行的顺序。

Page 33: 教师 (PASCAL 串讲 ) 培训讲习

例 L3_1 火车托运行李,要根据行李的重量按不同标准收费。例如不超过50kg ,按每公斤 0.35元收费。若超过 50kg ,则其中 50kg 按每公斤 0.35元收费,其余超过部分按每公斤 0.50 元收费。现输入托运行李重量,要求计算并输出托运费。

数学建模:设托运行李重量为weight ,该问题要求根据weight 是否超过 50kg ,按不同公式计算出托运费。设托运费为 pay 。weight 和 pay均为实型。

下面给出算法。一级算法1 、读入weight 的值。2、根据weight 的大小选择不同的公式计算 pay 。3、输出pay 。其中第2步需求精。根据题意,可以写出计算 pay 的公式如下:

weight≤50weight>50

5.0)50(35.050

35.0

weight

weightpay

Page 34: 教师 (PASCAL 串讲 ) 培训讲习

除了上面给出的 IF 语句形式外, PASCAL中还有另外一种 IF语句形式。即

IF (条件) THEN (语句)在条件为真时,执行

THEN 后的语句。在条件为假时,不执行 THEN 后的语句,在两种情况下的后继语句都是 IF语句的下一个语句。

Page 35: 教师 (PASCAL 串讲 ) 培训讲习

例 L3_2 读入三个数,找出并打印其中的最大数。

解:PROGRAM L3_2; VAR a,b,c:real; BEGIN write('a=?'); read(a); write('b=?'); read(b); write('c=?'); read(c); IF a<b THEN a:=b; IF a<c THEN a:=c; writeln('ZuiDaShu:',a) END.

Page 36: 教师 (PASCAL 串讲 ) 培训讲习

3.2.2 复合语句 在 IF 语句中,跟在 THEN或 ELSE 后的语句可

能不止一个,这时要用到复合语句的概念。 复合语句是一个以 BEGIN 开始,以 END结束的

语句。在 BEGIN与 END之间可以包括若干个语句,每个语句之间以分号分开。一般形式为:BEGIN (语句 1 ); (语句 2 ); … (语句 n )END

一个复合语句从外部看来,相当于一个语句。

Page 37: 教师 (PASCAL 串讲 ) 培训讲习

3.2.3 IF 语句的嵌套 在 IF 语句中, THEN或 ELSE

后的语句本身也可能是 IF 语句。此时称为 IF 语句的嵌套(或称为复合 IF 语句)。

例如语句 IF (条件 1 ) THEN (语句 1 ) ELSE IF (条件 2) THEN (语句 2) ELSE (语句 3) 就是一个复合 IF 语句,在它的

ELSE 后又是一个 IF 语句。

Page 38: 教师 (PASCAL 串讲 ) 培训讲习

有时 IF 语句可能会有两种不同的理解。

注意:在进行注意:在进行 IFIF 语句的嵌套时应注意语句的嵌套时应注意 IF IF 与 与 ELSEELSE 的配对关系,的配对关系, ELSEELSE 是是不能省略的,否则将造成逻辑错误。解决的办法是写一个空语句或者采用不能省略的,否则将造成逻辑错误。解决的办法是写一个空语句或者采用复合语句,即增加语句括号(复合语句,即增加语句括号( begin…end)begin…end) 。从内层开始,。从内层开始, ELSEELSE总是与总是与它上面最近的(示曾配对的)它上面最近的(示曾配对的) IFIF配对。配对。

Page 39: 教师 (PASCAL 串讲 ) 培训讲习

例 L3_3: 有一个函数表达式为:

编写程序,输入 x, 输出 y 的值。

01

00

01

x

x

x

y

Program L3-3;

var

x:real;

y:integer;

begin

write(‘please input x=‘);

readln(x);

If x<0

then y:=-1

else

if x>0

then y:=1

else y:=0;

Writeln(‘y=‘,y);

End.

Page 40: 教师 (PASCAL 串讲 ) 培训讲习

3.3 CASE 语句 CASE 语句是实现选择结构程序设计的另一种语句。它的使用有时比 IF 语句

来得简单、直观。 CASE 语句(或称情况语句)的一般形式是 CASE (表达式) OF (值表 1 ):(语句 1 ); (值表 2):(语句 2); …… (值表 n ):(语句 n ) ; ELSE 语句 n+1; END;

在 CASE 语句头上的表达式必须是有序类型(整型、字符型、布尔型以及后面要介绍的枚举型、子界型)。值表是一些由逗号分开的常数。表达式所有可能的值必须在值表中出现,且每个值只能出现一次。

如果当前表达式的值在某个值表 i 中出现,则该程序只执行对应值表 i的语句 i ,然后执行整个 CASE 语句后的下一语句。

else 可以省略,此时若无表达式的值与之相匹配的常数表时程序将向下运行并跳出 case 语句。

Page 41: 教师 (PASCAL 串讲 ) 培训讲习

例 L3_5 输入年、月,输出该月有几天。

讨论:每年的 1 、 3 、 5 、7 、 8 、 10 、 12 月,每月有 31 天; 4 、 6 、 9 、11 月,每月有 30 天; 2月闰年有 29 天,平年有28 天。

年号能被 4 整除,但不能被 100 整除,或者年号能被 400 整除的年均是闰年。

用 year 、 month 、 days 分别表示年、月、每月天数。它们均为整数。

闰年的条件可以写成如下的布尔表达式:

(year MOD 4 = 0) AND (year MOD 100 <> 0) OR (year MOD 400 = 0)

Program L3_5; var year,month,days:integer; begin read (year,month); case month of 1,3,5,7,8,10,12: days:=31; 4,6,9,11 : days:=30; 2 : if (year mod 4 =0) and (year mod 100<>0) or (year mod 400 =0) then days:=29 else days:=28; end; writeln (year,’year’,month,’month:’,’days:’,days);End.

Page 42: 教师 (PASCAL 串讲 ) 培训讲习

例 L3_6 编制程序,根据输入的 x 值,计算 y与 z并输出。

)5.2(1

)5.2(12

2

xx

xxy

)0(52

)0(0

)0(32

xx

x

xx

z

PROGRAM L3_6;PROGRAM L3_6; CONSTCONST PI=3.14159;PI=3.14159; VARVAR x,y,z:real;x,y,z:real; BEGINBEGIN write('x=?');write('x=?'); read(x);read(x); IF x<=2.5IF x<=2.5 THEN y:=x*x+1THEN y:=x*x+1 ELSE y:=x*x-1;ELSE y:=x*x-1; IF x<0IF x<0 THEN z:=-PI/2*x+3THEN z:=-PI/2*x+3 ELSE IF x=0ELSE IF x=0 THEN z:=0THEN z:=0 ELSE z:=PI/2*x-5;ELSE z:=PI/2*x-5; writeln('x=',x:6:2,',y=',y:6:2,', z=',z:6:2)writeln('x=',x:6:2,',y=',y:6:2,', z=',z:6:2) END.END.

Page 43: 教师 (PASCAL 串讲 ) 培训讲习

作业: XT3_1 对一批货物征收税金,价格在 1 万元以上的货

物征税 5% ,在 5000 元以上, 1 万元以下的货物征税3% ,在 1000 元以上, 5000 元以下的货物征税 2% ,1000 元以下的货物免税。编写一程序,读入货物价格,计算并输出税金。

XT3_2 输入某学生成绩,若成绩在 85 分以上,输出very good ,若成绩在 60 分到 85 分之间,输出 good ,若成绩低于 60 分,输出 no good 。

XT3_3 输入班号,输入该班学生人数。应用 CASE 语句编程序。 班级 201 202 203 204 205

班额 45 47 42 46 48

Page 44: 教师 (PASCAL 串讲 ) 培训讲习

第 4课 循环结构 循环结构(或称重复结构)是程序中的一个基本结构,在解许多问题中是很有用的。我们知道,在许多复杂的问题中,常常需要做大量类同的计算处理。尽管计算机的运算速度很快,然而要把这些大量类同的计算处理的每一步都写成语句,并输入计算机中,其工作量是相当大的。有时是难以完成的。

循环结构程序设计可以帮助我们有效地解决这一难题。利用循环结构程序设计,使得我们有可能只编写少量的语句,让计算机重复执行它许多次,从而完成大量类同的计算要求。

在 PASCAL 中,实现循环程序设计的主要语句有 FOR 语句、WHILE 语句和 REPEAT 语句。

Page 45: 教师 (PASCAL 串讲 ) 培训讲习

一、 FOR语句格式 1 : (递增型 ) FOR x: =<初值 > TO <终值 > DO < 循环体 >

格式 1: (递减型 ) FOR x: =<初值 > downTO <终值 > DO < 循环体 >

FOR X:= 1 TO 10 DOFOR X:= ‘A’ TO ‘Z’ DO

控制变量 初值

控制变量≤终值 false

true 执行语句

控制变量 succ(控制变量)

控制变量 初值

控制变量≥终值 false

true 执行语句

控制变量 pred(控制变量)

FOR X:=10 DOWNTO 1 DOFOR X:=10 DOWNTO 1 DOFOR X:=’Z’ DOWNTO ‘A’ DOFOR X:=’Z’ DOWNTO ‘A’ DO

Page 46: 教师 (PASCAL 串讲 ) 培训讲习

T4_001 计算 1+2+3+…+10

PROGRAM T4_001; VAR s,n:integer; BEGIN s:=0; FOR n:=1 TO 10 DO s:=s+n; writeln(‘s=’,s) END.

s=0当 n=1 s=s+n=0+1=1;当 n=2 s=s+n=1+2=3当 n=3 s=s+n=3+3=6当 n=4 s=s+n=6+4=10当 n=5 s=s+n=10+5=15当 n=6 s=s+n=15+6=21当 n=7 s=s+n=21+7=28当 n=8 s=s+n=28+8=36当 n=9 s=s+n=36+9=45当 n=10 s=s+n=45+10=55

Page 47: 教师 (PASCAL 串讲 ) 培训讲习

例 T4_002 : 输入 10个任

意整数,求它们的和 .

PROGRAM T4_002; VAR s,n,a:integer; BEGIN s:=0; FOR n:=1 TO 10 DO BEGIN read(a); s:=s+a; END; writeln(‘s=’,s) END.

例例 T4_003T4_003 : 计算: 计算 n!n!(( n!n!=1×2×3×…×n=1×2×3×…×n ))

PROGRAM T4_003; VAR n,i,sum:integer; BEGIN read(n); sum:=1; FOR i:=1 TO n DO sum:=sum*i; writeln('n!=',sum); END.

注意 N<8 ,否则会溢出。

Page 48: 教师 (PASCAL 串讲 ) 培训讲习

例 T4_004:任何一个 n3 一定可以表示成 n 个连续的奇数和。输入 n(n≤100), 输出 n3对应的表达式。

数学题解:设表达式中的最小奇数为 x;当 N=1时,最小奇数 X=1 , 1 个奇数;当 N=2 时,最小奇数 X=3, 2 个奇数;当 N=3 时,最小奇数 X=7, 3 个奇数; N N3 1 1 2 23=8=3+5 3 33=27=7+9+11 4 43=64=13+15+17+19 ……当 N=K 时,最小奇数 X 前己有 1+2+3+…+(K-1) 个奇数,则第 K个奇数 K*( K-1 )X = *2+1=K*( K-1 ) +1=N*( N-1 ) +1 2

Page 49: 教师 (PASCAL 串讲 ) 培训讲习

Program T4_004; var i,n,a:longint {循环变量,连续的奇数个数,当前项,类型 为长整型 } begin readln(n); a: = n*(n-1) +1; for i:= 1 to n-1 do begin write(a,’+’); a:=a+2; end; writrln(a); readln; end

思考题:用数学方法证明上述定理。

Page 50: 教师 (PASCAL 串讲 ) 培训讲习

作业:T4_005 输入 10个任意整数,求它们的平均值。T4_006 按正序和反序分别输出26个英文字母。T4_007 输入20个整数,输出其中最大数。T4_008 输入20个整数,统计其中正、负和零的个数。

思考题:

100...321 s求值:

Page 51: 教师 (PASCAL 串讲 ) 培训讲习

作业答案:PROGRAM T4_005; VAR ave:real; i,n,sum:integer; BEGIN sum:=0; FOR i:=1 TO 10 DO BEGIN read(n); sum:=sum+n; END; ave:=sum/10; writeln('ave=',ave:6:2) END.

PROGRAM T4_006; VAR i:integer; BEGIN writeln(); FOR i:=1 TO 26 DO write(chr(96+i)); writeln(); FOR i:=122 DOWNTO 97 DO write(chr(i)) END.

PROGRAM T4_006_1; VAR i:char; BEGIN writeln(); FOR i:=‘A’TO ‘Z’ DO write(i); writeln(); FOR i:=‘Z’DOWNTO ‘A’ DO write(i) END.

Page 52: 教师 (PASCAL 串讲 ) 培训讲习

作业答案:PROGRAM T4_007; VAR max,i,n:integer; BEGIN read(max); FOR i:=1 TO 19 DO BEGIN read(n); IF max<n THEN max:=n; END; writeln('max=',max) END.

PROGRAM T4_008; VAR i,n,Zheng,Fu,Ling:integer; BEGIN Zheng:=0; Fu:=0; Ling:=0; FOR i:=1 TO 20 DO BEGIN read(n); IF n>0 THEN Zheng:=Zheng+1 ELSE IF n=0 THEN Ling:=Ling+1 ELSE Fu:=Fu+1; END;{FOR} writeln('Zheng Shu You: ',Zheng,'; Fu Shu You: ',Fu,'; Ling You: ',Ling) END.

Page 53: 教师 (PASCAL 串讲 ) 培训讲习

二、while 语句 (当型循环) 当循环次数未知,例如它依赖

于某个布尔表达式的值,而此值在循环执行过程中会改变。这种循环不可能由 FOR语句实现, PASCAL 为此提供了 WHILE 语句和 REPEAT 语句。

WHILE 语句的一般形式: WHILE < 布尔表达式 > DO < 循环体 >

flaseflase 布尔表达式布尔表达式

truetrue

语句语句

Page 54: 教师 (PASCAL 串讲 ) 培训讲习

例 T4_009 :求 S=2+6+10+…+98 的值。

分析: S 为求和累加器, X为当前项,赋初值为 2,每次循环后增加 4,取 X≤98 为布尔表达式。

Program T4_009;Program T4_009;VarVar s,x:longint;s,x:longint;beginbegin x:=2; s:=0;x:=2; s:=0; while x<=98 do {while x<=98 do { 当满足条件时执行后面语句}当满足条件时执行后面语句} beginbegin s:=s+x;s:=s+x; x:=x+4;x:=x+4; end;end; writeln (‘s=‘,s);writeln (‘s=‘,s);end.end.

课堂作业:计算 S=1+2+4+8+…+128+256的值。

Page 55: 教师 (PASCAL 串讲 ) 培训讲习

例 T4_010:求两个自然数的最小公倍数。

分析:先从数学角度来分析一下,所谓最小公倍数就是指能被M和 N同时整除的最小自然数。先设一个变量 i,让它从 1 开始按自然数增长,将 i与M相乘的结果存到变量 S 中,这样 S就是M的公倍数,由于 i 是从最小开始的,然后再用每一个 S除以因子 N ,若能整除,则 S为M和 N两个因子的最小公倍数。

Program T4_010;var n,m,I,s:longint;begin write(‘请输入两个自然数‘ ) ; readln(m,n); i:=1; s:=m*I; while s mod n <>0 do begin i:=i+1; s:=m*I; end; writrln(‘s=’ , s) ;end.

Page 56: 教师 (PASCAL 串讲 ) 培训讲习

三、 repeat 语句(直到型循环)REPEAT 语句也用于循环次数未知的循环,它的用法与

WHILE 语句稍有不同。REPEAT 语句的一般形式如下:REPEAT< 循环体 >UNTIL < 布尔表达式 >

例 T4_011 计算 (泰勒展开式)

直到最后一项的绝对值小于 10-7时停止计算, x由键盘输入。

...!7!5!3

)sin(753

xxx

xx

Page 57: 教师 (PASCAL 串讲 ) 培训讲习

题解: 设 题解: 设 SS 为累加器,为累加器, t t 为当前项,为当前项, ii为为 XX 的幂次的幂次 即即 S=tS=t11+t+t22+t+t33…+t…+tkk,,其中其中

(( 11 )确定重复条件为)确定重复条件为 abs(t)<1e-7abs(t)<1e-7 (2) (2) 确定重复体确定重复体由由

(3)(3) 设初值设初值

由此得出程序:由此得出程序:

Program T4_011;Program T4_011; varvar I : integer;I : integer; t,s,x: real;t,s,x: real;beginbegin readln(x);readln(x); x:=x*3.14159/180;x:=x*3.14159/180; i:=1; t:=X;s:=0;i:=1; t:=X;s:=0; repeatrepeat s:=s+t;s:=s+t; t:=-t*x/(i+1)*x/(i+2);t:=-t*x/(i+1)*x/(i+2); i:=i+2;i:=i+2; until abs(t)<1e-7 ;until abs(t)<1e-7 ; writeln(‘sin(‘,x,’)=’,s:0:4)writeln(‘sin(‘,x,’)=’,s:0:4) readln;readln;End.End.

)2()1()1(1

i

x

i

xtt ii

xt 1

;0;;1 sxti

Page 58: 教师 (PASCAL 串讲 ) 培训讲习

作业:

T4_012: 计算

当最后一项的绝对值小于 10-6时结束,打印输出结果。

T4_013: 求满足条件 N!≤ 100000 的最大值 N 。

...1 71

51

31 s

Page 59: 教师 (PASCAL 串讲 ) 培训讲习

三种循环语句的相同点与不同点FOR WHILE REPEAT

语句格式 FOR <循环变量 >:=<初值 > TO <终值> DO

<语句 >

WHILE <布尔表达式 > DO<循环体 >

REPEAT<循环体 >UNTIL <布尔表达式 >

循环变量 赋值 布尔表达式 无循环变量循环次数 确定,由初值和终值决

定不确定,由循环体前的布尔表达式决定,当值

“ ”为 假 时,结束循环。可能一次循环也没有

不确定,由循环体后的布尔表达式决定,

“ ”当值为 真 时结束循环。

至少有一次循环循环体 多语句时,需用 BEGIN

和 END多语句时,需用 BEGIN和

END多语句时,不需用 BE

GIN和 END

Page 60: 教师 (PASCAL 串讲 ) 培训讲习

用计算机解题的基本方法 在对问题有了清楚的分析后,可以仔细在对问题有了清楚的分析后,可以仔细地构造求解步骤——算法。算法可以自顶向地构造求解步骤——算法。算法可以自顶向下、由粗到细,逐步求精。下、由粗到细,逐步求精。

描述问题由粗到细的过程,一般可以分描述问题由粗到细的过程,一般可以分为三步:为三步:

一级算法一级算法二级求精二级求精写出程序写出程序

Page 61: 教师 (PASCAL 串讲 ) 培训讲习

第 5 课 多重循环

如果一个循环结构的内部(循环体)又包括一个循环结构,就称为多重循环结构。实现多重循环结构仍可以用前面讲的三种循环语句。因为任一循环语句的循环体部分都可以包含另一个循环语句,这种循环语句的嵌套为实现多重循环提供了方便。

多重循环的嵌套次数可以是任意的。可以按照嵌套层次数,分别叫做二重循环、三重循环等。处于内部的循环叫作内循环,处于外部的循环叫作外循环。

在设计多重循环时,要特别注意内、外循环之间的关系,以及各语句安放的位置,不要搞错。

Page 62: 教师 (PASCAL 串讲 ) 培训讲习

T5_001 求 1~100之间的素数(质数 ) ,每行输出 5 个素数 .

素数是大于素数是大于 11 ,且除了,且除了 11 和它本身外,不能被其它任和它本身外,不能被其它任何整数所整除的整数。何整数所整除的整数。

讨论:根据素数的定义可知讨论:根据素数的定义可知为了判断某数为了判断某数 ii 是否为素数,一个最简单的办法是用是否为素数,一个最简单的办法是用 22 、、

33 、、 44 、、 55 、……、、……、 i-1i-1 这些数逐个去除这些数逐个去除 ii ,看能否,看能否除尽。若被其中一个数除尽了,则除尽。若被其中一个数除尽了,则 ii 不是素数,否则不是素数,否则(全都除不尽)(全都除不尽) ii 是素数。(此算法次数较多)是素数。(此算法次数较多)

用用 22 、、 33 、、 44 、…… 去除,如果都除不尽,则、…… 去除,如果都除不尽,则 ii 是是素数。(此算法次数较少)素数。(此算法次数较少)i

Page 63: 教师 (PASCAL 串讲 ) 培训讲习

一级算法:FOR i:=2 TO 100 DO BEGIN 1 、用 2 到去除 i ,看看能否除尽 2 、 IF 除不尽 THEN 输出素数 i END算法需进一步求精。用变量 yn来表示是否除尽。一开始让 yn=1 ,当有一个数能除尽时,让 yn=0 表

示能除尽,这时 i 不是素数;若循环结束时, yn仍等于 1 ,表示都除不尽,这时 i 是素数。

二级求精 1 、用 2 到去除 i ,看看能否除尽 1-1 yn:=1 1-2 WHILE n<sqrt(i) DO BEGIN n:=n+1 IF i MOD n=0 THEN yn:=0 END为了每行输出 5 个数,还需增加一个变量 counter来计数。

Program T5_001; var I,n,yn,counter:integer; begin writeln();counter:=1; Write(2,’,’); for i:=3 to 100 do begin n:=1;yn:=1; while n<sqrt(i) do begin n:=n+1; if I mod n=0 then yn:=0; end; if yn=1 then begin counter:=counter+1; if counter mod 5 =0 then writeln(i) else write (I,’,’); end;{if} end;{for}End.{main}

Page 64: 教师 (PASCAL 串讲 ) 培训讲习

T5_002 验证哥德巴赫猜想(任何充分大的偶数都可由两个素数之和表示)。

将 4~2*s ( s≤1000)中的所有偶数分别用两个素数之和表示。 哥德巴赫猜想是:对任一充分

大的偶数 even ,可以找到两个素数 p 、 q 。使得

even=p+q即 1+1 问题。此问题还未得到最后的证明。我们这里只是对有限范围内的

数,用计算机加以验证,不算严格证明。

读入偶数 even ,将它分成 p和 q ,使 even=p+q 。

p从 2开始(每次加 1 ), q=even-p 。如果 p 、 q 均为素数,则输出结果,否则将p加 1再试。

一级算法:一级算法:11 、读入一个数、读入一个数 eveneven ;;22 、判断、判断 eveneven 是否为偶数,如果是偶数,是否为偶数,如果是偶数,则继续,否则结束程序;则继续,否则结束程序;33 、、 FOR p:=2 TO trunc(even/2)FOR p:=2 TO trunc(even/2)3-1 q:=even-p3-1 q:=even-p3-2 3-2 判断判断 pp 是否为素数(是否为素数( pyn:=1pyn:=1 表示表示pp 为素数,为素数, pyn:=0pyn:=0 表示表示 pp 不是素数)不是素数)3-3 3-3 判断判断 qq 是否为素数(是否为素数( qyn:=1qyn:=1 表示表示qq 为素数,为素数, qyn:=0qyn:=0 表示表示 qq 不是素数)不是素数)3-4 IF pyn=1 AND qyn=13-4 IF pyn=1 AND qyn=1 THEN writeln(even,’=’,p,’+’,q)THEN writeln(even,’=’,p,’+’,q)

Page 65: 教师 (PASCAL 串讲 ) 培训讲习

二级求精:二级求精:11 、、 read(even)read(even)22 、、 IF even MOD 2=0IF even MOD 2=0 THEN THEN 第第 33步步3-23-2 、、 n:=2n:=2WHILE n<sqrt(p) DOWHILE n<sqrt(p) DO BEGINBEGIN n:=n+1;n:=n+1; IF p MOD n=0IF p MOD n=0 THEN pyn:=0;THEN pyn:=0; END;END;3-33-3 、、 n:=2n:=2WHILE n<sqrt(q) DOWHILE n<sqrt(q) DO BEGINBEGIN n:=n+1;n:=n+1; IF q MOD n=0IF q MOD n=0 THEN qyn:=0;THEN qyn:=0; END;END;

Page 66: 教师 (PASCAL 串讲 ) 培训讲习

作业:程序找错误(一)

错误一:第错误一:第 22 行少“行少“ VAVAR”R” ;;错误二:第错误二:第 55 行少分号;行少分号;错误三:第错误三:第 44 、、 66 、、 88行,字符串应用单引号,行,字符串应用单引号,题中用了双引号;题中用了双引号;错误四:第错误四:第 88 行字符串行字符串与变量之间少逗号。与变量之间少逗号。

Page 67: 教师 (PASCAL 串讲 ) 培训讲习

作业:程序找错误(二)PROGRAM T5_004;PROGRAM T5_004; VARVAR n,integer;n,integer; BEGINBEGIN write('Please input a number from 0 to 6 for wewrite('Please input a number from 0 to 6 for we

ekday:')ekday:') read(n);read(n); CASE n CASE n 0:writeln('Sunday');0:writeln('Sunday'); 1:writeln('Monday');1:writeln('Monday'); 2:writeln('Tuesday');2:writeln('Tuesday'); 3:writeln('Wednesday');3:writeln('Wednesday'); 4:writeln('Thursday');4:writeln('Thursday'); 5:writeln('Friday');5:writeln('Friday'); 6:writeln('Saturday');6:writeln('Saturday'); END.END.

错误一:第错误一:第 22 行变量与数据类型行变量与数据类型之间应用冒号,这里用了逗号;之间应用冒号,这里用了逗号;错误二:第错误二:第 55 行少分号;行少分号;错误三:第错误三:第 77 行,行, CASECASE 语句少语句少了了 OFOF ;;错误四:错误四: CASECASE 语句没有语句没有 ENDEND与之配对。与之配对。

Page 68: 教师 (PASCAL 串讲 ) 培训讲习

作业:程序找错误(三)PROGRAM T5_005; VAR ch:char; ZiMu,ShuZi,FuHao:integer; BEGIN ZiMu:=0; ShuZi:=0; FuHao:=0; WHILE ch<>'?' BEGIN read(ch);IF (ch>A) AND (ch<Z) OR (ch>a) AND (ch<z) THEN ZiMu=ZiMu+1 ELSE IF ord(ch)>=48 AND ord(ch)<=57 THEN ShuZi:=ShuZi+1 ELSE FuHao:=FuHao+1; END; writeln('Zi Mu Ge Shu: ',ZiMu); writeln('Shu Zi Ge Shu: ',ShuZi); writeln('Qi Ta Fu Hao Ge Shu: ',FuHao) END.

错误一:第错误一:第 99 行行 WHILEWHILE 语句少语句少 DODO ;;错误二:第错误二:第 1212 行行 IFIF 语句中,字符语句中,字符没有加单引号;没有加单引号;错误三:第错误三:第 1313 行,赋值语句不对,行,赋值语句不对,应为应为 :=:=错误四:第错误四:第 1414 行,行, IFIF 语句中,语句中, ANANDD 两边的逻辑判断应各自加括号,两边的逻辑判断应各自加括号,即(即( ord(ch)>=48ord(ch)>=48 ) ) AND AND (( ordord(ch)<=57(ch)<=57 )。)。

Page 69: 教师 (PASCAL 串讲 ) 培训讲习

T5_003 “百钱买百鸡”是我国古代的著名数学问题,内容是 3文钱可以买 1只公鸡, 2文钱可以买 1只母鸡, 1 文钱可以买 3 只小鸡。用了 100文钱买了 100 只鸡,问有多少只公鸡、母鸡、小鸡?

分析:用分析:用 XX ,, YY ,, ZZ 分别代表购买公鸡、母鸡、分别代表购买公鸡、母鸡、小鸡的数量,则存在以下关系:小鸡的数量,则存在以下关系:

同时满足:同时满足: 1≤x ≤33,1 ≤y ≤50,1≤x ≤33,1 ≤y ≤50,

1 ≤z ≤1001 ≤z ≤100 。然后在各变量范围内进行检验,。然后在各变量范围内进行检验,能满足上面两个关系式的变量值。能满足上面两个关系式的变量值。

100

1003

123

zyx

zyx

Program T5_003Program T5_003VarVar x,y,z:integer;x,y,z:integer; begin begin for x:=1 to 33 dofor x:=1 to 33 do beginbegin for y:=1 to 50 dofor y:=1 to 50 do z:=100-x-yz:=100-x-y if 3*x+2*y+z/3 =100 thenif 3*x+2*y+z/3 =100 then writeln(‘gong qi:’,x,’mu qi’:8,writeln(‘gong qi:’,x,’mu qi’:8,y, ‘xiao qi’:8,z);y, ‘xiao qi’:8,z); end;end; end;end;End.End.

Page 70: 教师 (PASCAL 串讲 ) 培训讲习

第 6课 PASCAL 语言数据类型

数据类型

简单类型

标准类型

用户自定义类型

整型实型字符型布尔型

枚举类型

子界类型

构造类型

集合类型数组类型

字符串类型记录类型

指针类型

文件类型

Page 71: 教师 (PASCAL 串讲 ) 培训讲习

6.1.1 整型的运算项目项目 内容内容算术算术运算符运算符

++ 、、 -- 、、 ** 、、 // ,, div(div(取商取商 )) 、、 mod(mod(取取模模 ))

关系关系运算符运算符 == 、、 <><> 、、 >> 、、 << 、、 <=<= 、、 >=>=

标准标准函数函数

Pred(Pred(前趋前趋 )) 、、 succ(succ( 后继后继 )) 、、 ord(ord( 序序号号 )) 、、 abs(abs(绝对值绝对值 )) 、、 sqr(sqr( 平方平方 )) 、、 sqrsqrt(t( 平方根平方根 )) 、、 odd(odd(判奇判奇 ))[奇数为[奇数为 true,true,

偶数偶数 false]…false]…

Page 72: 教师 (PASCAL 串讲 ) 培训讲习

例 T6_000: 如果变量 A 既能被 7整除又能被 11 整除,写成 PASCAL 表达式 :( A mod 7=0) and (A mod 11=0)

例 T6_001: 求水仙花数。所谓水仙花数,如 ABC,如果满足A3+B3+C3=ABC,则 ABC称为水仙花数。

例: 153=13+53+33 ,所以 153就是水仙花数。

分析:此题关键是分解出 A、B 、 C

a= I div 100 b= I div 10 – 10*a C= I mod 10

Program T6_001; Var I,a,b,c:longint; begin for I := 100 to 999 do begin a:=I div 100 b:=I div 10- a*10 c:=I mod 10 if i= a*a*a+b*b*b+c*c*c then writeln (‘is’,i) end; end.

Page 73: 教师 (PASCAL 串讲 ) 培训讲习

6.2: 实型

名称名称 类型名类型名 数据范围数据范围 位数字节位数字节

单精度实型单精度实型 SingleSingle 1.5E-45~3.4E+381.5E-45~3.4E+38 44

实 型实 型 RealReal 2.9E-39~1.7E+382.9E-39~1.7E+38 66

双精度实型双精度实型 DoubleDouble 5.0E-324~1.7E+3085.0E-324~1.7E+308 88

扩展实型扩展实型 ExtendedExtended 1.9E-4932~1.1E+49321.9E-4932~1.1E+4932 1010

装配实型装配实型 CompComp -2-26363+1~2+1~26363-1-1 之间的整数之间的整数 88

这几种实数类型的使用方法与Real 的使用方法类似,必须在程序开始打开编译开关{ $N+ } ,这些类别才能被系统识别。

Page 74: 教师 (PASCAL 串讲 ) 培训讲习

例 T6_2: 求 1/1+1/2+2/3+3/5+5/8+…前 n项( n≤50) 的和。

分析:分析:设设 e=te=t11+t+t22+t+t33+…+t+…+tii+..+t+..+tnn,,

其中其中 ttii= , (1 ≤i ≤n)= , (1 ≤i ≤n) 。。

由数列的特征可以看出,由数列的特征可以看出,aaii=b=bi-1i-1,b,bii=a=ai-1i-1+b+bi-1i-1 。。 由于由于 N ≤50N ≤50 ,因此,因此 aaii ,, bbii ,,

ee 的数值超过了标准的的数值超过了标准的整数型和实数型的范围。整数型和实数型的范围。不得不通过{不得不通过{ $N+}$N+}启启动浮点运算,并将动浮点运算,并将 aaii ,, bbii ,,

ee 的数据类型设为的数据类型设为 exteextended,nded, 使得精度保持在使得精度保持在1919位。位。

i

i

b

a

Program T6_2; {$N+} var I,n :integer; a,b,c,e:extended; begin readln(n); a:=0; b:=1;e:=0; for i:=1 to n do begin c:=b;b=a+b;a:=c; e:=e+a/b; end;{for} writeln(e:20:2)end.{main}

Page 75: 教师 (PASCAL 串讲 ) 培训讲习

6.3:字符型( ASCII码)

( 1 )类型名: Char( 2 )范围: ASCII码(美国标准信息交换代码)

( 3 )表示方法:‘一个字符’( 4 )字符是有序类型,每个字符都对应一个序

号,其中字符‘ A’ 的序号是 64 ,字符’ a’ 的序号是 97 。

( 5 )字符类型占内存一个字节。

Page 76: 教师 (PASCAL 串讲 ) 培训讲习

6.4:布尔型( 1 )类型名: boolean( 2 )范围:只有两个值 false 和 true( 3 )是有序数据: false 序号是 0 , true 的

序号是 1 。即 ord(false)=0, ord(true)=1. 约定: false< true 。( 4 )布尔型占内存一个字节。( 5 )逻辑运算符: and 、 or 、 not运算结果

为布尔型。

Page 77: 教师 (PASCAL 串讲 ) 培训讲习

例 T6_3: 填写数字:求出 中的数字,并找印算式。8 0 9

1

设位数较少的除数为设位数较少的除数为 x (x ( 被除数的位数被除数的位数 44 ,除数的位数,除数的位数 22 ),由),由 xx 得出得出y:y:y=809x+1y=809x+1根据以下条件,判断 根据以下条件,判断 xx 和和 y y 是否同时成立:是否同时成立:(( 11 )) yy 为四位数(为四位数( y>999)and(y<10000)y>999)and(y<10000) (2) 8(2) 8 乘以乘以 XX 为二位数为二位数 ((8x<100)and(8x>9)((8x<100)and(8x>9) (3) 9(3) 9 乘以乘以 XX 为三位数为三位数 ((9x<1000)and(9x>99)((9x<1000)and(9x>99)

Page 78: 教师 (PASCAL 串讲 ) 培训讲习

程序:Program T6_3;Program T6_3; var var x,y:integer;x,y:integer; beginbegin for x:= 10 to 99 dofor x:= 10 to 99 do beginbegin y:=809*x+1y:=809*x+1 if (y>999)and(y<10000)and(8*x<100)and(8*x>9)and(9*x>99)and(9*x<100if (y>999)and(y<10000)and(8*x<100)and(8*x>9)and(9*x>99)and(9*x<100

0)0) then beginthen begin writeln(‘809’:19);writeln(‘809’:19); writeln(‘-------------’:20);writeln(‘-------------’:20); writeln(x:6,’)’:3,y:10);writeln(x:6,’)’:3,y:10); writeln(8*x:17);writeln(8*x:17); writeln(‘-------------’:20);writeln(‘-------------’:20); writeln(y-800*x:19);writeln(y-800*x:19); writeln(9*x:19);writeln(9*x:19); writeln(‘-------------’,20) ;writeln(‘-------------’,20) ; writeln(‘1’:19);writeln(‘1’:19); end;{then}end;{then} end ;{for}end ;{for} end.{main}end.{main}

Page 79: 教师 (PASCAL 串讲 ) 培训讲习

6.5: 枚举型( 1 )格式: type 枚举类型标识符 =(标识符 1 ,标识符 2,…标识符 n); (2) 特点: 枚举元素只能是标识符,不能是数值常量或字符常量 同一枚举元素不能出现在两个及以上枚举型定义中 枚举类型有顺序,序列号从 0开始 ord(Monday)=0, succ(Friday)=Saturday, pred(Friday)=Thursday 枚举类型只能进行赋值和关系运算 枚举变量不允许用 read或 readln 语句进行赋值,也不能被write或wr

iteln输出。

Page 80: 教师 (PASCAL 串讲 ) 培训讲习

例 T6_4: 有红、橙、黄、绿、蓝 5 种顔色的小旗,每次取出 3种不同顔色表示不同的信号,输出所有信号的方案及方案总数。

分析:枚举值的输入,一般先输入序号,通过 CASE 语句将枚举值相应地赋值给枚举变量;输出时,通过 CASE 语句判断枚举类型变量的值,输出相应的字符串。

Program T6_4;Type color =(red,orange,yellow,green,blue);var m,m1,m2,m3:color; s,p:integer; begin s:=0; for m1:=red to blue do for m2:=red to blue do if m1<>m2 then for m3:= red to blue do if (m3<>m1) and (m3<>m2) then begin s:=s+1 write (s,’:’); for P:=1 to 3 do begin case p of 1: m:=m1; 2: m:=m2; 3: m:=m3;

end;{case p}case m ofred: write(‘red’:8);orange:write(‘orange’:8);yellow:write(‘yellow’:8);green:write(‘green’:8);blue: write(‘blue’:9);

end;{case 结束 } end;{for 结束} writeln; end;{if 结束} writeln (‘total:’,s);end .

Page 81: 教师 (PASCAL 串讲 ) 培训讲习

6.6: 子界类型type

子界类型标识符 = 常量 1.. 常量 2

注释: 常量 2必须大于常量 1 ; 可以是整型、字符型、布尔型、枚举型等顺序型的两个常量,且必须是同一类型的数据。

子界型常量上下界不可以是实数型。

Page 82: 教师 (PASCAL 串讲 ) 培训讲习

类型定义:类型定义: type ren=‘A’..’F’;type ren=‘A’..’F’;

Program T6_5;Program T6_5;VarVar m,n:’A’..’F’;m,n:’A’..’F’; s: integer;s: integer; beginbegin s:=0;s:=0; for m:=‘A’ to ‘E’ dofor m:=‘A’ to ‘E’ do for n:=succ(m) to ‘F’ dofor n:=succ(m) to ‘F’ do beginbegin s:=s+1;s:=s+1; writeln (m,’------’,n);writeln (m,’------’,n); end;end; writeln (‘zhongshu=‘,s);writeln (‘zhongshu=‘,s); end.end.

例 T6_5: 新学期开学第一天,新学期开学第一天, 66个小朋友查聚后握手致意,请用个小朋友查聚后握手致意,请用 AA~~ FF 表示表示 66个小朋友,输出个小朋友,输出 66个人相互握手的各种情况,并统计握手的次数。个人相互握手的各种情况,并统计握手的次数。

Page 83: 教师 (PASCAL 串讲 ) 培训讲习

11 、常量说明语句、常量说明语句(( 11 )无类型常量的说明)无类型常量的说明 CONST CONST 常量名常量名 ==无类型常量;无类型常量; (无类型常量是真正的常量,不允许改变其值)(无类型常量是真正的常量,不允许改变其值) 例:例: const s=‘test’const s=‘test’ ;; (2) (2) 有类型常量的说明有类型常量的说明 CONST CONST 常量名: 类型常量名: 类型 == 类型变量;类型变量; (对于有类型常量,可以重新被赋值)(对于有类型常量,可以重新被赋值)

True True 和 和 false false 是布尔值常量是布尔值常量 整数标准常量 整数标准常量 maxint maxint ,其值为标准整数(,其值为标准整数( integer)integer) 的的

最大值最大值 221515-1-1

6.76.7:变量与常量说明:变量与常量说明

Page 84: 教师 (PASCAL 串讲 ) 培训讲习

22 、类型说明语句:、类型说明语句: 定义形式: 定义形式: type type 类型名类型名 == 数据类型;数据类型; 例如 例如 type type

index = 1..100; index = 1..100; {子界类型}{子界类型} number=(one,two,three,four); number=(one,two,three,four); {枚举类型}{枚举类型} 类型类型 indexindex 是用户自定义的子界类型,该类型的变量可取从是用户自定义的子界类型,该类型的变量可取从 11 到到 11

0000 区间的任一整数值。类型区间的任一整数值。类型 number number 是用户的枚举类型,该类型是用户的枚举类型,该类型的变量仅可取的变量仅可取 oneone ,, twotwo ,, threethree ,, fourfour 四个标识符之一。四个标识符之一。

枚举类型只能是标识符,不能是数值或字符常数。枚举类型只能是标识符,不能是数值或字符常数。 例以下定义是错误的:例以下定义是错误的: type type

days=(‘sun’,’mon’,’tue’,’wed’,’thu’,’fri’,’sat’)days=(‘sun’,’mon’,’tue’,’wed’,’thu’,’fri’,’sat’)

month=(1,2,3,4,5,6,7,8,9,10,11,12)month=(1,2,3,4,5,6,7,8,9,10,11,12)

Page 85: 教师 (PASCAL 串讲 ) 培训讲习

第 7课 : 数组与字符串 数组是计算机语言常用的一种数据类

型,由具有固定的相同类型的元素按一定顺序排列而成。我们先看一个例子,看出数组的必要性:

程序读入 50 个学生的成绩,求和并输出全班的总分。

Program T7_1;Var s,x:real;i:integer;Begin s:=0;For i:=1 to 50 do beginReadln(x);s:=s+xEnd;Writeln(‘s=‘,s);Readln;End.

此程序每次输入的成绩放在变量X 中,前边的成绩被后边的成绩给冲掉了,只有最有一个成绩存在变量 X 中,如果要保留中间成绩,程序就比较麻烦。如果用数组就方便多了:

For i:= 1 to 50 do readln(x[i]);S:=0;For i:=1 to 50 do s:=s+x[i];

Page 86: 教师 (PASCAL 串讲 ) 培训讲习

7.1 数组的定义Array [<下标类型 1>,…,<下标类型

n>] of <元素类型 >例: type abc=(a1,b1,c1) arr1=array[1..100] of integer; arr2=array[‘a’..’z’] of char; arr3=array[1..2,1..3] of real; arr4=array[a1,..c1] of boolren;以上定义了四个数组,其中 arr1 是一

个一维数组,下标从 1 到 100 ,元素是整型。

arr2 是一维字符数组,其下标从‘ a’到字符’ z’, 有 26 个元素。

arr3 是一个二维实型数组,有 2*3即6 个元素。

arr4 是一个一维布尔数组,其下标是枚举元素 a1,b1,c1 ,有 3 个元素。

数组类型常量的定义:Const a:array[1..2,1..3] of integer =((1,2,3),(2,3,2));相当于说明了数组变量a var a:array [1..2,1..3] of integer;且给变量 a 赋了值。a[1,1]:=1; a[1,2]:=2; a[1,3]:=3;a[2,1]:=2; a[2,2]:=3; a[2,3]:=2;

Const m:array[1..6] of integer =(2,1,5,7,9,6)相当于定义数组元素:m[1]:=2; m[2]:=1; m[3]:=5; m[4]:=7; m[5]:=9; m[6]:=6.

Page 87: 教师 (PASCAL 串讲 ) 培训讲习

7.1.1: 一维数组一维数组是指只有一个下标的数组,适用于处理一行数据或一列数据。一维数组是指只有一个下标的数组,适用于处理一行数据或一列数据。一维数组的定义形式:一维数组的定义形式:Type Type 类型标识符类型标识符 =array[=array[ 下标类型下标类型 ] of ] of 元素类型;元素类型;Var Var 数组名:类型标识符;数组名:类型标识符;或:或: var var 数组名:数组名: array [array [ 下标类型下标类型 ] of ] of 元素类型;元素类型;注意:下标类型的正确选择很重要!注意:下标类型的正确选择很重要!

例例 T7_2:T7_2: 对下列问题定义数组:对下列问题定义数组:(( 11 )) 100100名学生的数学成绩。名学生的数学成绩。(( 22 )表示)表示 5050名学生的及格或不及格的情况。名学生的及格或不及格的情况。(( 33 )统计周一至周五的学生出勤情况。)统计周一至周五的学生出勤情况。解解 : (1) var math: array [1..100] of real;: (1) var math: array [1..100] of real; (2) var jg (2) var jg : : array [1..50] of boolean;array [1..50] of boolean; (3) type day =(mon,tue,wed,thu,fri); {(3) type day =(mon,tue,wed,thu,fri); { 枚举类型说明}枚举类型说明} cq=array[day] of integer;cq=array[day] of integer; var m:cq;var m:cq;

Page 88: 教师 (PASCAL 串讲 ) 培训讲习

一维数组的应用例 T7_3: 利用一维数据,生成菲波那契数列的前 50项。

1 , 1 , 2 , 3 , 5 , 8 , 13 ,…

分析: a1=1; a2=1; an=an-1+an-2(当n≥3时)。

Program T7_3;

Var a:array[1..50] of int64;

i: integer;

Begin

a[1]:=1; a[2]:=1;

for i:=3 to 50 do

a[i]:=a[i-1]+a[i-2];

for i:=1 to 50 do

write(a[i],’ ‘);

End.

例 T7_4: (排序法)随机产生 8 个两位整数,从小到大排序。

Program T7_4;Const n=8;Var a:array [1..n] of integer;I,j,t:integer;Begin randomize; {初始化随机发生器} for i:=1 to n do a[i]:=random(90)+10; for i:= 1 to n do write(a[i]:4); writeln; { 冒泡程序排序} for i:=1 to n-1do for j:=i+1 to n do if a[i]>a[j] then begin t:=a[i];a[i]:=a[j];a[j]:=t; { 交换} end;For i:=1 to n do write (a[i]:4);Writeln;Readln; { 等待输入一个回车键}End.

Page 89: 教师 (PASCAL 串讲 ) 培训讲习

例 T7_5: 计算灯的开关状态。有 N 个灯放在一排,从 1 到 N依次顺序编号。有 N 个人也从 1 到 N依次编号。 1 号将灯全部关闭, 2号将凡是 2的倍数的灯打开; 3号将凡是 3的倍数灯相反处理(该灯如为打开的,则将它关闭;如关闭,则将它打开)。以后的人都和 3号一样,将凡是自己编号倍数的灯作相反处理。试计算第 N 个人操作后,哪几只灯是亮的?( 0—表示打开, 1---表示关闭)

题解: 设布尔数组 a为 n 只灯的状态。初始时,所有的灯打开,即 a 数组的每一个元素设为 false 。然后依次将每只灯序号的倍数作取反处理,由此得出的 a 数组元素的序数值即为最后的灯状态。

Program T7_5;Var k,n,I,j:integer;a: array[1..100] of boolean; Begin

readln(n); for i:=1 to n do a[i]:=false; for i:=1 to n do begin j:=I; while j<=n do begin a[j]:=not(a[j]); j:=j+I; end;{while}

End{for}; for i:=1 to n do write(ord(a[i]));Writeln;End.{main}

Page 90: 教师 (PASCAL 串讲 ) 培训讲习

7.2:二维数组的应用例 T7_6: 编写一程序将 n阶方阵转置。转置就是将方阵 A 的行元素转为列元素。例如:

1 2 3

4 5 6

7 8 9

1 4 7

2 5 8

3 6 93×3 3×3

程序为:Program T7_6;Const n=3;Var a: array[1..n,1..n] of integer; I,j,temp:integer;Begin for i:=1 to n do begin write(‘enter ‘,I,’:’); for j:=1 to n do read(a[I,j]); readln; end;{for} for i:=1 to n do for j:=i+1 to n do begin temp:=a[I,j];a[I,j]:=a[j,i];a[j,i]:=temp; end; for i:=1 to n do begin for j:=1 to n do write(a[I,j]:4); writeln; end;{for}Readln;End.{main}

Page 91: 教师 (PASCAL 串讲 ) 培训讲习

例 T7_7: 打印杨辉三角形将杨辉三角形写成以下形式:11 11 2 11 3 3 11 4 6 4 11 5 10 10 5 11 6 15 20 15 6 1……算法分析:Yh[1,1]=1;Yh[I,1]=1;yh[I,j]=yh[i-1,j-1]+yh[i-1,

j](2≤j≤n-1)Yh[I,i]=1

程序为:Program T7_7;Const n=6;Var yh:array[1..n,1..n] of integer; I,j ,k:ingeger; begin yh[1,1]:=1; for i:=2 to n do begin yh[i,1]:=1;yh[i,i]:=1; for j:=2 to i-1 do yh[I,j]:=yh[i-1,j-1]+yh[i-1,j]; end;{for} k:=25; For i:=1 to n do begin write(‘ ‘:k); For j:=1 to i do write(yh[i,j]:4); writeln; k:=k-2; End; Readln;End.{main}

Page 92: 教师 (PASCAL 串讲 ) 培训讲习

例 T7_8: 计算 Xn精确的每一位。设 Xn总位数在 5000位以内。

整型 Integer 型( -32768~ 32767 , 5位)只能求 7!

字型 Word 型 (0~65535,5位)只能求 8!

长整型 longint(-2147483648~2147483647,10位 )只能到 16!

实型 Real ( 1038 , 38位)虽然能求到 33!但精度已经有问题了。

扩展型 Extended(104920,4920位),精度是 19~ 20位)

Xn 的位数为 Trunc(lgXn )+1=trunc(nlgx+1)=trunc(n*ln(x)/ln(10))+1

N! 的位数为 trunc((ln(n)+ln(n-1)+ln(n-2)+…+ln(2)+ln(1))/ln(10))+1

一位存储,先将数组 C清 0 ,Y=Ai*Bj+Ci+j-1,Ci+j=Ci+j+Y div 10,Ci+j-1=Y mod 10

源程序:Program T7_8; var a,array[1..5000] of integer; i,j,n, len,len1:integer; k1,k2,x:longint; begin write(‘x^n=‘); readln(x,n); fillchar(a,sizeof(a),0); {将 a 数组每一个数值都赋为 0} len:=0; len1=trunc(ln(x)/ln(10))+1 a[1]:=1; for i:=1 to n do begin len:=len+len1; k1:=0; for j:=1 to len do begin k2:= x*a[j]+k1; k1:=k2 div 10; a[j]:= k2 mod 10; end; end; for i:= trunc(n*ln(x)/ln(10))+1 downto 1 do write(a[i]); writein; readln;End.

Page 93: 教师 (PASCAL 串讲 ) 培训讲习

思考题:

T7_9: ( 1998 年全国初中组试题) 精确计算出 s=1!+2!+3!+4!+…+n!(n≤50),其中“!”

表示阶乘。输入正整数 n, 输出计算结果 S 。

Page 94: 教师 (PASCAL 串讲 ) 培训讲习

7.3: 字符串

字符串有常量形式和变量形式。把按一定顺序排列的字符数据叫做字符串,表

示方法是将字符放入单引号中,字符串个数叫做字符串的长度。

字符串变量可以用串类型标识符 string[n]来表示。 N取值在 1~ 255之间。省略为 255 。

定义格式 : type 字符串类型名 =string [ 最大长度 ] ;定义字符串变量格式是:Var 字符串变量名:字符串类型名;

也可以直接定义字符串变量,其格式为:Var 变量名: string[ 最大长度 ] ;或 变量名: string;

字符串之间的运算:• 对字符串可以整体输入或输出,如:read(x);write(y);• 允许对串变量进行赋值,如: X:=‘abc’; y:=x 。• 可以对字符串进行连接运算,使用‘ +’进行连接。如:‘ ho’+’me’ 结果是:’ home’ 。• 字符串之间可以进行关系运算: > 、 < 、 = 、 <> 、 >= 、 <= 、 <> 。比较方法按 ASCII码一个字符一个字符比较。

Page 95: 教师 (PASCAL 串讲 ) 培训讲习

7.3.1: 字符串函数( 1 )字符串测长函数格式: length(s)功能:求字符串 S 的长度,结果为整型。(2) 求子串函数格式: copy (s,n,1);功能:在 S 串的第 N位开始截取 1位字符串。( 3 ) 查找子串函数格式: pos ( b,s) ;功能:求子串 b 在 s 中出现的起始位置,结果为整型,若未找到显示 0 。( 4 )插入过程格式: insert ( s1,s2,i);功能:将 s1插入 s2 中的第 i 个字符位置,若结果超出 s2 的最大长度,则超出的部分被截掉。( 5 )删除过程格式: delete (s,I,n);功能:删除 s 中第 i 个字符位置开始的 n 个字符。( 6 )数值转换为字符串过程格式: str(v,s);功能:将数值 V转换成字符串,存放在字符串变量 s 中。( 7 )字符串转换为数值过程格式: val(s,v,c);功能:将数字串 s转换成数值 v, 变量 C 记录检测出错的第一个字符的位置,当未出错时, C 为

0 。

Page 96: 教师 (PASCAL 串讲 ) 培训讲习

例 7_10: 统计一篇不超过 500字的英语日记中数字 1 、 2 、3 出现的次数。最后输入’ !’ 表示输入结束。

Program T7_10;

Var

a:array[1..500] of string;

n:char;

j,len.one,two,thr:integer;

Begin

read(n);

len:=0;one:=0;two:=0;thr:=0;

while n<>’!’ do

begin

len:=len+1;a[len]:=n;read(n)

end;

for j:=1 to len dofor j:=1 to len do

beginbegin

If a[j]=‘1’ then one:=one+1;

If a[j]=‘2’ then two:=two+1;

If a[j]=‘3’ then thr := thr+1;

End;

Writeln(‘1 de ge shu=‘,one);

Writeln(‘2 de ge shu=‘,two);

Writeln(‘3 de ge shu=‘,thr);

end.{main}

Page 97: 教师 (PASCAL 串讲 ) 培训讲习

例 T7_11: 输入 25 个英文单词,将它们按词典次序排序。

Program T7_11;

Type

zf= string[20];{定义字符串}Var

m:array[1..25] of zf;

n:zf;

i,j:integer;

Begin

for i:=1 to 25 do

readln(m[i]); { 读入 25 个单词}

For i:=1 to 24 do

for j:=i+1 to 25 do

if m[i]>m[j] then

begin

n:=m[i];m[i]:=m[j];m[j]:

=n;

end;

for i:=1 to 25 do

writeln(m[i]);

End.

Page 98: 教师 (PASCAL 串讲 ) 培训讲习

第 8 课: 函数与过程1 、定义新函数 function 函数名(形式参数

表):函数类型; var

变量说明部分 begin

函数体 end;

2 、函数的调用 函数名(实在参数表)

例 T8_1: 定义一个计算阶乘的函数。 Function f(n:integer):real;Var i:integer; s:real;Begin s:=1; for i:=1 to n do s:=s*I; f:=s;End;

思考题:思考题: (T8_2) 1(T8_2) 1 、 求、 求 P=P= (( a+b)! ÷(aa+b)! ÷(a !! +b!)+b!) 的值。的值。 (T8_3) 2(T8_3) 2 、定义一个函数、定义一个函数 CC (( n,k)=n!/(k!*(n-k)!),n<1n,k)=n!/(k!*(n-k)!),n<133

8.1 8.1 函数函数

Page 99: 教师 (PASCAL 串讲 ) 培训讲习

8.2 过程 函数可以看成子程序,但这样的子程序有些死板,每次必须返回值而且只返回一个值。而我们有时需返回多个值,或者不返回任何值时。这时函数就不行,而需要形式更灵活的子程序了。

1 、定义过程Procedure 过程名 (形式参数名); var 变量说明部分 begin 过程体 end;

注释: 所定义的过程名,在同一程序中,不能再作其他名称。

形式参数表括在圆括号内,一般由值形参和变量形参组成。如

Procedure abc(x,y:real;var m:real) x,y 为值形参, m 为变量形参。 与函数不同的是,不能给过程名赋值。

例 T8_2: 定义交换二个变量值的过程。Procedure swap(var m,n:char) var zhong: char; begin zhong:=m;m:=n;n:=zhong; end;

例 T8_3: 定义一个求三个数中较大数的过程。Procedure max(x,y,z:integer;var m:integer); begin if x>=y then m:=x else m:=y; if z>m then m:=zEnd;

Page 100: 教师 (PASCAL 串讲 ) 培训讲习

2. 过程的调用函数的调用不能作为单独的语句出现,而

过程的调用必须是一个单独的语句。格式: 过程名(实在参数表);例 T8_4: 求 s=3!+6!+8!程序如下:Program T8_4; var x,s:real; procedure fa(n:integer;var t:real); var k:integer; begin t:=1; For k:=1 to n do t:=t*k; end;

Begin s:=0; fa(3,x); s:=s+x; fa(6,x); s:=s+x; fa(8,x); s:=s+x; writeln (s:8:2);End.{main}

注释:• 实在参数与形式参数必须一一对应,参数之间用逗号隔开。• 实在参数可以是常量、变量或表达式。如 fa(6,x) 与 fa(2+4,x)效果一样。• 调用过程中,值形参只给过程提供数据,但不能带回结果。变量形参即给过程提供数据,也将结果带回调用的程序

Page 101: 教师 (PASCAL 串讲 ) 培训讲习

8.3: 局部变量与全程变量 局部变量的作用域是它所在的过程

或函数。 全程变量的作用域分为两种情况。

例 T8_5: 通过以下程序的运行,体会全程变量的作用域。

(1) 全程变量在过程中改变值时,新的值回到主程序后有效。

Program T8_5; var m: integer; {m 为全程变量}Procedure test1; begin m:=100; {m 在过程中改变值} end;

Begin m:=5; writeln(‘before’,m); test1; writeln(‘after’,m);End.

运行结果:Before5After100

这个例子中 M 是全程变量,它在整个程序中都有意义。 M先赋值为 5 ,调用 test1 后, M被新赋值为 100 ,由于M 为全程变量,所以 M 值被带回主程序。

Page 102: 教师 (PASCAL 串讲 ) 培训讲习

( 2 )全程变量和局部变量同名时,全程变量的作用域是包含同名局部变量的过程或函数以外的程序部分。

Program T8_6; var m: integer; {m 为全程变量}Procedure test1; Var m:integer;{局部变量,与全局变量同名} begin m:=100; {m 在过程中改变值} end;Begin m:=5; writeln(‘before’,m); test1; writeln(‘after’,m);End.

运行结果:运行结果:Before5Before5After5After5 本程序中全程变本程序中全程变量和局部变量名量和局部变量名都是都是 m,m, 由于局由于局部变量只在子程部变量只在子程序中有效,所以序中有效,所以在调用过程在调用过程 testtest11 后,主程序中后,主程序中的的 mm值不变。值不变。

Page 103: 教师 (PASCAL 串讲 ) 培训讲习

利用全程变量,我们可以对 T8_4程序进行优化,修改如下:

Program T8_7;

Var

t: integer; {将 t 定义为全程变量} s:real;

procedure fa(n:integer); { 定义过程时不再使用变量形参}

var

k:integer;

begin

t:=1;

For k:=1 to n do

t:=t*k;

end;

Begin; s:=0; fa(3); { 第一次调用过程 } s:=s+t; fa(6); { 第二次调用过程 } s:=s+t; fa(8); { 第三次调用过程 } s:=s+t; writeln(s,8,2); end. {main}

由此可见,合理使用全程变量与局部变量可以使程序及子程序的调用变量简单。

Page 104: 教师 (PASCAL 串讲 ) 培训讲习

8.4:嵌套与递归一、嵌套 一个函数或过程可能要求调用另一个

函数或过程,称为函数与过程的嵌套。

( 1 )内、外层子程充不得相互交叉,内层必须完全嵌套在外层中;

( 2 )调用原则

外层程序可以调用与它相邻的内层程序,反之不行。

同层程序处于后面的可以直接调用前面的

如果 tu1想调用 tu2必须作如下处理: … procedure tu2; {新增加的行,使 t

u2 的首部提前} forward; {向前引用说明}

主程序

过程 SUB

过程 TU1

过程 TU2

Page 105: 教师 (PASCAL 串讲 ) 培训讲习

例 T8_8: 已知 , ))!(!(! nmnmC nm

58

39 ,CC Program T8_8;

Function fac(x:integer):longint:Var i: integer;Begin fac:=1; for i:=1 to x do fac :=fac*I;End;Function c(a,b:integer):real; begin C:=fac(a)/fac(b)/fac(a-b); end;Begin writeln(‘c(9,3)=‘,c(9,3):0:0); writeln(‘c(8,5)=‘,c(8,5):0:0);End.

求:

Page 106: 教师 (PASCAL 串讲 ) 培训讲习

二、递归 函数或过程调用它本身,成为递归。递函数或过程调用它本身,成为递归。递

归在解决某些程序设计问题中是一个十归在解决某些程序设计问题中是一个十分有用的方法。它可以将某些看起来不分有用的方法。它可以将某些看起来不容易解决的问题变得容易解决,写出的容易解决的问题变得容易解决,写出的程序较简洁。程序较简洁。

例 例 T8_9: T8_9: 递归计算 递归计算 n! n! 。。 分析:分析: n! n! 可以由下列公式计算:可以由下列公式计算:

n! =n! =

因为(因为( n-1)!n-1)!乘乘 nn 等于等于 n!,n!,所以求所以求 n!n! 的的问题可以转化为求(问题可以转化为求( n-1)!n-1)! 的问题,同的问题,同理可以转化为(理可以转化为( n-2)!n-2)! 的问题的问题 ,…,… 最后最后归结为归结为 00!,而!,而 00!已经定义!已经定义 11 。由。由 00!!一步步返上去求出一步步返上去求出 1!,2!,…,1!,2!,…, 直到求出直到求出n!n! 。。

1 n=0

n(n-1)! n >0

Program T8_9;Program T8_9;VarVar n: integer;n: integer; y:real;y:real;Function fac(n:integer):real;Function fac(n:integer):real; beginbegin if n=0 then fac:=1if n=0 then fac:=1 else fac:=n*fac(n-1);else fac:=n*fac(n-1); end;end;BeginBegin readln(n);readln(n); y:=fac(n);y:=fac(n); writeln(n,’!=‘,y:10:0);writeln(n,’!=‘,y:10:0);End.End.

本程序本程序 N<=170,N<=170,否则要溢出。否则要溢出。

11 、 直接递归:、 直接递归:过程与函数直接调用自己过程与函数直接调用自己

Page 107: 教师 (PASCAL 串讲 ) 培训讲习

2、间接递归:通过调用其他过程或函数间接调用自己

例例 T8_10: T8_10: 验证角谷猜想。验证角谷猜想。 对于一个正整数对于一个正整数 N, N, 若若 NN 为奇为奇

数则乘以数则乘以 33加加 11 ,若,若 NN 为偶数为偶数则除以则除以 22 ,有限步后,有限步后 N=1N=1 。。

Program T8_10;Program T8_10;Var Var i:integer;i:integer;Procedure Q(var m:integer);Procedure Q(var m:integer);Forward;Forward;Procedure P(var n:integer);Procedure P(var n:integer);BeginBeginn:= n div 2; write(n:3);n:= n div 2; write(n:3);

If n>1 thenIf n>1 then if odd(n) then Q(n) else P(n);if odd(n) then Q(n) else P(n);End;End;Procedure Q(var m:integer);Procedure Q(var m:integer);BeginBegin m:=m*3+1; write(m:3);m:=m*3+1; write(m:3); P(m);P(m);End;End;BeginBegin readln(i);readln(i); If odd(i) then Q(i) else P(i);If odd(i) then Q(i) else P(i); Readln;Readln;end.end.

Page 108: 教师 (PASCAL 串讲 ) 培训讲习

例 T8_11: 骨牌辅法。有 1×n 的一个长方形,用一个 1×1 、 1×2 和 1×3 的骨牌铺满方格。例如 n=3时为1×3 的方格。此时用 1×1 、 1×2和 1×3 的骨牌辅满方格,共有四种辅法。

输入 n(0≤n ≤30), 输出铺法总数。分析:将 n 格分成 n-x 格和 x 格。

N-1 格

N-2 格N-2 格

N-3 格 N-3 格

N-3 格 N-3 格

F(1)=1F(2)=2F(3)=4F(n)=f(n-1)+f(n-2)+f(n-3) (当 n≥4)

Program T8_11;Var n:integer;Function f(i:integer):longint;Begin if i in [1..2] Then f:=i else if i=3 then f:=4 else f:=f(i-1)+f(i-2)+f(i-3);End;{f}Begin readln(n); { 输入格子数}Writeln(f(n)); {计算和返回总数}End.{main}

Page 109: 教师 (PASCAL 串讲 ) 培训讲习

第 9 课 文件 当一个程序需要输入大量的数据,由键盘

输入数据是很麻烦的。我们引入用户自定义的文件,常用于人与计算机,或者计算机与各类设备之间进行数据传递。文件可以存储在磁盘、光盘等外部设备上,故通常称为外部文件。

9.1: 文件的类型Free pascal 语言中的文件可以从不同的角度进行分类。从文件的内容来区分,分为两种类型:程序文件和数据文件。

从文件的结构来区分,一般分为文本文件和随机文件两种类型。

( 1 )文件文件。具有行结构的字符文件。( 2 )随机文件。是以二进制形式存储在磁盘上的,不具有行结构。

目前,在青少年信息学奥林匹克竞赛( NOI )和分区联赛( NOIP )复赛中,输入数据和输出数据都要求采用文本文件形式。

9.2: 文本文件的概念一、文件名Free pascal 语言规定文件名由主文件名和扩展名两部分组成,中间用“ .” 分隔。 主文件名 .扩展名 主文件名由 1~ 3 个字符组成,扩展名由最多 3 个字符。扩展名可以省略。在信息学竞赛中,常用 .in作为输入文件的扩展名, .out作为输出文件的扩展名。二、文件的指针文本文件是顺序存取文件。对于某个文件只能从中读取或写入数据,不能同时即读又写。为方便读取,对每个文件设置一个指针,指向读写的位置。

Page 110: 教师 (PASCAL 串讲 ) 培训讲习

9.3: 文件的基本操作1 、链接文件Assign ( 文件变量,‘文件名’);例如: assign(t,’d:\fp\f1.dat’);

在 free pascal 语言中链接文件是建立、打开文件进行读写数据的关键步骤。

2 、建立文件( 1 ) Program 程序名( input,output, 文件名);( 2 ) var 说明文件变量的类型。 文件变量: text;

( 3 ) assign ( 文件变量,‘文件名’); ( 4 ) rewrite (文件变量);对文件初始化,使该文件为空白文件,准备写入数据。文件指针指向文件之首。 (5) write( 文件变量,变量);作用是将变量的值写入指针所指的文件变量的当前位置中。

Page 111: 教师 (PASCAL 串讲 ) 培训讲习

例 T9_1: 将 1 , 2, 3,… ,9 , 10这 10 个数写入到文本文件 f1.dat 中。要求相邻两数用一个空格分隔。

Program T9_1(input,output,f1);

Var

t : text;

i : integer;

Begin

assign(t,’f1.dat’);

rewrite(t);

for i:=1 to 10 do

begin

write (t,i);

write (t,’ ‘);

end;

Colse (t);

End.

例 T9_2: 产生 6 个 0 到 100之间的随机整数,写入到文本文件 sj.in 中。要求每行 3 个数,两数之间用一个空格分隔。

Program T9_2;Var f: text; I,x:integer;Begin randomize; assign(f,’sj.in’); rewrite(f); For i:=1 to 6 do begin x:=random(100); write (f,x); if I mod 3=0 then writeln(f) else write(f,’ ‘); End; close (f);End.

Page 112: 教师 (PASCAL 串讲 ) 培训讲习

3、打开文件当程序需要对文件中的数据进行读取操作之前,要打开保存在磁盘上的文件。

打开文件读取数据的操作步骤为:( 1 ) program 程序名;( 2 ) var 文件变量: text;( 3 ) assign( 文件变量,‘文件名’);( 4 ) reset ( 文件变量); reset 语句的作用将文件指针指向文件之首,准备从文件的第一个分量开始读数。

( 5 )用 read 语句由文件中读取数据。 read ( 文件变量,变量);

例 T9_3: 从例 T9_1建立的文本文件 f1.dat 中读取数据,并在显示器上输出数据。计算这 10 个数据的和并输出。Program T9_3;Var t:text; I,x,s:integer;Begin assign(t,’f1.dat’); reset(t); s:=0; for i;:= 1 to 10 do begin read (t,x); write (x,’ ‘); s:=s+x; end;

Page 113: 教师 (PASCAL 串讲 ) 培训讲习

4 、关闭文件 : Close (文件变量); 5、文件修改 : append(文件变量);如果需要,在原有的文本文件最后写入新数据, append语句可以完

成这项任务。 6 、读取数据: read(文件变量,变量表); readln (文件变量,变量表); 这二个语句的执行结果是将文件中的数据依次读入到变量表中的各个

变量之中。 Read语句与 readln 语句的区另主要表现在对程序中下一个输入语句的执行上,当使用 read语句时,程序中的下一个 read语句执行时,将在本次指针位置后读入数据;如果使用 readln语句,则执行下一个 read语句时,将换行从下一行的行首位置向后读入数据。

如果通过键盘输入数据的 read语句写完整的话,其格式为: read(‘input’,变量表);其中‘ input’可以省略 ,写成:

read (变量表) ;

Page 114: 教师 (PASCAL 串讲 ) 培训讲习

7 、写入数据: write ( 文件变量,数据表); 或: writeln ( 文件变量,数据表); 区别在于使用 write 语句时,程序中下一个 Write将在本次指

针位置向后输出数据;如果使用 writeln 语句时,将换行从下一行的行首位置向后输出数据。

其中,文件变量同前所述,数据表是一个表达式表,可以有多个表达式,不同表达式之间用“,”分隔。

例如: write(t,x,y); 将表达式 x,y 的值依次写入到文件 t 中。 如果要在显示器上输出运行结果,其格式为: write(‘output’,数据表); 其中的 output 表示系统的标准输出设备,即显示器,故可省略。 设 x 为实数 123.456 ,在不同语句设置中执行情况如下: 执行 writeln(t,x); 语句时,将在文件变量 t 链接的文本文件中写

入: 1.2345600000E+02 执行 writeln(t,x:10:4); 语句时,在文件中写入: 123.4560 执行 writeln(t,x:10:2); 语句时,在文件中写入: 123.46

Page 115: 教师 (PASCAL 串讲 ) 培训讲习

9.4:文本文件的操作函数1 、 eoln 函数格式: eoln( 文件变

量)功能:检测文本文件当前行是否结束。如果文件当前指针的下一个字符为行结束或文件结束符,函数返回值为 true,否则为 false 。

2 、 eof 函数格式: eof( 文件变

量)功能:检测文件是否

结束。若是则为true,否则为 false 。

例 T9_4: 在例 T9_2建立的文本文件 sj.in 中存有 2组数,每组 3 个整数,求每组数的和。输入格式:文本文件 sj.in存有 6 个数据,分为 2 行,每行 3 个数,有空格分隔。输出格式:结果输出到文本文件 h.out, 每行 1 个数。

Program T9_4;Var t,m:text; I,x,y,z,w:integer;Begin assign (t,’sj.in’); reset (t);{将指针指向 t 文件首} assign (m,’h.out’); rewrite(m); { 使 m 为空白文件} while not eof(t) do {当 sj 文件未结束时执行循环}

Begin readln(t,x,y,z); w:=x+y+z; writeln(m,w);

End;Close(t);Close(m);End.

Page 116: 教师 (PASCAL 串讲 ) 培训讲习

文本文件的基本操作步骤操作步骤 语句 功能定义文件变量类型 文件变量: text 说明文件变量类型

链接文件 Assign( 文件变量,文件名); 链接程序中的文件变量和要访问的磁盘文件

建立文件 Rewrite( 文件变量); 初始化文件,使该文件为空白文件,准备写入数据

打开文件 Reset( 文件变量); 初始化文件,准备读取数据

关闭文件 Close( 文件变量 );关闭文件,结束文件变量与磁盘文件的链

文件修改 Append( 文件变量 ); 在原有的文本文件最后写入新数据

读取数据 Read( 文件变量 , 变量); 由文件中读取数据写入数据 Write( 文件变量 ); 向文件写入数据

Page 117: 教师 (PASCAL 串讲 ) 培训讲习

第 10课 集合和记录

10.1.1 、集合类型 集合是具有共同性质的一组数据构成的整体,集合中的数据叫做集合元素,简称元素。例如 10以内的质数构成一个集合,它包括 2 、 3 、 5 、7共 4 个元素, PASCAL 中用[ 2 , 3 , 5 , 7]表示。不包括任何元素的集合叫做空集,用[]表示。

集合具有如下性质:( 1 )元素唯一性;( 2 )元素无序性。

PASCAL 语言提供一种自定义数据类型 ----集合类型,可以用来表示集合。但有以下限制(区别于纯数学理论的集合概念):

集合元素必须是有序类型的数据(数学集合元素可以是实数)。 集合的元素数目不能超过 256 个(数学集合元素个数可以是任意个)。

Page 118: 教师 (PASCAL 串讲 ) 培训讲习

10.1.2 集合的定义定义集合类型格式:定义集合类型格式: type type 集合类型名集合类型名 =set of =set of 基类型;基类型;说明:说明: 类型名应该是一个合法的标识符;基类型名应该是一个合法的标识符;基

类型是集合中元素的类型,它必须类型是集合中元素的类型,它必须是有序的类型,元素的序号范围必是有序的类型,元素的序号范围必须在须在 00 到到 255255之间。之间。

定义集合变量格式:定义集合变量格式: var var 变量名:集合类型名;变量名:集合类型名;这样定义的变量就是一个集合变量,在这样定义的变量就是一个集合变量,在

程序中表示一个集合。程序中表示一个集合。

允许集合类型描述和变量定义合并在一允许集合类型描述和变量定义合并在一起,共格式为:起,共格式为:

var var 变量名:变量名: set of set of 基类型;基类型;

例:下面集合定义是正确的:例:下面集合定义是正确的: typetype T1= set of 1..5;T1= set of 1..5; T2= set of char;T2= set of char; T3= set of (while,read,blue);T3= set of (while,read,blue);

下面集合定义是错误的:下面集合定义是错误的: typetype T1= set of integer;T1= set of integer; T2= set of -30..-20;T2= set of -30..-20; T3= set of real;T3= set of real; T4= set of 200..300;T4= set of 200..300;

Page 119: 教师 (PASCAL 串讲 ) 培训讲习

10.1.3 集合的操作( 1 )赋值运算: var a:set of 0..255;

begin

a;=[2,3,5,7];

(2) 集合元素不能用 read 和 wrte 语句直接输入和输出。如果需要输入和输出集合元素,必须借助集合的运算来实现。

Program T10_1;

var s:set of 0..255;

i:integer;a,b:0..255;

begin

s:=[ ];

for i:=1 to 10 do begin

read (a); s:=s+[a];end;

For b:=0 to 255 do

if b in s then

write(b,‘ ’);

end.

(3) 元素与集合可以进行‘属于’运算。例: 1 in [ 1,2,3] 为 true, 1 in [ 2,3,4 ] 为 fluse. in 相当于数学里集合运算符‘∈’。(4)集合之间可以进行‘并’、‘差’、‘交’三种集合运算。

• 并运算符为“ +” ,所得集合叫做并集。例

[ 1 , 2] +[ 1 , 2 , 3 , 4] =[ 1 , 2 , 3 , 4]

• 差运算符为“ -” ,所得集合为属于A且不属于 B 的全部元素。

例:[ 1 , 2 , 3] -[ 2] =[ 1 ,3]

[ 1 , 2 , 3] -[ 4] =[ 1 , 2 ,3]

• 交运算符为“ *” ,其元素为属于 A且属于 B 的全部元素。

例:[ 1 , 2 , 3] *[ 2 , 3 , 4]=[ 2 , 3]

[ 1 , 2 , 3] *[ 4 , 5] =[ ](空集)

Page 120: 教师 (PASCAL 串讲 ) 培训讲习

( 5 )集合之间可以进行“相等”和“包含”两种运算,运算结果为布尔值。

相等(运算符为“ =” ) 表达式 [ 1 , 2] =[ 1 , 2]为 tr

ue,

表达式[ 1 , 3] =[ 1 , 2]为 fluse.

包含(运算符为“》 =” 和“《 =”

表达式 [ 1 , 2 , 3]》 =[ 1 , 2]为 true ,

表达式 [ 1 , 3]》 =[ 1 , 2 , 3]为 fluse.

相当于数学中集合运算“ ”、和“ ”。

例 10_2: 设集合 a=[2,3,5,7,8],b=[1..5],

c=[3,4,5,7,9], 求 a*b-c.

解: a*b=[2,3,5]

a*b-c= [2,3,5]-[3,4,5,7,9]=[2]

例 11_3: 用筛选法求 200 以内的质数。分析:筛选法的基本思想是:( 1 )设立一个 2 到 n之间的全体整数的集合 S;( 2 ) 设立一个集合 S1 ,用于存放筛选出的质数; ( 3 ) i 从集合 S 中最小的质数 2开始;( 4 )先将 i 添加到 S1 中,然后将 i的所有整数倍(包括 i 本身)从 s 中删除,此时剩下的最小元素 x 一定是与 i紧邻的质数;( 5 )通过循环累加的方法,将 i 更新为 x ;( 6 )重复执行第 4 、 5步,直到 S中己没有元素为止。此时 S1 中存放的就是筛选出来的 2 到 n之间的全体质数。

Page 121: 教师 (PASCAL 串讲 ) 培训讲习

Program T10_3; var s,s1:set of 2..200; i,j:2..200; begin s:=[2..200]; {s 最初是 2 到 200 之间的全体整数}

s1:=[]; i:=2; repeat if i in s then begin s1:=s1+[i]; for j:=i to 200 do if j mod i =0 then s:= s-[j]; end;

i:= i +1;Until s=[ ];For i:=2 to 200 do if i in s1 then write(i:4);End.

Page 122: 教师 (PASCAL 串讲 ) 培训讲习

10.2 记 录如图书馆的图书卡片:书名: PASCAL 语言作者:张文双、吴树娟定价: 30.00 元页数: 242页

为了表示这样的数据,可以使用 PASCAL语言提供的记录类型。记录( record) 是由一组不同类型的数据项构成,记录中的数据项叫做记录的域( field) 。

域也叫做字段。

10.2.1 记录的定义

1 、记录类型的定义

type

类型名 =record

域名 1 :类型 1 ;

域名 2 :类型 2 ;

域名 3 :类型 3 ;

End;

2 、记录变量的定义

var

变量名:记录类型名;

也可以将类型描述与变量定义合并一起,其格式为:

var 变量名: record 域名 1 :类型 1 ; 域名 2 :类型 2 ; … 域名 3 :类型 3 ; end;

Page 123: 教师 (PASCAL 串讲 ) 培训讲习

10.2.2 记录的运用例 10_4: 编写一个通讯录,从键盘接收 10 个人的资料,然后显示出来。

程序为: program T10_4; const n=10; type TDirrec=record num:integer; name: string[10]; Tele:string[20]; addr:string[50]; end; TDir=array[1..n] of TDirrec;

序号 姓名 电话号码 家庭地址

1 张三 *** ***

2 李四 *** ***

3 王五 *** ***

4 赵六 *** ***

Var Dir:TDir; i :integer;Begin for i :=1 to n do begin Dir[i].num:=i; write(input name:’); readln(Dir[i].name); write(‘input telephone:’); readln(Dir[i].Tele); write(‘input address:’); readln(Dir[i].addr); end; for i:=1 to n do begin writeln(No.’,Dir[i].num); writeln(Dir[i].name); writeln(Dir[i].Tele); writeln(Dir[i].addr); end; End.

Page 124: 教师 (PASCAL 串讲 ) 培训讲习

10.2.3 开域语句( with 语句) 在程序中,我们经常集中使用同一个记录

的各个域。例如: card1.Title := ‘PASCAL 语言’ ; card1.Author := ‘张文双、吴树娟’ ; card1.Price := 30.00; card1.Page :=242;这时,就要将记录的名字重复书写多次。

PASCAL 语言提供了“开域语句”。格式如下: with 记录 do 语句;其中, with 后面指定了一个确定的记录,

do 后面的语句可以直接引用该记录中的域,无须再指明记录。 do 后面的语句可以是简单语句,也可以是复合语句。

上述语句改写为:

with card1 do begin

Title := ‘PASCAL 语言’ ; Author := ‘张文双、吴树娟’ ; Price := 30.00; Page :=242;End;

Page 125: 教师 (PASCAL 串讲 ) 培训讲习

第 11 课 指针数据结构分为两类:----静态数据结构和动态数

据结构。前面介绍的数组、记录和集

合都属于静态数据结构。其特点是:变量定义后,PASCAL系统自动为变量分配内存空间。当需要对己赋值数组的某个位置插入 ( 或删除 ) 一个数据时,会造成众多数据的后移(或)前移,算法会很复杂。

为了弥补静态数据结构的上述不足, PASCAL系统引入指针变量。

12.1 指针变量例如:变量 P 是一个存储地址的变量,其自身的地址是 100 ;变量 q 是一个存储整数 30 的变量,其地址是 150 ,从 P 的内部画一个箭头指向 q ,如图所示:

100 150 p q 30

P称为指针变量,指针变量存放的是变量q地址,通过这个地址可以找到 q 中的数据 30 。指针箭头所指变量存储的数据类型称为指针变量的基类型。指针变量的基类型可以是除文件类型以外的其他数据类型。

Page 126: 教师 (PASCAL 串讲 ) 培训讲习

11.1.1 指针变量的定义格式 1 : type 指针类型标识符 = ^ 基类型标识符; var 指针变量名:指针类型标识符;

例如: type P= ^integer; var p1,p2:P; 先定义了一个指针变量 P ,指向整型

变量。然后定义了两个类型的变量P1 和 P2 ,它们的值分别是存储单元的地址,而存储单元恰好能存放一个整型数据。

格式 2 : Var 指针变量名: ^ 基类型标识符; 例:上例也可表示成: var p1,p2: ^integer;

Page 127: 教师 (PASCAL 串讲 ) 培训讲习

11.1. 2 指针变量的基本操作

1 、新建存储地址格式: new( 指针变量);例如: new(p);

功能:分配一个存放数据的存储单元,并把该存储单元的地址赋给指针变量 p 。

注意:一个指针变量只能存放一个地址。如果程序再次执行 new(p) 语句,将在内存中开辟另外一个新的存储单元,并将其地址放在 p 中,从而丢失了原存储单元的地址。

2 、释放存储单元为了节省内存空间,系统通过标准

过程 dispose释放不再使用的存储单元。

格式: dispose( 指针变量);例如: dispose(p);

功能:释放指针变量 p所指向的存储单元,使指针变量的值取 nil(空指针值),即指针不指向任何变量。

Page 128: 教师 (PASCAL 串讲 ) 培训讲习

3. 指针变量的引用 利用 new 过程可以将一个存储单元的地址值赋给一个指针变量,通常我们并不需要了解这个地址值,而真正关心的上该指针变量所指向的存储单元的数据。

Pascal 用 q^来表示指针变量 q所指向的存储单元的内容。对于 q 和 q^我们都可以用赋值语句赋值,只是效果大不相同。前者赋给的是地址值,可以改变 q 的指向;后者赋给的是数据内容,改变的是 q所指向的存储单元的内容。

格式:(指针变量) ^:= 数据;例如: q^:=2;

功能:在指针变量 q所指向的存储单元中,存储的数据是 2 。

例:执行语句 p:=q; 是将 q 的值( q所指向存储单元的地址)赋给变量 p, 这样 p 与 q都同时指向 q所指向的存储单元。

例:执行语句 p^:=q^; 是将 q所指向的存储单元的数据存放到p所指向的存储单元中。这样p 和 q虽然指向不同的存储单元,但两个存储单元的数据是相同的。

Page 129: 教师 (PASCAL 串讲 ) 培训讲习

11.2 链表设有一批整数( 66 , 92 , 49 , 86 , 75 ,…),如何存放呢?当然我们可以选择学过的数组类型。但是,如果事先不能确定整数的个数,就要定义一个中够大的数组,这种做法处理问题,就会浪费内存,这就是静态存储结构的局限性。

我们利用前面介绍的指针变量可以构造一个简单而实用的动态数据结构 ----- 链表。如图所示是一个简单链表结构示意图: head 2020 1324 3360 2895 5102

2020 66 92 49 86 75

1324 3360 2895 5102 nil

在这个链表中,每个框表示链表的一个元素,称为结点。框顶端的数字表示该存储单元的地址(这里的地址是假设的)。第 1 个结点称为表头 head ,框内的数字 202 表示表头的地址。后面的每个结点有两个域。第一个域是数字域(存放数据),第二个域是指针域(存放下一个结点的地址)。表尾结点的指针域值为空( nil ),用来表示表的结束。指向表头的指针( head)称为头指针,当头指针 head 为 nil时,称为空链表。链表作表头与表尾外,每一个结点都有一个直接的前趋结点和一个后继结点。相邻结点的地址可以互不连续,它们靠指针域相互联系。

Page 130: 教师 (PASCAL 串讲 ) 培训讲习

11.2.1 链表的定义要定义一个链表,每个结点要定义成记录型,而且其中有一个域为指针。例如:

type pt=^node; node=record data:integer; next:pt end; var p1,p2:pt;说明:上面定义了两个指针变量:

p1 和 p2,其基类型为 node 。 Node 是一个自定义记录类型,有两个域:数据域 data, 类型为整型;指针域为 next ,类型为 pt 型。在这种定义中,指针中有记录,记录中有指针,形成一种递归关系。

如果在上述结点定义后,程序中出现如下语句:New(p1);new(p2); {新建两个存储单元}p1^.data:=100;{指针变量 p1所指的存储单元的数据域赋值为 100}P1^.next:=p2; {将指针变量 p2所指存储单元的地址赋值给 p1 的指针域}

这样就将两个独立的存储单元通过指针域连接起来,此时链表中这两个结点的状态如图所示:

201 412p1 p2

100

412

Page 131: 教师 (PASCAL 串讲 ) 培训讲习

11.2.2 建立链表一个链表的建立步骤为:1 、申请新结点;2 、为结点的数据域和指

针域赋值;3 、将结点链接到表中的

某一位置。

例 12_1: 建立一个有 10个结点的链表,最后输出该链表。

分析:首先应定义指针类型、结点类型和指针变量。从表头开始建立链表。先用指针 p1构造头结点,为头结点申请存储单元后,为其数据域赋值,令头指针 h 指向结点的指针域。

Program T11_1; type pt=^node; node=record data:string[5]; next:pt^ end; var p1,p2,h:pt; i:integer; Begin new(p1); writeln(‘input data1:’); readln(p1^.data); h:=p1;

For i:=1 to 9 do begin new(p2); writeln(‘input data:’); readln(p2^.data); p1^.next=p2; p1:=p2; end; p2^.next:=nil; p1:=h; while p1<>nil do begin write(p1^.data,’’); p1:=p1^.next end;End.

Page 132: 教师 (PASCAL 串讲 ) 培训讲习

链表的举例1 、队(先进先出)。此种链表按照输入数据的顺序建立。先输入位于表

首,后输入的数据位于其后。输出时按从表首到表尾的顺序进行,正好与输入顺序一致,所以称为先进先出链表。

head a1 a2 an-2 an-1 an

2 、栈(先进后出)。此种表后输入的数据放在先一个输入的数据之前。这样,最先输入的数据位于表尾,最后输入的数据位于表首。输出时按从表首与表尾的顺序正好与输入顺序相反,所以称先进后出表。

head an an-1 a3 a2 a1

hil

hil

Page 133: 教师 (PASCAL 串讲 ) 培训讲习

例 T11_2: 读入一组非负整数,以负数为输入结束标志,建立先进先出的链表并输出。(建队)

Program T11_2; type pt=^node; node=record data:integer; next:pt end; var h,p1,p2:pt; x:integer; begin h:=nil; read(x); while x>=0 do

begin if h=nil then begin new(p1); p1^.data:=x; p1^.next:=nil; p2:=p1; { 指针 p2 指向当前链表(即

p1所指)的尾结点} h:=p1 { 指针 h 指向当前链表的尾结点}

end else begin new(p1); p1^.data:=x;

p1^.next:=nil; p2^.next:=p1; p2:=p1 end; read(x); end;

p1:=h; while p1<>nil do begin write(p1^.data:5); p1:=p1^.next end; writeln;End.

Page 134: 教师 (PASCAL 串讲 ) 培训讲习

例 T11_3: 读入一组实数,以负数为输入结束标志,建立先进后出的链表并输出。(建栈)

Program T11_3; type pt=^node; node=record data:real; next:pt end;

var h,p:pt; x:real;

begin

p:=nil; {初始准备} read(x);

while x>=0 do begin new(h); h^.data:=x; h^.next:=p; { 链接到当前链表的表

首} p:=h; { 调整指针 p 指向当前链

表的表首} read(x); end;

{ 输出链表 }while p<>nil do begin write(p^.data:5:1); p:=p^.next end; writeln;End.

h p

hilx

Page 135: 教师 (PASCAL 串讲 ) 培训讲习

11.2.3 插入结点 要往数组里插入一个元素比较困难,首先要确定插入位置,然后将从该位置

以后的所有元素依次后移一个位置,以便空出一个位置插入新元素。而采用链表插入比较简单。在确定插入位置后,不必移动链表中的元素,只需给相应的指针重新赋值就可以了。我们分三种情况进行分析:

1 、插入表头:h

hil

hil

h

qq^.next:=h;h:=q;{q 为表头,所以调整头指针 h, 指向 q}

2 、插入表中:p1^.next:=q;q^.next:=p2;

p1 p2

hil

h

p1 p2h

qq^.next:=h;h:=q;{q 为表头,所以调整头指针 h, 指向 q}

q

Page 136: 教师 (PASCAL 串讲 ) 培训讲习

3 、插入表尾 插入表尾只需

执行下列语句:p2^.next:=q;q^.next:=nil;

h

hil

h

hilp2

q

例 T11_4: 在一个有序链表中插入一个新的结点,仍为有序链表。Procedure insert(x:real;var h:point);Var q,p1,p2:point;Begin new(q); q^.data:=x; if x<=h^.data then begin q^.next:=h; h:=q end else begin p2:=h;

while (x>p2^.data) and (p2.next<>nil) do begin p1:=p2; p2:=p2^.next end; If x<=p2^.data then begin p1^.next:=q;q^.next:=p2; end; else begin p2^.next:=q;q^next:=nil end endEnd;

Page 137: 教师 (PASCAL 串讲 ) 培训讲习

11.2.4 删除一个结点

要从一个链表中删除一个结点,首先在链表中找到该结点,然后将其前趋结点的指针域指向其后继结点即可。如图要删除 p2 结点,只需执行语句:

p1^.next:=p2^.next;

就可以了。

p1 p2

p1 p2

被删除结点所占用的存储空间,可以通过 dispose(p2)释放。

Page 138: 教师 (PASCAL 串讲 ) 培训讲习

例 T11_5: 编写一个过程,将链表中值为 x的第一个结点删除。分析:有三种情况存在,头结点数据值为 x; 除头结点外的某个结点数据域的值为 x ;没有数据域值为 x 的结点。

算法分两步完成:查找、删除。( 1 )查找。从头开始遍历表,直到找到目标或到达表尾为止。( 2 )删除。如果目标找到,将其删除,设置标志( delete) 为真,否则设置为假。

Procedure delete(x:real;var h:pointer; var delete:boolean); { 删除结点的过程}Var p1,p2:pointer; begin p2:=h; while (p2^.data<>x) and (p2^.next<>nil) do {遍历表直到找到目标或到达表尾} begin p1:=p2; p2:=p2^.next end;

If p2^.data=x then begin delete:=true; if p2=h then h:=h^.next else p1^.next:=p2^.next end else delete:=flaseend;

Page 139: 教师 (PASCAL 串讲 ) 培训讲习

11.2.5 循环链表 前面所介绍的链表尾结点的指针域为空( nil ),称为单向链表。如果让表尾

结点的指针域指向表头结点,就使整个链表形成一个环形。这种首尾相接的链表称为循环链表。在循环链表中,从任意一个结点出发都可以找到表中的其他结点。如图所示就是一个单循环链表。

h

单循环链表的操作和单向链表的基本一致,只是在循环终止条件上有所不同:前者是指针变量再一次指向表头结点;后者是指针变量的指针域为空( nil) 。

例 T11_6: (约瑟夫问题)旅行社要从 n名旅客中选出一名幸运旅客,为他提供免费服务。方法是,大家站成一圈,然后指定一个数 m 。从第 1 个人开始报数 1 , 2 , 3 ,…,报到m 的人退出圈外,然后从下一个人开始重新从 1报数,重复这个过程,直到只剩下一个人时,此人就是幸运之星。请由键盘输入 n,m, 输出退出圈外客人的序号,选出幸运之星。

分析:因为 n 个人是围成一个圈的,所以第 n 个人后面的应该是第 1 个人,这就形成了一个环。利用单循环链表求解,将客人的编号作为结点数据域的值,将指向下一个人的地址作为结点的指针域值。

Page 140: 教师 (PASCAL 串讲 ) 培训讲习

Program T11_6;Type pt=^node; node=record data:integer; next:ptEnd;Var m,n,i:integer; p1,p2,h:pt;Begin write(‘input n,m:’); readln(n,m); new(p1); p1^.data:=1; h:=p1;For i:=2 to n do begin new(p2); p2^.data:=i; { 结点数据域赋值} p1^.next:=p2; {结点指针域赋值} p1:=p2End;

P1^.next:=h; {链表首尾相接}

i:=1;P1:=h;Repeat p2:=p1^.next; i:=i+1; if i mod m =0 then begin p1^.next:=p2^.next; { 删除结点} write(p2^.data:8); {退出客人的序号} p2^.next:=nil; dispose(p2) end else p1:=p2Until p2^.next=p2;Writeln;Writeln(‘the luck star is no:’,p2^.data) { 输出幸运之星}End.

Page 141: 教师 (PASCAL 串讲 ) 培训讲习

解法二:用数组方法分析:算法步骤如下:1 、由于对于每个人只有出圈或不出圈两种状态,因此设置标志数组存放游戏过程

中每个人的状态。不妨用 1 表示出圈, 0 表示不出圈。2 、给标志数组赋初值为 0 。3 、模拟报数游戏全过程。 T从 1 变化到 N控制报数游戏的每节循环,它实际上是

一个指针变量,依次指向当前报数的位置;用 S累计每节报数的数值;用 F统计出圈的总人数;因此 F=N时游戏结束。

Program T11_6_2;Var n,m,s,f,t:integer; a:array[1..100] of 0..1;Begin write(‘Input n,m=‘); readln(n,m); for t:=1 to n do a[t]:=0; f:=0;t:=0;s:=0; write(‘coming out is:’);

Repeat t:=t+1; if t=n+1 then t:=1; if a[t]=0 then s:=s+1; if s=m then begin s:=0; write(t:5); a[t]:=1; f:=f+1; end;Until f=n;Readln;End.

Page 142: 教师 (PASCAL 串讲 ) 培训讲习

第 12课 : 编程训练例 T12_1: 如果一个自然数除了 1 和本身 ,还有别的数能够整

除它 ,  这样的自然数就是合数。例如 15, 除了 1 和 15,还有3 和 5 能够整除 ,所以 15 是合数。 14,15,16 是三个连续的合数 , 试求连续十个最小的合数。

解:从 14,15,16三个连续合数中可看出 , 它们正好是两个相邻素数 13 和 17 之间的连续自然数 ,所以求连续合数问题可以转化为求有一定跨度的相邻两个素数的问题。因此,求连续十个最小的合数可用如下方法:

①从最小的素数开始,先确定第一个素数 A; ②再确定与 A相邻的后面那个素数 B;(作为第二个素数 ) ; ③检查 A,B 的跨度是度否在 10  以上 , 如果跨度小于 10,就把 B 作为新的第一个素数 A,重复作步骤② ;

④如果 A 、 B跨度大于或等于 10 ,就打印 A 、 B之间的连续 10 个自然数,即输出 A+1, A+2, A+3 …,  A+10 。

Page 143: 教师 (PASCAL 串讲 ) 培训讲习

Pascal 程序:Program  T12_1;Program  T12_1;var a,b,s,n: integer;var a,b,s,n: integer;        yes: boolean;yes: boolean;procedure sub(x: integer;var yy: booleaprocedure sub(x: integer;var yy: boolea

n);          {n);          { 过程:求过程:求 xx 是否为素数 是否为素数 }}var k,m: integer;         { var k,m: integer;         {  用用 yyyy逻辑值转出逻辑值转出

}}beginbegin    k:=trunc(sqrt(x));k:=trunc(sqrt(x));    for m:=2 to k dofor m:=2 to k do              if x mod m=0 then yy:=false;if x mod m=0 then yy:=false;end;end;

Page 144: 教师 (PASCAL 串讲 ) 培训讲习

begin                  {begin                  { 主程序 主程序 }}    b:=3;b:=3;    repeatrepeat        a:=b;                       {a a:=b;                       {a  为第一个素数 为第一个素数 }}        repeat repeat         yes:=true;yes:=true;    inc(b,2);                               {binc(b,2);                               {b 是是 aa 后面待求的素数后面待求的素数 ,,相当于执行了相当于执行了 b:=bb:=b

+2}+2}        sub(b,yes);                    {sub(b,yes);                    { 调用调用 SUBSUB 过程来确认过程来确认 bb 是否为素数 是否为素数 }}        if yes then s:=b-a;                     {if yes then s:=b-a;                     { 如果如果 bb 是素数,则求出跨度是素数,则求出跨度 s  }s  }            until yes;until yes;        until s > = 10;until s > = 10;        for n:=a+1 to a+10 dofor n:=a+1 to a+10 do              write(n:6);write(n:6);        writeln;writeln;        readlnreadln    end.end.

Page 145: 教师 (PASCAL 串讲 ) 培训讲习

例 T12_2:

将合数 483 的各位数字相加( 4+8+3 ) =15 ,如果将 483 分解成质因数相乘: 483=3*7*23 ,把这些质因数各位数字相加( 3+7+2+3 ),其和也为 15 。即某合数的各位数字之和等于它所有质因数的各数字之和。求 500以内具有上述特点的所有合数。

Page 146: 教师 (PASCAL 串讲 ) 培训讲习

解:①设 n 为所要求的合数,让 n 在 1~ 500 间循环做以下步骤;

②用 t1 , t2 分别累计合数 n及 n 的质因数的各位数字之和,初值均为 0 ;

③调用过程 SUB3进行非素数判定,以布尔变量 yes 的真假值判定是否, yes 的初值为 true ,如果为 (not true) 非素数,就做步骤④,⑤,⑥;否则取新的 n 值,重复步骤③;

④调用 SUB1 ,求 n 的各数字之和,传送给 t1 ; ⑤调用 SUB2 ,求 n 的各质因数,对于每个质因素都通过 SUB1 求它各位数字之和,将所有各质因数字传送给 t2 。

⑥如果 t1=t2 (各位数字之和等于它所有质因数的各数字之和),则输出此 n 。

Page 147: 教师 (PASCAL 串讲 ) 培训讲习

Pascal 程序:

program T12_2;var n,t1,t2,tatol: integer;    yes: boolean;procedure sub1(x:integer; var 

t:integer);           { 过程 : 分离 x 的各位数字 }begin                                          

     { 并求各位数字之和 }repeat    t:=t+x mod 10;    x:=x div 10;  until x=0end;

procedure sub2(x: integer; var t: integer);procedure sub2(x: integer; var t: integer);       {       { 过程:分解质因数 过程:分解质因数 }}var xx,tt:integer;var xx,tt:integer;beginbegin    xx:=2;xx:=2;    while x>1 dowhile x>1 do    if x mod xx=0 then if x mod xx=0 then beginbegin                tt:=0;tt:=0;                sub1(xx,tt);sub1(xx,tt);                t:=t+tt;t:=t+tt;                x:=x div xx;x:=x div xx;            endend        else inc(xx)else inc(xx)end;end;

Page 148: 教师 (PASCAL 串讲 ) 培训讲习

procedure sub3(x: integer;var yy: boolean);      {procedure sub3(x: integer;var yy: boolean);      { 过程:判断过程:判断 xx 是否为素数 是否为素数 }}var k,m: integer;var k,m: integer;beginbegin    k:=trunc(sqrt(x));k:=trunc(sqrt(x));    for m:=2 to k dofor m:=2 to k do        if x mod m=0 then yy:=false;if x mod m=0 then yy:=false;end;end;begin                               {begin                               { 主程序主程序 }}      for n:=1 to 500 dofor n:=1 to 500 do          beginbegin              t1:=0;t2:=0;t1:=0;t2:=0;              yes:=true;yes:=true;              sub3(n,yes);             {sub3(n,yes);             { 调用过程求素数 调用过程求素数 }}              if not yes then         {if not yes then         { 如果非素数就… 如果非素数就… }}                  beginbegin                      sub1(n,t1);           {sub1(n,t1);           { 调用过程求调用过程求 nn 的各位数字之和 的各位数字之和 }}                      sub2(n,t2);          {sub2(n,t2);          { 调用过程求调用过程求 nn 的各质因数的数字之和 的各质因数的数字之和 }}                      if t1=t2 then write(n:6);                   {if t1=t2 then write(n:6);                   { 打印合格的合数 打印合格的合数 }                                }                                                  endend          end;end;      readlnreadlnend.end.

Page 149: 教师 (PASCAL 串讲 ) 培训讲习

例: T12_3 汉诺塔游戏 约在十九世纪末,欧洲出现了一

种称为汉诺塔( Tower of Hanoi )的游戏。据说这种游戏最早来源于布拉玛神庙( Temple of Bramach )里的教士。游戏的装置是一块铜板,上面有三根金刚石的针,针上放着从大到小的 64 个盘子。游戏的目标是把所有的盘子从一根针上移到另一根针上,还有一个针作为中间过渡。游戏规定每次只能移动一个盘子,并且大盘子不能压在小盘子上面。由于需要移动的次数太多,该游戏的结束将标志着世界末日的到来。

通过计算,对于 64 个盘子至少需要移动 264-1=1.8×1019次。若每秒钟移动一次,需一万亿年,而太阳原子燃料大约只能维持 150亿年。若用现代电子计算机,一微秒移动一次,也需要一百万年。

Page 150: 教师 (PASCAL 串讲 ) 培训讲习

下面以三个盘子为例。要从源 1移动到目标 3 ,需要借助中间 2来过渡。一个可行的移动方案是:

1→3 (表示将第 1根针上的一个盘子移动到第 3根针上,下面各行以此类推)

1→23→21→32→12→31→3此时共移动 7次,完成了三个盘子从源 1

到目标 3 的移动。考虑一般情形,为了将 n 个盘子从 a经

过 b移动到 c 。可以先将 n-1 个盘子从 a经过 c移动到 b ,然后将 a 中剩下的一个盘子移动到 c ,最后再将 n-1 个盘子从 b经过 a移动到 c 。这样我们就将原来与 n 有关的问题变成了与 n-1 有关的问题。重复这个过程,每次 n减 1 。最后当 n=1时,直接移动该盘子就可以了。

Page 151: 教师 (PASCAL 串讲 ) 培训讲习

定义过程 move 。为了将 n 个盘子从 a经过 b移动到 c ,可调用过程如下:

move(n,a,b,c) 根据上面的讨论,可以

分解成下面的 3 个步骤: move(n-1,a,c,b) a→c move(n-1,b,a,c)

PROGRAM T12_3; 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{else} END;{move} BEGIN read(total); move(total,1,2,3); END.

Page 152: 教师 (PASCAL 串讲 ) 培训讲习

例 T12_4: 数字三角形[问题描述]如下所示为一个

数字三角形: 7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

请编一个程序计算从顶至底的某处的一条路径,使该路径所经过的数字的总和最大。

每一步可沿直线向下或右斜线向下走;

1<三角形行数≤ 100 ; 三角形中的数字为整数

0 , 1 , 2 , …, 99

[问题分析]假设从顶至数字三角形的某一位置的所有路径中,所经过的数字总和最大的那条路径我们称之为该位置的最大路径。由于题目规定每一步只能沿直线或右斜线向下走,若要走到某一位置,则其前一位置必为其左上方或正上方两个位置之一。由此可知,当前位置的最优路径必定与其左上方或正上方两个位置的最优路径有关,且来自其中更优的一个。 我们可以用一个两维数组 a 记录数字三角形中的数, a[I,j] 表示数字三角形中第 i 行第 j 列的数,再用一个两维数组 max 记录每个位置的最优路径的数字总和。计算 max 数组可以像计算杨辉三角形一样用逐行递推的方法实现,具体看程序清单:

Page 153: 教师 (PASCAL 串讲 ) 培训讲习

Program T12_4;Const maxline=100;Var i,j,t,line:integer; a,max:array[1..maxline,1..maxline] of

integer;Begin randomize; write(‘input number of line(<100)’); readln(line); for i:=1 to line do begin for j:=1 to i do begin a[i,j]:=trunc(random(99)); write (a[i,j]:4); end; writeln; end; writeln;

Max[1,1]:=a[1,1];For i:=2 to line doBegin max[i,1]:=max[i-1,1]+a[I,1]; for j:=2 to i-1 do if j:=2 to ido begin if max[i-1,j]>=max[i-1,j-1] then max[i,j]:=a[i,j]+max[i-1,j] else max[i,j]:=a[i,j]+max[i-1,j-1]; max[I,i]:=max[i-1,i-1]+a[i,i] end;End;

t:=0;For i:=1 to line do if t<max[line,i] then t:=max[line,i]; writeln(‘the maximum sum is:’,t); readln;End.

Page 154: 教师 (PASCAL 串讲 ) 培训讲习

解法二:递归求解Program T12_4;Const maxline=100;Var i,j,t,line:integer; a:array[1..maxline,1..maxline] of

integer;

Function maxsum(i,j:integer):integer;

Begin if i=line then maxsum:=a[i,j] else if maxsum(i+1,j)>max(i+1,j+1) then maxsum:=maxsum(i+1,j)+a[i,j] else maxsum:=maxsum(i+1,j+1)+a[i,

j]End;

Begin randomize; write(‘input number of line(<100)’); readln(line); for i:=1 to line do begin for j:=1 to i do begin a[i,j]:=trunc(random(99)); write (a[i,j]:4); end; writeln; end; writeln;Writeln(‘maxsum=‘,maxsum(1,1));Readln;End.