一部开头为几个神仙在人与电脑下象棋棋,然后因为一只炮讨论到下界的事情

拒绝访问 | www.eeff.net | 百度云加速
请打开cookies.
此网站 (www.eeff.net) 的管理员禁止了您的访问。原因是您的访问包含了非浏览器特征(3c9a-ua98).
重新安装浏览器,或使用别的浏览器当前位置: >>
Pascal教程(整理版)
第一章 简单程序........................................................................................................................... 2 第一节 Pascal 程序结构和基本语句................................................................................... 2 第二节 顺序结构程序与基本数据类型 ............................................................................... 6 第二章 分支程序......................................................................................................................... 10 第一节 条件语句与复合语句 ............................................................................................. 10 第二节 情况语句与算术标准函数 ..................................................................................... 12 第三章 循环程序......................................................................................................................... 16 第一节 for 循环 .................................................................................................................. 16 第二节 repeat 循环 ............................................................................................................. 22 第三节 While 循环 ............................................................................................................. 27 第四章 函数与过程..................................................................................................................... 32 第一节 函数......................................................................................................................... 32 第二节 自定义过程............................................................................................................. 35 第五章 Pascal 的自定义数据类型 ............................................................................................ 39 第一节 数组与子界类型 ..................................................................................................... 39 第二节 二维数组与枚举类型 ............................................................................................. 47 第三节 集合类型................................................................................................................. 55 第四节 记录类型和文件类型 ............................................................................................. 59 第五节 指针类型与动态数据结构 ..................................................................................... 66 第六章 程序设计与基本算法 ....................................................................................................... 72 第一节 递推与递归算法 ..................................................................................................... 72 第二节 回溯算法................................................................................................................. 79 第七章 数据结构及其应用 ......................................................................................................... 85 第一节 线性表..................................................................................................................... 85 第二节 队列......................................................................................................................... 89 第三节 栈............................................................................................................................. 92 第四节 数组......................................................................................................................... 96 第八章 搜索................................................................................................................................... 99 第一节 深度优先搜索 ......................................................................................................... 99 第二节 广度优先搜索 ....................................................................................................... 110 第九章 其他常用知识和算法 ..................................................................................................... 114 第一节 图论及其基本算法 ............................................................................................... 114 第二节 动态规划............................................................................................................... 1211 第一章简单程序无论做任何事情,都要有一定的方式方法与处理步骤。计算机程序设计比日常生活中的 事务处理更具有严谨性、规范性、可行性。为了使计算机有效地解决某些问题,须将处理步 骤编排好,用计算机语言组成“序列” ,让计算机自动识别并执行这个用计算机语言组成的 “序列” ,完成预定的任务。将处理问题的步骤编排好,用计算机语言组成序列,也就是常 说的编写程序。在 Pascal 语言中,执行每条语句都是由计算机完成相应的操作。编写 Pascal 程序,是利用 Pascal 语句的功能来实现和达到预定的处理要求。 “千里之行,始于足下” , 我们从简单程序学起,逐步了解和掌握怎样编写程序。第一节Pascal 程序结构和基本语句在未系统学习 Pascal 语言之前,暂且绕过那些繁琐的语法规则细节,通过下面的简单例 题,可以速成掌握 Pascal 程序的基本组成和基本语句的用法,让初学者直接模仿学习编简 单程序。[例 1.1]编程在屏幕上显示“Hello World!” 。 Pascal 程序: Program ex11; Begin Writeln(‘Hello World!’); ReadLn; End. 这个简单样例程序,希望大家的程序设计学习能有一个良好的开端。程序中的 Writeln 是一个输出语句,它能命令计算机在屏幕上输出相应的内容,而紧跟 Writeln 语句后是一对 圆括号,其中用单引号引起的部分将被原原本本地显示出来。 [例 1.2]已知一辆自行车的售价是 300 元,请编程计算 a 辆自行车的总价是多少? 解:若总售价用 m 来表示,则这个问题可分为以下几步处理: ①从键盘输入自行车的数目 a; ②用公式 m=300*a 计算总售价; ③输出计算结果。 Pascal 程序: Program Ex12; {程序首部} Var a,m : {说明部分} Begin {语句部分} Write(‘a=’); ReadLn(a); {输入自行车数目} M := 300*a; {计算总售价}2 Writeln(‘M=’,m); ReadLn; End.{输出总售价} {等待输入回车键}此题程序结构完整,从中可看出一个 Pascal 程序由三部分组成: (1)程序首部 由保留字 Program 开头,后面跟一个程序名(如:Exl1);其格式为: Program 程序名; 程序名由用户自己取,它的第一个字符必须是英文字母,其后的字符只能是字母或数 字和下划线组成,程序名中不能出现运算符、标点符和空格。 (2)说明部分 程序中所用的常量、变量,或类型、及过程与自定义函数,需在使用之前预先说明, 定义数据的属性(类型) 。[例 1.2] 程序中 Var S,R,C: Real; 是变量说明,此处说明 S, R,C 三个变量均为实数类型变量。只有被说明为某一类型的变量,在程序中才能将与该变 量同类型的数值赋给该变量。变量说明的格式为: Var 变量表:类型; (3)语句部分 指由保留字 Begin (开始)至 End. (结尾)之间的语句系列,是解决问题的具体处理步 骤,也是程序的执行部分。 Pascal 程序不管是哪部分,每句末尾都必须有分号(;),但允许最接近 End 的那个语句 末尾的分号省略;程序结束的 End 末尾必须有圆点(. ),是整个程序的结束标志。 程序中花括号“{ }”之间的部分为注释部分。 Pascal 程序结构可归纳用如下的示意图来表示: Program 程序名; 程序首部 标号说明; (Label) 常量说明; (Const) 说明部分 类型说明; (Type) 变量说明; (Var) 过程或函数说明; Begin 程序体 (主程序) 语句系列; 语句部分 End. 图 1.1 Pascal 程序的结构 把处理问题的步骤编成能从上到下顺序执行的程序,是简单程序的基本特征。再来分析 下面两道例题的 Pascal 程序结构和继续学习基本语句。 [例 1.3]编程计算半径为 R 的圆的面积和周长。 解:这是一个简单问题,按数学方法可分以下几步进行处理: ① 从键盘输入半径的值 R; { 要求告诉圆的半径 R } ② 用公式 S=π R2 计算圆面积; ③ 用公式 C=2π R 计算圆周长;3 ④ 输出计算结果。 Pascal 程序: Program Ex13; {程序首部 } Var R,S,C: Real; {说明部分 } Begin {语句部分 } Write ('R=?'); Readln(R); {输入半径 } S:=Pi*R*R; {圆面积公式 S=π R2} C:=2*Pi*R; {圆周长公式 C=2π R} Writeln('S=',S); {输出结果 } Writeln('C=',C); Readln {等待输入回车键} End. 程序中 Pi 是 Pascal 提供的标准函数,它返回圆周率的近似值:3.1415926…。 (:=)是赋值符号,赋值语句的格式为: 变量:=表达式; 赋值语句的作用是将:=右边表达式的值记录到左边的变量中。 Writeln 是输出语句,输出语句有三种格式: ① Write (输出项 1,输出项 2) ; {执行输出后光标不换行} ② Writeln (输出项 1,输出项 2) ; {执行输出后光标换到下一行} ③ Writeln {仅输出空白且光标换到下一行} Writeln 语句后面的圆括号以内部分均为输出项,可以是多项,各项间用逗号分隔; 对 单引号里的内容按照引号内的原样(字符)输出显示。如果输出项是表达式,则只输出表达式 的值,而不是表达式本身。 [例 1.4] 输出两个自然数相除的商和余数。 解:设被除数、除数、商和余数,分别为 A,B,C,D,均为变量,且都是整数类型。题 中未给出具体的自然数 A、B,可采用键盘输入方式。 ① 给出提示,从键盘输入 a, b; ② 显示两数相除的数学形式; ③ 求出 a 除以 b 的商 c; ④ 求出 a 除以 b 的余数 d; ⑤ 紧接等式后面输出显示商和余数。 Pascal 程序: Program Ex14; Var a,b,c,d : integer; Begin Write('INPUT A,B:'); {给出提示信息} Readln(a,b); {输入 a,b} Writeln; {输出一空行} Write(a,'/',b,'='); {输出等式之后不换行} c:=a div b; {整除运算,取商的整数部分}4 d:=a mod b; {相除求余运算,取商的余数部分} Writeln(C,'?',d); {输出后自动换行 } Readln {等待输入回车键 } End. 执行本程序中第一个 Write 语句,输出其引号以内的一串提示信息,是给紧接着的输入 语句提供明确的提示(要求),有“一目了然,人机对话”之效果。 Readln 是一个特殊的输入语句,要求输入一个回车(换行)才能往下执行。 Readln 是输入语句,它的一般格式为: ① Read (变量 1,变量 2); ② Readln (变量 1,变量 2); ③ Readln 前两种格式均要从键盘给变量输入数据,输入时,所键入的数据之间以空格为分隔,以 回车为输入结束。若多输入了数据(即数据个数超过变量个数),Read 语句读完数据之后,能 让后续的读语句接着读取多下来的数据;而 Readln 语句对本行多输入的数据不能让后续语 句接着读取多下来的数据。 为了防止多输入的数据影响下一个输入语句读取数据, 建议尽量 使用 Readln 语句输入数据。第三种格式不需输入数据,只需按入一个回车键。 [例 1.5]自然数的立方可以表示为两个整数的平方之差, 比如 43=102-62, 请输出自然数
的这种表示形式。(这里的 4 用自乘三次的形式 4*4*4 表示;10 也用自乘二次的形式 10*10 表示) 解:此题没有现成的计算公式能直接利用, 但可以自行推出处理方法或构建适当的运算公 式,按着构想的处理方案编排出各步骤。 设这个自然数为 N,两个平方数分别为 X,Y, 将问题表示为求 N3=X2―Y2 ① 先找出 X 的值,仔细观察题中的示例,用数学方法归纳可得出 X=N*(N+1)/2; (构成 本题可用的计算公式) ② 再仔细观察,发现 Y 值比 X 小一个 N 值,即 Y=X―N; ③ 输出等式 N3=X2―Y2 或 N*N*N=X*X―Y*Y Pascal 程序: Program Ex15; Const N=1996; {常量说明 } Var X,Y: Longint; {变量说明,此题计算中的数值较大,用长整型 } Begin X:=N*(N+1) div 2; { div 是整除运算 } Y:=X-N; Writeln(N,'*',N,'*', N,'=', X,'*', X,'―',Y,'*',Y); { 输出结果 } Readln End. 本程序中 N 是常量,X,Y 是变量,为长整数类型(Longint); 程序中的 div 是整除运 算,其结果只取商的整数部分; [例 1.6] 求一元二次方程 x2+3x+2=0 的两个实数根。 解:方程的系数是常量,分别用 a,b,c 表示,可运用数学上现成的求根公式求方程的根,5 采取如下方法: ① 先求出 d=b2-4ac; (求根公式中需用开方运算的那部分) ② 再用求根公式算出 x1,x2 的值。(x1,x2 = ? ) ③ 输出 x1,x2. Pascal 程序: program Ex16; Const a=1; {常量说明 } b=3; c=2; {a,b,c 表示方程系数} Var d : integer; {d 为整型变量} X1,X2: Real; {X1,X2 为实型变量} Begin d:=b*b-4*a*c; x1:=(-b+sqrt(d))/(2*a); {求方程的根} x2:=(-b-sqrt(d))/(2*a); Writeln('X1=',X1,'?':6,'X2=',X2);{输出结果} Readln {等待输入一个回车键} End. 本程序中的 a,b,c 均为常量;变量 d 是整数类型,而变量 x1,x2 则是实数类型,因 为运算式中的 Sqrt(d)开平方运算和(/)除法运算使结果为实数。Sqrt( ) 是开平方函数,是 Pascal 系统的一个标准函数。 习题 1.1 模仿例题编程 1. 加法计算器:编程由键盘输入两个整数 a 和 b,计算出它们的和并输出到屏幕上。 2. 某梯形的上底、下底和高分别为 8,12,9,求该梯形的面积。 ( 梯形面积公式为 S= ) 3. 求右图所示边长为 5.6 的正立方体表面积。 4. 已知图园柱体的高为 12,底面园的半径为 7,求园柱体表面积。 5. 计算某次考试语文、数学、英语和计算机等四科的总成绩与平均成绩。 (请用输入语句从键盘输入各科成绩分)第二节顺序结构程序与基本数据类型前面的简单程序已体现出处理问题步骤、思路的顺序关系,这就是顺序结构程序。 [例 1.7]交换两个变量的值:由键盘输入两个正整数 A 和 B,编程交换这两个变量的 值。 解:交换两个变量的值,可以想象成交换两盒录音带(称为 A 和 B)的内容,可以按以 下步骤处理: 步骤①:拿一盒空白录音带 C 为过渡,先将 A 翻录至 C;6 步骤②:再将 B 翻录至 A; 步骤③:最后将 C 翻录至 B。 这样操作,可达到题目要求。 Pascal 程序: Program Exam17; Var a,b,c : Begin Write(‘A,B=’); Readln(a,b); C:= A; {等价于步骤 1} A := B; {等价于步骤 2} B := C; {等价于步骤 3} Writeln(A,B); End. [例 1.8] 分钱游戏。甲、乙、丙三人共有 24 元钱,先由甲分钱给乙、丙两人,所分给的 数与各人已有数相同;接着由乙分给甲、丙,分法同前;再由丙分钱给甲、乙,分法亦同前。 经上述三次分钱之后,每个人的钱数恰好一样多。 求原先各人的钱数分别是多少? 解:设甲、乙、丙三人的钱数分别为 A,B,C。用倒推(逆序)算法, 从最后结果入手, 按反相顺序, 分步骤推算出每次各人当时的钱数: 在每个步骤中, ( 各人钱数分别存在 A、 B、 C 中) 步骤①: A=8 B=8 C=8 {这是最后结果的钱数,三人都一样多 } 步骤②: A=A/2 (=4) B=B/2 (=4) C=A+B+C(=16) { A,B 未得到丙分给的钱时, 只有结果数的一半;C 应包含给 A,B 及本身数三者之和 } 步骤③: A=A/2 (=2) C=C/2 (=8) B=A+B+C(=14) {A,C 未得到乙分给的钱时, 只有巳有数的一半;B 应包含给 A,C 及本身数三者之和 } 步骤④: B=B/2 (=7) C=C/2 (=4) A=A+B+C(=13) C 未得到甲分给的钱时,只有巳有数的一半;A 应包含给 B,C 及本身数三者之和 } 步骤⑤: 输出 A(=13)B(=7)C(=4){此时的 A,B,C 就是三人原先的钱数 } Pascal 程序: Program Exam18; Var a,b,c: integer; Begin a:=8; b:=8; c:=8; {对应于步骤①} a:=a div 2; b:=b div 2; c:=a+b+c; {对应于步骤②} a:=a div 2; c:=c div 2; b:=a+b+c; {对应于步骤③} b:=b div 2; c:=c div 2; a:=a+b+c; {对应于步骤④} Writeln('a=',a,' ': 4,'b=',b,' ': 4,'c=',c) ; {输出} Readln End. 细心观察,会发现本程序语句的顺序很关键。此例用反推顺序(逆序),按步骤正确推算 出各变量的值。当然,有的问题可按正序步骤编程,这类程序都称为顺序程序。 本程序 Writeln 语句的输出项含有( ' ' : 4 ), 这里的冒号用来指定该项显示所占宽度,7 此处是输出 4 个空格即(空格项占 4 格)。 [例 1.9] 有鸡兔同笼,头 30,脚 90,究竟笼中的鸡和兔各有多少只? 解:设鸡为 J 只,兔为 T 只,头为 H,脚为 F,则: J+T=30 ① 2*J+4*T=90 ② 解此题暂不必采用数学上直接解方程的办法,可采用“假设条件与逻辑推理”的办法: 假设笼中 30 个头全都是兔, 那么都按每头4只脚计算, 总脚数为(4*H), 与实际脚数 ( F ) 之差为(4*H―F),如果这个差=0,则笼中全是兔(即鸡为 0 只) ;如果这个差值 &0,说明 多计算了脚数,凡是鸡都多给算了两只脚,用它除以 2 就能得到鸡的只数,处理步骤为: ① J=(4*H―F)/2 {先用脚数差值除以 2 算出鸡的只数} ② T=H―J {再用总头数减鸡数算出免的只数} 按此方法,这两步运算必须注意先后顺序才会符合运算逻辑。 Pascal 程序: Program Exam16; Const H=30; {常量说明 } F=90; Var J,T: byte; {为字节类型的整数 } Begin J:=(4*H-F) div 2; {整除运算 } T:=H-J Writeln ('J=',J,' ': 6,'T= ',T ) ; Readln End. 本程序中 H,F 为常量,变量 J,T 为 byte 类型,属于整数类型。 Pascal 定义了五个标准整数类型,如下表所示: 类型 Shortint(短整型) Integer (整型) Longint(长整型) Byte Word (字节型) (字型) 取值范围 -128..127 -3 -.. 0..255 0..65535 占字节数 1 2 4 1 2 格式 带符号 8 位 带符号 16 位 带符号 32 位 无符号 8 位 无符号 16 位在前面程序中常用的数据类型除整数类型,还有实数类型。Pascal 还定义了五个标准实 数类型,列表所示如下: 类型 Real Single Double Extended Comp 取值范围 2.9×10 ~1.7×10 1.5×10 ~3.4×10 5.0×10 1.9×10-324 -45 -39 38 38占字节数 6 4 8 10 8有效数字 7~8 位 11~12 位 15~16 位 19~20 位 19~20 位~1.7×1038308-4951 63~1.1×104932-2 +1~2 -1在 Turbo Pascal 中实数的表示用科学记数法,可认为由三部分组成:8 ① 省略。 例如: 1.7E+38 可写成 1.7E38 (等同于 1. 7×1038 )。 在实数类型定义下,即使是整数,在程序执行时系统也将自动转换成科学记数形式,试 请运行下面程序并注意观察运行结果: Program Exam17; Var x: real; {x 为实数类型 } Begin X:=180; {把整数 180 赋给实数类型变量 X} Writeln ('x=',x) ; {输出的 x 自动表示成实数形式 } Readln End. 习题 1. 2 1.已知△ABC 中的三边长分别为 25.76,74.03,59.31,求△ABC 的面积。 ( 计算公式: S= 。 其中 P = ) 2.某车棚存有自行车和三轮车共 65 辆,它们的轮子数合计为 150 个。求该棚内存有的自 行车和三轮车各是多少辆? 3.甲、乙、丙三人分别有磁带 36,48,64 盒。先由甲把自己的磁带平均分为三份,分给 乙、丙各一份,自己留下一份;接着是乙,最后是丙,都按甲的方法处理。编程输出甲、乙、 丙在上述过程中各人的磁带数分别是多少? (输出所有的中间结果) 4.五位好朋友相聚。第一位朋友带来了很多糖块赠送给各位朋友,使每人的糖块在各自 原有的基础上翻了一倍; 接着第二位好友也同样向每人赠送糖块, 他同样使每人的糖块在各 人已有的数量上翻了一倍;第三、第四、第五位好友都照此办理。经过这样的赠送之后,每 人的糖块恰好都为 32 块。问各位好友原先的糖块数分别是多少?# . ## E +## 或 # . ## E -## #.##表示有效数字; ② E 表示以 10 为底的幂; ③ +##或-##是指数部分,+号可9 第二章分支程序在程序设计中,许多问题是在一定条件下才选择某种处理方式的,这就需要用条件判断 语句或情况选择语句进行处理。程序执行中将出现选择(分支),根据条件只选择执行部分语 句,不一定都是按原顺序从头到尾地执行所有语句,这样的程序称为分支程序。第一节条件语句与复合语句[例 2.1] 某服装公司为了推销产品,采取这样的批发销售方案:凡订购超过 100 套的,每 套定价为 50 元,否则每套价格为 80 元。编程由键盘输入订购套数,输出应付款的金额数。 解:设 X 为订购套数,Y 为付款金额,则:① 输入 X; ② 判断 X 值; ③ 根据判断结果选择符合条件的那种方法计算 Y 值; ④ 输出计算结果。 Pascal 程序: Program Exam21; Var x,y: integer; Begin Write('X=') ;Readln(x) ; { 输入 X} if x &100 then y:=50*X else y:=80*X; {条件判断与选择 } Writeln('y=',y) ; Readln End. 程序中的 if 语句常称为条件语句,它的一般格式为: (1) if 条件 then 语句; (2) if 条件 then 语句 1 else 语句 2; IF 语句的功能是按条件在两种可能中选择其中一种。习惯上把 if 后面的表达式称为条 件,then 后面的语句称为真项,else 后面的语句称为假项。若条件成立(为真)就执行真项, 然后执行 if 语句的后继语句;若条件不成立(为假)就跳过真项而执行假项,然后执行后继语 句。而第一种格式只有真项,没有假项,当条件不成立(为假)就什么也不需做,直接往下去 执行后继语句。 [例 2.2] 读入三个不同的数,编程按由小到大的顺序排列打印出来。10 解:设读入的三个数为 a,b,c,为了把较小的数排在前面,可作如下处理: ① 如果 a>b 就交换 a、b 的值,将较大的值换至后面; ② 如果 a>c 就交换 a、c 的值,将较大的值换至后面; ③ 如果 b>c 就交换 b、c 的值,将较大的值换至后面; ④ 输出处理后的 a,b,c。 Pascal 程序: Progranm Exam22; Var a,b,c,t: Real; Begin Write('Input a, b,c='); Readln(a,b,c); if a>b then begin {复合语句} t:=a; a:=b; b:=t {交换 a,b} end; if a>c then begin {复合语句} t:=a; a:=c; c:=t {交换 a,c} end; if b>c then begin {复合语句} t:=b; b:=c; c:=t {交换 b,c} end; Writeln('a,b,c:',a:6, b:6, c:6); Readln End. if 语句规定它的真项或假项位置上只能是一个基本语句,如果需要写一组语句,就应当 使用复合语句。本程序中有三处用到复合语句。每个复合语句的范围是从 Begin 开始到与它 相对应的 End 为止。复合语句的地位和一个基本语句相同;其一般格式为: Begin 语句系列 End; 习题 2. 1 1.假设邮局规定寄邮件时若每件重量在 1 公斤以内(含 1 公斤), 按每公斤 1.5 元计算邮费, 如果超过 1 公斤时,其超出部分每公斤加收 0.8 元。请编程序计算邮件收费。 2.输入三个正整数,若能用这三个数作为边长组成三角形,就计算并输出该三角形的面 积,否则输出 Can't。(组成三角形的条件为:任意两边之和大于第三边) 3.输入一个三位数的整数,将数字位置重新排列,组成一个尽可大的三位数。例如:输 入 213,重新排列可得到尽可能大的三位数是 321。11 第二节情况语句与算术标准函数如果有多种(两种或两种以上)选择,常用情况语句编程。 将前面[例 2.1]改成用如下方法来处理。根据题意,付款计算可分为两种情况: ① Y=50*X (X>100) ② Y=80*X (X<=100) 显然,情况①与②的选择取决于 X 值。假设用 N 表示“情况值” ,暂且先让 N=2; 如果 X>100 则 N=1; (此题中 N 的值只是 1 或 2,且取决于 X 值) Pascal 程序: Program Exam21_1; Var X,Y,N: integer; Begin Write('X=') ;readln(x) ; n:=2; { 先让 n=2 } if X>100 then n:=1; {如果 X>100 则 n=1 } Case n of { 关于情况处理 } 1: Y:=50*X; 2: Y:=80*X; end; Writeln('Y=',Y) ; Readln End. 程序中的 Case─end 语句为情况语句,是多路分支控制,一般格式为: Case 表达式 of 情况常量表 1: 语句 1; 情况常量表 2: 语句 2; : : 情况常量表 n: 语句 n end; 执行情况语句时,先计算 Case 后面表达式的值,然后根据该值在情况常量表中的“对 应安排” ,选择其对应的语句执行,执行完所选择语句后就结束 Case 语句;如果常量表中没 有一个与表达式值对应的语句,则什么也不做就结束本 Case 语句。 Case 语句的另一种应用格式为: Case 表达式 of 情况常量表 1: 语句 1; 情况常量表 2: 语句 2; : : 情况常量表 n: 语句 n; else 语句 n+1 end;12 这种格式的前面部分是相同的,所不同的是:如果常量表中没有一个与表达式值对应的 语句,则执行与 else 对应的语句,然后结束 Case 语句。 [例 2.2] 对某产品征收税金,在产值 1 万元以上征收税 5%;在 1 万元以下但在 5000 元 以上的征收税 3%;在 5000 元以下但在 1000 元以上征收税 2%;1000 元以下的免收税。 编程计算该产品的收税金额。 解:设 x 为产值,tax 为税金,用 P 表示情况常量各值,以题意中每 1000 元为情况分界: P=0: tax=0 (x&1000 ) P=1,2,3,4: tax=x*0.02 (1000&=x&5000 ) P=5,6,7,8,9: tax=x*0.03 (5000&X&=10000 ) P=10: tax=x*0.05 (x& 10000 ) 这里的 P 是 “情况” 用产值 x 除以 1000 的整数值作为 P, 值, 如果 P&10 也归入 P=10 的情况。Pascal 语言用 P=trunc(x/1000)取整计算, Pascal 程序: Program Exam22; Var x,p : integer; Tax : real; Begin Write('Number=') ; readln(x) ; P:=trunc(x/1000) ; if P>9 then P:=10; Case P of 0 : tax:=0; 1,2,3,4 : tax:=x*0.2; 5,6,7,8,9 : tax:=x*0.3; 10 : tax:=x*0.5 end; Writeln('tt=',tt:5:2) ; Readln End. 情况表达式的计算必须考虑到“全部”情况,不要有遗漏。如果情况常量表的“值”在 某范围内是连续的,可将常量表写成: n1.. n2:语句; 因此,上面程序中的情况常量表可以写成如下程序中表示形式: Program Exam22_1; Var x,p: integer; tax: real; Begin Write('Number=') ; readln(x) ; P:=trunc(x/1000) ; if P>9 then P:=10; Case P of 0 : tax:=0;13 1..4 : tax:=x*0.2; { 从 1 至 4 作为同一情况处理 } 5..9 : tax:=x*0.3; { 从 5 至 9 作为同一情况处理 } 10 : tax:=x*0.5 end; Writeln('tt=',tt:5:2) ; Readln End. 程序中的 trunc(x)为取整函数, Pascal 的算术标准函数之一。 是 Pascal 常用的算术标准函 数有 19 个: (1) abs(x) 求 x 的绝对值(|x|); (2) exp(x) 求 ex 的值; (e 为无理数 2.71828?) (3) frac(x)求 x 的小数部分; (4) int(x) 求 x 的整数部分(不舍入,函数值为实型); (5) ln(x) 求以 e 为底的 x 的对数(log ex ); (6) odd(x) 判断 x 的奇偶数(当 x 为奇数时 odd(x)值为 true,否则为 false); (7) ord(x) 求 x 的序号,结果为整型(x 为有序类型量); (8) pi π 值(3.7932?); (9) pred (x) 求 x(有序类型)的前趋值; (10) succ(x) 求 x(有序类型)的后继值; (11) random 随机函数,产生 0~1 的随机值; (12) random(n)产生 0~n 的随机数(n 为 word 类型,先执行 randomize, 才能得到随 机整数); (13) round(x) 求 x 的四舍五入整数; (14) trunc(x) 求 x 的整数部分(截掉小数部分,结果为整型); (15) sqr(x) 求 x 的平方值(x2 ); (16) sqrt(x) 求 x 的开平方根值( ); (17) sin(x) 求 x 的正弦函数(x 为弧度); (18) cox(x) 求 x 的余弦函数(x 为弧度); (19) arctan(x) 正切的反三角函数(x 为数值); 习题 2.2 1.运输公司计算运费时,距离(S)越长,每公里运费越低,标准如下: 如果 S<250 公里;运费为标准运价的 100% 如果 250 公里<=S<500 公里,运费为标准运价的 98%; 如果 500 公里<=S<1000 公里,运费为标准运价的 95%; 如果 1000 公里<=S<2000 公里,运费为标准运价的 92%; 如果 2000 公里<=S<3000 公里,运费为标准运价的 90%; 如果 S=>3000 公里,运费为标准运价的 85%; 。请编计算运费的程序。 2. 输入考试成绩,如果获 85 分以上为 A 等,获 60 分~84 分为 B 等,60 分以下为 C 等,编程输出考试等级。 3. 某车间按工人加工零件的数量发放奖金, 奖金分为五个等级: 每月加工零件数 N & 100 者奖金为 10 元; & = N & 110 者奖金为 30 元; & = N &120 者奖金为 50 元; & = N 100 110 12014 &130 者奖金为 70 元;N & 130 者为 80 元。 请编程,由键盘输入加工零件数量,显示应发奖金数。15 第三章循环程序在编程中经常遇到需要多次规律相同的重复处理,这就是循环问题。Turbo Pascal 采用 不同的循环方式来实现,常用的环循有三种: for、repeat、while.第一节for 循环for 循环是一种自动计数型循环。 [例 3.1] 试打印出 1~20 的自然数。 解:① 用 a 代表 1~20 各数,同时也用 a 兼作计数,以控制循环次数; ② 让 a 从 1 开始; ③ 输出 a; ④ a 自动计数(加 1) ,如果未超越所规定的循环范围则重复步骤③,否则结束循 环。 Pascal 程序: Program Exam12; Var a: byte; Begin for a:=1 to 20 do Writeln (a); Readln End. 程序中 for a:=1 to 20 do Writeln (a); 是 for 循环语句。 for 循环语句有两种格式: (1) for 循环变量:=初值 To 终值 do 语句; (2) for 循环变量:=初值 downto 终值 do 语句; 第(1)种格式的初值小于等于终值,循环变量值按自动加 1 递增变化; 第(2)种格式的初值大于或等于终值,循环变量值按自动减 1 递减变化。for 循环是 (以 递增 1 或以递减 1) 计数型循环。 比如: 若将[例 3.1]程序改为倒计数(递减)循环,则输出 20~1 的自然数数: Program Exam31; Var a: byte; Begin for a:=20 downto 1 do Writeln(a) ; Readln End. [例 3.2]打印出 30 至 60 的偶数。] 解: 方法一:16 ①设 a 表示 30 至 60 的所有的数,可用 for 循环列出; ②用式子 a mod 2=0 筛选出其中的偶数并输出。 Pascal 程序: Program ex32; Var a : Begin For a := 30 to 60 do If (a mod 2=0) then writeln(a); R End. 在这个程序中,for 循环后的循环语句是一个条件分支语句。 方法二:我们知道,在式子 a=2*n 中,若 n 取自然数 1、2、3、…,时,则 a 依次得到 偶数 2、4、6、…。因此要想得到 30 至 60 的偶数,就可以让上面式子中的 n 取 15 至 30 的 自然数就可以了。所以本题还可以按以下步骤处理: ①设 n 表示 15 至 30 的所有自然数,可用 for 循环列出; ②用式子 a := 2*n 求出其中的偶数; ③将结果输出至屏幕。 Pascal 程序: Program ex32; Begin For n := 15 to 30 do Begin a := 2*n; Writeln(a); E R End. [例 3.3]自然数求和:编一个程序,求从 1 至 100 的自然数的和。 解:① 令 S=0; ② 令 a 表示 1 至 100 的自然数,用循环列出; ③ 将这些自然数用公式 S:=S+a 逐一累加到 S 中去; ④ 循环结束后,S 即为 1 至 100 的自然数的和,输出即可。 Pascal 程序: Program ex33; var s,a : Begin S := 0; For a := 1 to 100 do S := S+a; Writeln(‘S=’,S);17 R End. [例 3.4]一个两位数 x,将它的个位数字与十位数字对调后得到一个新数 y,此时 y 恰好 比 x 大 36,请编程求出所有这样的两位数。 解:① 用 for 循环列举出所有的两位数,x 为循环变量; ② 用公式 a:= x div 10 分离出 x 的十位数字; ③ 用公式 b:= x mod 10 分离出 x 的个位数字; ④ 用公式 y:= b*10+a 合成新数 y; ⑤ 用式子 y-x=36 筛选出符合条件的数 x 并输出。 Pascal 程序: Program ex34; Begin For x := 10 to 99 do Begin a := x div 10; b := x mod 10; y := b*10+a; if y-x=36 then writeln(x); E R End. [例 3.5] 把整数 3025 从中剪开分为 30 和 25 两个数,此时再将这两数之和平方, (30+25)2=3025 计算结果又等于原数。求所有符合这样条件的四位数。 解:设符合条件的四位数为 N,它应当是一个完全平方数,用(a*a)表示。 ① 为了确保 N=(a*a)在四位数()范围内,可确定 a 在 32~99 循环; ② 计算 N=a*a;将四位数 N 拆分为两个数 n1 和 n2; ③ 若满足条件(n1+n2)*(n1+n2)=N 就输出 N 。 Pascal 程序: Program Exam35; Var N,a, x,n1,n2: Integer; Begin for a:=32 to 99 do begin N:=a*a; n1:= N div 100; {拆取四位数的前两位数} n2:= N-n1*100; {拆取四位数的后两位数} X:=n1+n2; if x*x=N then writeln (N); end; Readln18 End. [例 3.6]用“*”号打印出如下的长方形图案。 ********* ********* ********* ********* 解:① 上面给出的图例共有 4 行,我们可以用一个循环控制行的变化; ② 在每行中又有 9 列,我们可以在前面控制行的循环中再套一个循环来控制列的 变化。 Pascal 程序: Program ex36; Begin For a := 1 to 4 do {外循环控制行的变化} Begin For b := 1 to 9 do {内循环控制列的变化} write(‘*’); W {输出一行的“*”后换行} E R End. 程序中的循环对于 a 的每个值都包含着一个 b=(1~9)次的内循环。外循环 for a 将内循 环 for b 包含在里面,称为 for 循环的嵌套。嵌套形式如: for a:=n1 to n2 do for b:=m1 to m2 do 循环体语句; [例 3.7] 打印出九九乘法表: 解:设 a 为被乘数,范围为 1~9;b 为乘数,范围为 1~a;乘式为 a*b=(a,b 的乘积),则 a=1: b=1~a 1*1=1 a=2: b=1~a 2*1=2 2*2=4 a=3: b=1~a 3*1=3 3*2=6 3*3=9 a=4: b=1~a 4*1=4 4*2=8 4*3=13 4*4=16 : : a=9 b=1~a 9*1=9 9*2=18 ? 9*9=81 ⑴从上面分解的横行中看到共有 9 行,这里的“行”数变化与 a 的变化从 1~9 相同, 可用 a 控制“行”的循环; ⑵每“行”里面相乘的次数与 b 的范围相关,由 b 控制每“行”里面的“内部”循环; ⑶内循环被包含在最里层,执行完每“行”的内部循环,就到下一“行”去执行新“行” 里面的循环,每“行”都拥有形式相同的( b=1~a )内循环。 即每到一“行”都要执行该“行”的内循环。这里所指的“行”可以理解成抽象的行, 不一定是实际上具体对应的行,可以是一个处理“块” 。 Pascal 程序:19 Program Exam37; Var a,b: byte; Begin for a:=1 to 9 do {外循环 } begin for b:=1 to a do {内循环 } write(a, ’ ’= ’ ’* ,b, ,a*b, ’:3); ’ writeln end; Readln End. 根据这种格式还可以实现多层循环嵌套,例如: for a:=n1 to n2 do for b:=m1 to m2 do for c:=k1 to k2 do 循环体语句; [例 3.8]从七张扑克牌中任取三张,有几种组合方法?请编程输出所有组合形式。 解:设每次取出三张分别为 a,b,c。用三重循环分别从 1~7 的范围里取值;为了排除取 到重号,用(a-b)*(b-c)*(a-c) & &0 进行判断。 Pascal 程序: program Exam38; const n=7; var a,b,c,t: Begin t:=0; for a:=1 to n do for b:=1 to n do for c:=1 to n do if (a-b) * (b-c) * (a-c) & &0 then Begin inc (t); writeln (a:3, b:3, c:3) E writeln ( total:, t :5); readln End. [例 3.9] 数学上把除了 1 和它本身, 没有别的数能够整除它的自然数叫做素数(或质数)。 现在由键盘输入一个自然数 N,编程判断 N 是否是素数,是则输出“Yes” ,否则输出“No” 。 解:根据定义,对于给定的自然数 N,只需判断除 1 和它本身外,还有没有第三个自然 数即可。 ① 令 K 从 1 循环至 N;20 ② 根据 N mod K 是否为 0 可统计 K 的约数的个数; ③ 若 N 的约数的个数超过 2 个,则判定 N 不是素数。 Pascal 程序: Program Exam39; Var n,m,k,t: integer; Begin write(‘N=’); ReadLn(N); t:=0; for k:=1 to N do {外循环 } if N mod k=0 then t := t+1; {如果 N 是奇数 } if t&2 then writeln(‘No’) else writeln(‘Yes’); R End. 程序中的变量 yse 为布尔(或逻辑)类型(Boolean)。布尔值只有两个: True(真) False(假) 布尔值与条件判断结果为真(条件成立)或为假(条件不成立)的作用相同,常用于条件语 句和循环语句中。 上面程序中用 if yes and (t mod 7=0) then writeln;实现每行打印七个素数换行,程序中 布尔变量 yes 为真,在逻辑上表示是素数;关系式(t mod 7=0) 的值为真时,表示该行输出 素数巳是7个;用 and 将这两个“条件”连起来是作一种布尔(逻辑)运算。 Pascal 共有四种逻辑运算符: ① and (与) 两条件都为 True 时,其结果值为 True;否则为 False; ② or (或) 两条件中只要有一个为 True ;其结果值为 True;否则为 False; ③ xor (异或) 两条件的逻辑值不相同时,其结果值为 True;否则为 False; ④ not (非) 条件为 True 时,其结果值为 False;否则为 True;(取反)习题 3.1: 1.打印出 1 至 20 的平方数表。 2.打印出 100 至 200 之间的奇数。 3. 鸡兔同笼(用 for 循环程序完成) 4.一辆快车和一辆慢车开往同一地点,快车票价为 18 元,慢车票价为 13. 5 元,共售出 400 张,共计 5940 元,求快车票和慢车票各多少张?. 5.求出能被 5 整除的所有四位数的和。 6.在下面式子中的二个□内填入一个合适的同样的数字,使等式成立。 □3*6528=3□*8256 7.有一个三位数,它的各位数字之和的 11 倍恰好等于它自身,请编程求出这个三位数。 8.在自然数中,如果一个三位数等于自身各位数字之立方和,则这个三位数就称为是水21 仙花数。如:153=13+53+33,所以 153 是一个水仙花数。求所有的水仙花数。 9.编程序打印出下列图案: 平行四边形 等腰三解形 菱形 ****** * * ****** *** *** ****** ***** ***** ****** ******* *** ****** ********* * 10.编程打印出如下图案: 1 222 4 .有三种明信片:第一种每套一张,售价 2 元;第二种每套一张,售价 4 元; 第三种每 套 9 张,售价 2 元。现用 100 元钱要买 100 张明信片,要求每种明信片至少要买一套,问三 种明信片应各买几套?请输出全部购买方案。 12.某人想把一元钱换成伍分、贰分、壹分这样的零钱, 在这三种零钱中每种零钱都至 少各有一个的情况下,共有多少种兑换方案。并打出这些方案。 13. 14. 输出 100 以内的全部素数,要求每行显示 5 个。 15.A、B 两个自然数的和、差、积、商四个数加起来等于 243,求 A、B 两数。 16.百钱买百鸡:今有钱 100 元,要买 100 只鸡,公鸡 3 元一只,母鸡 1 元一只,小鸡 1 元 3 只,若公鸡、母鸡和小鸡都至少要买 1 只,请编程求出恰好用完 100 元钱的所有的买鸡 方案。第二节repeat 循环Repeat 循环是直到型循环。 试将上一节的例 3.1(打印出 1~20 的平方数表)程序改为 repeat 循环: Program Exam31_1; Var a: byte; Begin a:=1; writeln ( ' a ' : 8 , ' a*a ' : 8 ) ; repeat writeln ( a :8,a*a : 8); inc(a); {改变 a 的值 } Until a>20; Readln Emd.22 程序中的 Repeat 循环格式为: repeat 循环体语句; until 条件表达式; {直到条件为真} Repeat 循环首先执行由 Repeat 和 Until 括起来的循环体语句, 然后检查 Until 后面 的条件表达式:如果表达式结果为假,则继续执行循环体,接着继续检查 Until 后面的条件 表达式, 如此反复执行直到这个表达式结果为真时结束循环。 Repeat 循环体语句必须有能改 变 Until 后面条件表达式值的语句,并最终使这个条件表达式的值为真,使循环自动结束。 程序中 inc (a) 指令相当于 a : =a+1,常用的同类指令格式如下: (1) inc(x) 等同 x:=x+1; (2) inc(x, n) 等同 x:=x+n; (3) dec(x) 等同 x:=x―1; (4) dec(x,n) 等同 x:=x―n; [例 3.10]求两个自然数 M 和 N 的最大公约数。 解:若自然数 a 既是 M 和约数,又是 N 的约数,则称 a 为 M 和 N 的公约数,其中最大 的称为最大公约数。为了求得最大公约数,可以从最大可能的数(如 M 或 N)向下寻找, 找到的第一个公约数即是最大公约数。 Pascal 程序: Program ex310; Begin a := N+1; Repeat a := a-1; Until (M mod a=0) and (N mod a=0); writeln(a); R End.[例 3.11]校体操队到操场集合,排成每行 2 人,最后多出 1 人;排成每行 3 人,也多出 1 人;分 别按每行排 4,5,6 人,都多出 1 人;当排成每行 7 人时,正好不多。求校体操队至少是多少人? 解:①设校体操队为 X 人,根据题意 X 应是 7 的倍数,因此 X 的初值为 7,以后用 inc(x,7)改 变 X 值; ②为了控制循环, 用逻辑变量 yes 为真(True) 使循环结束; ③如果诸条件中有一个不满足, yes 的值就会为假(false),就继续循环。 Pascal 程序: program Exam311; var x: yes : begin x:=0; repeat23 yes := inc(x,7); if x mod 2 & & 1 then yes:= if x mod 3 & & 1 then yes:= if x mod 4 & & 1 then yes:= if x mod 5 & & 1 then yes:= if x mod 6 & & 1 then yes:= writeln('All =', x) ; readln end.{直到 yes 的值为真 }程序中对每个 X 值,都先给 Yes 赋真值,只有在循环体各句对 X 进行判断时,都得到 “通过” (此处不赋假值)才能保持真值。 [例 3.12]从键盘输入一个整数 X(X 不超过 10000) ,若 X 的各位数字之和为 7 的倍数, 则打印“Yes” ,否则中打印“No” 。 解:本题考察的是数字分离的方法,由于 X 的位数不定,所以以往的解法不能奏效,这 是介绍一种取余求商法。 (1)用 X mod 10 分离出 X 的个位数字; (2)用 X div 10 将刚分离的个数数字删除,并将结果送回给 X; (3)重复(1) (2)直到 X=0。 Pascal 程序: Program ex12; var x,a,s : begin s := 0; repeat a := x mod 10; x := x div 10; s := s+a; until x=0; if s mod 7=0 then writeln(‘Yes’) else writeln(‘No’); R [例 3.13]求 1992 个 1992 的乘积的末两位数是多少? 解:积的个位与十位数只与被乘数与乘数的个位与十位数字有关,所以本题相当于求 1992 个 92 相乘,而且本次的乘积主下一次相乘的被乘数,因此也只需取末两位参与运算就 可以了。 Pascal 程序: Program ex313; var a,t :24 Begin a := 1; t := 0; repeat t := t+1; a := (a*92) mod 100; until t=1992; writeln(a); R End. [例 3.14]尼科彻斯定理:将任何一个正整数的立方写成一组相邻奇数之和。 如: 33=7+9+11=27 43=13+15+17+19=64 解:从举例中发现: (1) n3 正好等于 n 个奇数之和; (2) n 个奇数中的最小奇数是从 1 开始的奇数序列中的第 m 个奇数,与 n 的关系为: m=n (n ―1) / 2+1。 (3) 奇数序列中第 m 个奇数的值为 x,且 x= 2m―1,比如: n=3 时,m=3(3-1)/2+1=4, 即 3 个奇数中最小的奇数是奇数序列中的第 4 个, 它的值为 x=(2m-1)=7, 所以: 33=7+9+11。 (4) 从最小的奇数值 x 开始, 逐个递增 2, 连续 n 个,用 t 从 1 开始计数, 直到 t=n 为止。 Pascal 程序: Program Exam35; Var n,m,x,t,s : integer; Begin write(’input n:’); readln(n); {输入 N } m:=(n*(n-1) div 2)+1; {找到第 m 个奇数 } x:=2*m-1; t:=1; {算出第 m 个奇数的值 x,是所求的第一个} write(n’*’ ,n, ,n, ’*’ ’=’ ,x);{输出第一个} s:=x; {用 S 计算和 } if n>1 then Repeat inc(x,2); { 计算下一个奇数 } write (’+ ’ ,x) ; {加上下一个奇数 } inc (t ); inc (s,x); { 计个数并累加和 } Until t=n; {直到 n 个 } Writeln (’= ’ ) ; ,s Readln End. [例 3.15]猜价格:中央电视台的“幸运 52”栏目深受观众喜爱,其中的“猜商品价格” 的节目更是脍炙人口,现在请你编一个程序模拟这一游戏:由计算机随机产生 200 至 5000 之间的一个整数,作为某件商品的价格,然后由你去猜是多少,若你猜的数大了,则计算机25 输出提示“Gao” ,若你猜的数小了,则计算机输出提示“Di” ,然后你根据提示继续猜,直 到你猜对了,计算机会提示“Ok” ,并统计你猜的总次数。 解:本题的游戏规则大家都清楚,要完成程序,必须把处理步骤理清: (1)用随机函数 Random 产生 200 至 5000 之间的一个整数 X; (2)你猜一个数 A; (3)若 A>X,则输出“Gao” ; (4)若 A<X,则输出“Di” ; (5)若 A=X 则输出“Ok” ; (6)重复(2)(3)(4)(5)直到 A=X。 Pascal 程序: Program ex315; Var t,X,a : Begin R X := Random(; t := 0; Repeat t := t+1; write(‘[‘,t,’] Qing cai yi ge zheng shu : ‘); readln(a); if a&x then writeln(‘Gao’); if a&x then writeln(‘Di’); if a=x then writeln(‘Ok’); Until A=X; R End. 习题 3.2 1.求两个自然数 M 和 N 的最小公倍数。 (如果求三个或更多个数的最小公倍数呢?应如 何解决) 2.小会议室里有几条相同的长凳,有若干人参加开会。 如果每条凳子坐 6 人,结果有一条凳 子只坐有 3 人;如果每条凳子坐 5 人,就有 4 人不得不站着。 求会议室里有多少人开会,有多少 条长凳? 3.某动物饲养中心用 1700 元专款购买小狗(每只 31 元)和小猫(每只 21 元)两种小动物。 要求专款专用,正好用完, 应当如何购买?请输出所有方案。 4.某整数 X 加上 100 就成为一个完全平方数,如果让 X 加上 168 就成为另一个完全平方 数。求 X? 5.某次同学聚会,老同学见面个个喜气洋洋,互相握手问好。 参加此次聚会者每人都与老同 学握了一次手,共握 903 次,试求参加聚会的人数? 6.用自然数 300,262,205,167 分别除以某整数 A,所得到的余数均相同。求出整数A 以及相除的余数? 7.1600 年前我国的一部经典数学著作中有题: “今有物,不知其数,三三数之,剩二;26 五五数之,剩三;七七数之,剩二,问物几何。 ”求最小解。 8.编程求出所有不超过 1000 的数中,含有数字 3 的自然数,并统计总数。 9.阿姆斯特朗数:如果一个正整数等于其各个数字的立方和,则该数称为阿姆斯特朗数 (也称自恋数) ,如 407=43+03+73,试编程求出 1000 以内的所有阿姆斯特朗数。第三节While 循环While循环是当型循环。 [例3.8] 前面第一章[例1.2]的鸡兔同笼,头30,脚90, 求鸡兔各几只?在此用下面方 法编程求解。 解: 设鸡为J只,兔为T只。已知头为H, 脚为F。 ①让鸡的只数逐次加1进行递推计算,初始时J=0; ②计算兔的只数T=H-J; ③当总脚数(4*T+2*J) & & F就做 (J=J+1,T=H-J); ④当4*T+2*J=F时,说明所推算的J和T是正确的,应结束循环,并输出T, J。 Pascal程序: Program Exam38; Const H=30; F=90; Var J,T : Begin J:=0; T:=H-J; {初始时让J从0开始计算 } While 4*T+2*J<>F do {当条件为真就做do后面的循环体 } begin inc(J); { 递推改变J值 } T:=H-J {计算兔的只数 } Writeln('T=',T,' ':6, 'J=', J ) ; Readln End. 程序中采用While当型循环,While循环语句的格式为: While 条件式 do 语句; 其中do后面的“语句”是被重复执行的,称为循环体;若循环体是多个语句, 必须用 begin--end包起来成为复合语句。 While循环首先判断条件式,当条件式的值为真就执行do 后面的语句(循环体)。 While的循环体内也必须包含能改变控制变量取值语句, 影响条件式的值, 最终使条件 式为false (假), 才能结束循环。 [例3.9] 输入任一的自然数A, B, 求A , B的最小公倍数。 解:这里采用适合计算机查找的方法: 设D是它们的最小公倍数。先找出A, B当中的较大 者并存放在A中, 将较小者存放在B中, 让D=A, 当D能够整除B时, 则D是所求的最小公倍数;27 当D不能整除B,就逐次地让D增加A。例如:A=18, B=12, 步骤如下: ① 让D=A (D=18) ② 当(D mod B)<>0 为真时 ( D不能整除B ) 就做 D=D+A, 重复②; ③ 当(D mod B)<>0 为假时结束循环,并输出D。 Pascal程序: program Exam39; var a,b,d,t : begin write('input a,b: '); readln(a , b); if a&b then begin t:=a; a:=b; b:= d:=a; while d mod b & &0 do {当条件为真时就做do后面的语句 } inc(d,a); writeln('[', a, ' , ' , b, ']=', d) ; readln End. Pascal语言的三种基本循环方式, for循环对循环范围有明确规定, 且循环变量只能 是递增加1或递减1自动计数控制; 而repeat--until循环和while--do循环比较灵活, 只要 对条件表达式的值能控制满足一定要求就能组成循环, 但在循环体中必须有改变循环变量 值的语句, 使条件判断(逻辑值)最终为True或flase, 让循环能够终止。 [例3.10]求自然数A, B的最大公约数。 解:采用如下方法步骤: (1)求A除以B的余数; (2)当余数<>0就做n=a; a=b; b=n mod b, 重复(1)和(2); (3)当余数=0就结束循环,并输出b值。 比如a=18, b=12时,处理步骤为: (1) = ,得余数为6; (2) 此余数不为零 ,让a = 12, b = 6; (3) 重复 = , 得余数为0; (4) 结束循环,输出6(余数为零时的b值即是所求的最大公约数)。 此方法称为辗转相除法求最大公约数。 Pascal程序: program Exam310; var a,b, n : begin write('input a,b: '); readln (a,b); write('(', a, ' , ' , b, ')=' ) ; while a mod b & & 0 do28 begin n:=a; a:=b; b:= writeln(b); readln End. [例3.11]将一根长为369cm的钢管截成长为69cm和39cm两种规格的短料。在这两种规格 的短料至少各截一根的前提下, 如何截才能余料最少。 解:设两种规格的短料分别为: 规格为69cm的x根,可在1至(369-39)/69范围循环取值; 规格为39cm的y根,用y = (369-69*X)/39)计算; 余料R=369-69*X-39*Y。 ①设最小余料的初始值min=369; ②在X循环范围内,每一个X值都计算出对应的Y和R; ③如果R<min, 就将R存入min, x存入n, y存入m,记录余料最小时的x和y ; ④重复步骤②,当x值超出 ((369―39)/ 69) 时结束循环。 Pascal程序: program exam311; var x,y,r,min,n,m,a: begin min:=369; a:=(369-39) div 69; x:=1; while x&=a do begin y:=(369-69*x) div 39; r:=369-69*x-39*y; if r&min then begin min:=r; n:=x; m:= inc(x); writeln('min=', min, ' x=', n, ' y=', m) ; readln end. 在有些情况中, 三种循环方法可以互相换用。 [例3.12]甲、乙、丙三人都是业余射击爱好者, 在一次练习中他们枪枪中靶: 甲射了八 发子弹,取得225环成绩,乙射了七发,也取得225环;丙只射了六发,同样取得225环。 下面是成 绩表,请编程完成下表中空项的填数。 射子弹数 甲 乙 8 7 中50环有几发 中35环有几发 中25环有几发 成绩(环) 225 22529 丙6225解:①设N为发射子弹数, 只有8, 7, 6三个数字, 正好又可用来代表甲、乙、丙; ②设A为中50环的子弹数, 最小为0, 最大为(225 div 50=4); B为中35环的子弹数, 最小为0, 最大为(225 div 35=6); C为中25环的子弹数, C=N-A-B, 但必须C>0才可能正确; ③先让N=8, A取值(0~4), B取值 (0~6)用循环逐个选定, 在C>0的情况下若能 满足条件A*50+B*35+C*25=225就能确定一组填数。然后选N的下一数值,重复同样的过程。 Pascal程序: program exam312; var a,b,c,n,s : begin writeln('n':3, 'a':3, 'b':3, 'c':3, 's':5) ; n:=8; while n&=6 do begin a:=0; while a & = 4 do begin b:=0; while b & = 6 do begin c:=n-a-b; if c&0 then begin s:=50*a+35*b+25*c; if s=225 then writeln(n:3,a:3,b:3,c:3,s:5); inc(b); inc(a); dec(n); readln end. 程序运行结果获得两组填数答案。如果改用for循环,程序将更加简明: Program Exam312_1; Var a,b,c,n,s : I Begin Writeln('N':3, 'A':3, 'B':3, 'C':3, 'S':5) ; for n:=8 downto 6 do {N取值8, 6, 7, 并分别代表甲、 丙 } 乙、 for a:=0 to 4 do {中50环的可能范围 }30 for b:=0 to 6 do {中30环的可能范围 } begin c:=n-a-b; { 计算中25环的子弹数 } if c>0 then begin {如果不是负数 } s:=50*a+35*6+25*c; {计算总成绩 } if s=225 then writeln(n:3,a:3,b:3,c:3,s:5); readln End. 习题3.3 1.求S= 1-1/2 +1/3-1/4+1/5-1/6+ ??(求前N项的和) 2. Faibonacci数列前几项为: 0,1,1,2,3,5,8,?,其规律是从第三项起, 每项均等于前 两项之和。求前30项, 并以每行5个数的格式输出。 3.小球从100高处自由落下,着地后又弹回高度的一半再落下。求第20次着地时, 小球共 通过多少路程? 4.某登山队员第一天登上山峰高度的一半又24米; 第二天登上余下高度的一半又24米; 每天均如此。到第七天,距山顶还剩91米。求此山峰的高度? 5.给出某整数N,将N写成因数相乘的形式。如: N=12,输出: 12=1*2*2*3. 6.出售金鱼者决定将缸里的金鱼全部卖出。第一次卖出全部金鱼的一半加二分之一条; 第二次卖出剩余的三分之一加三分之一条金鱼;第三次卖出余下金鱼的四分之一加四分之一 条;第四次卖出余下的五分之一加五分之一条金鱼。 还剩下11条金鱼。 当然,出售金鱼时都是 整数条,不能有任何破损。求缸里原有的金鱼数? 7.外出旅游的几位朋友决定次日早晨共分一筐苹果。天刚亮,第一个人醒来,他先拿了一 个,再把筐里的八分之一拿走;第二个人醒来,先拿两个,再把筐里的八分之一拿走;第三个人 醒来,先拿三个,再拿走筐里的八分之一;?每个人依次照此方法拿出各人的苹果,最后筐里 的苹果全部拿完,他们每人所拿到的苹果数正巧一样多。求原先筐里的苹果数和人数。 8.图中由6个圆圈构成三角形,每条边上有三个圈, 将自然数1--6 不重复地填入各圆圈 位置上,使每条边圆圈上的数字之和相等,请编程输出所有的填法。 9.请编程显示出下面数字金字塔图形:31 第四章函数与过程程序中往往需要把主要任务分成若干个子任务,每个子任务只负责一个专门的基本工 作。每个子任务就是一个独立的子程序。Turbo Pascal 可以把函数和过程作为子程序调用。第一节函数Pascal允许用户在程序中自己说明定义所需要的函数并在程序中调用这些函数。 [例4.1]编程找出由键盘任意输入五个整数中的最大整数。 解:设输入的五个整数为n1、n2、n3、n4、n5,为了便于处理,引入一个中间变量t1, 按如下步骤处理: ①令t1=n1; ②将t1与n2比较,将两者中较大的数放入t1; ③将t1与n3比较,将两者中较大的数放入t1; ④将t1与n4比较,将两者中较大的数放入t1; ⑤将t1与n5比较,将两者中较大的数放入t1; ⑥经过以上5步处理后,t1即为5个数中最大者。 从上面规划的步骤看来,从步骤②到步骤⑤需处理的目标是相同的,因此我们可以设计 一段子程序Max(x1,x2),以找出x1和x2中最大的值并返回。 Pascal程序: Program Exam41_a; Var n1,n2,n3,n4,n5,t1 : Function max(x1,x2 : integer) : Begin If x1&x2 then Max := x1 Else Max := x2; E Begin Write(‘Input 5 numbers : ‘); Readln(n1,n2,n3,n4,n5); T1 := n1; T1 := Max(t1,n2); T1 := Max(t1,n3); T1 := Max(t1,n4); T1 := Max(t1,n5); Writeln(‘Max number : ‘,t1); End. 从上例看出,引入函数实际上是将一个复杂的问题划分成若干个易于处理的子问题,将32 编程化简的一种有效办法, 而化简的方法是多种多样的, 如前面已经做过求三个数中的最大 数,所以可定义一个专门求三个数中最大数的函数(Max)。第一次用这个函数求出n1,n2,n3 三个数中的最大数t1;第二次调用这个函数求出t1与n4,n5三个数中的最大数, 也就是前三个 数的最大数(已在t1中)和后面二个数再求一次,就得到五个数的最大数。因此,需要两次使 用“求三个数中的最大数”,步骤如下: ①调用函数Max ( n1, n2, n3), 求出n1,n2,n3中的最大者 t1; ②调用函数Max ( t1, n4, n5 ),求出t1, n4, n5中的最大者t2; ③输出最大数 t2。 Program Exam41_b; Var n1,n2,n3,n4,n5,t1: function Max(x1,x2,x3: integer): Var XX: begin if X1>X2 then XX:=X1 else XX:=X2; if X3>XX then XX:=X3; Max:=XX {自定义函数Max} {函数内部变量说明} {函数体}Begin {主程序} Write('Input 5 numb:'); Readln(n1,n2,n3,n4,n5); {输入五个数} t1:=Max(n1,n2,n3); {用函数求n1, n2, n3的最大数} t1:=Max(n4,n5,t1); {用函数求n4, n5, t1 的最大数} Writeln('Max Number :', t1); Readln End. 主程序中两次调用自定义函数。自定义函数的一般格式为: function 函数名(形式参数表): 类型; {函数首部} 局部变量说明部分; begin 语句系列; {函数体 } 函数中的形式参数接受调用函数时所传入的值,用来参与函数中的运算。 [例4.2]求任意输入的五个自然数的最大公约数。 解:⑴自定义一个专门求两自然数的最大公约数的函数GCD; ⑵调用自定义函数,第一次求前两个数的最大公约数;从第二次开始,用每次求得的 最大公约数与下一个数再求两个数最大公约数,直到最后。本题共四次“求两个数的最大公 约数”, 设输入的五个自然数分别是a1,a2,a3,a4,a5,采用如下步骤: ①求a1, a2两个数的最大公约数 → 存入a1;33 ②求a1, a3两个数的最大公约数 → 存入a1; ③求a1, a4两个数的最大公约数 → 存入a1; ④求a1, a5两个数的最大公约数 → 存入a1; ⑤ 输出 a1,此时的a1已是五个数的最大公约数。 Pascal程序: Program Exam42; Var a1,a2,a3,a4,a5: function GCD(x,y: integer): {自定义函数 } Var n: begin While x mod y <>0 do begin n:=x; x:=y; y:= GCD:= Begin {主程序 } Write('input 5 Numper:'); readln(a1,a2,a3,a4,a5); {输入五个数} Write('(',a1,',',a2,',',a3,',',a4,',',a5,')='); a1:=GCD(a1,a2); {调用函数GCD } a1:=GCD(a1,a3); a1:=GCD(a1,a4); a1:=GCD(a1,a5); Writeln(a1); readln End. 函数的结果是一个具体的值, 在函数体中必须将所得到的运算结果赋给函数名;主程序 通过调用函数得到函数的运算结果。调用函数的一般格式为: 函数名 (实在参数表) 调用函数时, 函数名后面圆括号内的参数必须有确定的值, 称为实在参数。 调用时即把 这些实际值传送给函数形参表中的相应形参变量。 函数不是单独的语句, 只能作为运算赋值 或出现在表达式中。 习题4.1 1. 数学上把从 1 开始的连续自然数相乘叫做阶乘。例如 把1*2*3*4*5 称作5的阶乘, 记为5!。 编写一个求n!的函数, 调用此函数求: D= 2.求从键盘输入的五个自然数的最小公倍数。 3.哥德巴赫猜想的命题之一是:大于6 的偶数等于两个素数之和。编程将6~100所有偶 数表示成两个素数之和。 4.如果一个自然数是素数,且它的数字位置经过对换后仍为素数,则称为绝对素数,例如34 13。试求出所有二位绝对素数。第二节自定义过程自定义函数通常被设计成求一个函数值,一个函数只能得到一个运算结果。若要设计成 能得到若干个运算结果,或完成一系列处理,就需要自定义“过程”来实现。 [例4.3] 把前面[例2.2 ](输入三个不同的整数,按由小到大排序)改为下面用自定义 过程编写的Pascal程序: Program exam43; Var a,b,c: Procedure Swap (var x,y: integer); {自定义交换两个变量值的过程 } Var t : Begin {过程体} t:=x; x:=y; y:=t {交换两个变量的值 Begin {主程序} Write('input a,b,c='); Readln(a,b,c); if a>b then swap (a,b); {调用自定义过程} if a>c then swap (a,c); if b>c fhen swap (b,c); Writeln (a:6, b:6, c:6); R End. 程序中Procedure Swap是定义过程名,从作用来看,过程与函数是相似的,都能将复杂 的问题划分成一些目标明确的小问题来求解, 只不过函数有值返回而过程则没有。 自定义过 程的一般格式如下: Procedure 过程名 (形式参数表); {过程首部} 局部变量说明部分; begin 语句部分; {过程体部分} [例4.4]如果一个自然数除了1和本身,还有别的数能够整除它, 这样的自然数就是合 数。例如15,除了1和15,还有3和5能够整除,所以15是合数。14,15,16是三个连续的合数,试 求连续十个最小的合数。 解:从14,15,16三个连续合数中可看出,它们正好是两个相邻素数13和17 之间的连续自 然数,所以求连续合数问题可以转化为求有一定跨度的相邻两个素数的问题。因此,求连续 十个最小的合数可用如下方法:35 ①从最小的素数开始,先确定第一个素数A; ②再确定与A相邻的后面那个素数B;(作为第二个素数); ③检查A,B的跨度是度否在10 以上,如果跨度小于10,就把B 作为新的第一个素数A,重 复作步骤②; ④如果A、B跨度大于或等于10,就打印A、B之间的连续10个自然数,即输出 A+1, A+2, A+3 …, A+10。 Pascal程序: Program exam44; var a,b,s,n: yes: procedure sub(x:var yy: boolean); {过程:求x是否为素数 } var k,m: { 用yy逻辑值转出 } begin k:=trunc(sqrt(x)); for m:=3 to k do if odd(m) then if x mod m=0 then yy:= begin {主程序 } b:=3; repeat a:=b; {a 为第一个素数 } repeat yes:= inc(b,2); {b是a后面待求的素数} sub(b,yes); {调用SUB过程来确认b是否为素数 } if yes then s:=b-a; {如果b是素数,则求出跨度s } until s & = 10; for n:=a+1 to a+10 do write(n:6); readln end. 程序中的过程SUB,用来确定b是否为素数。过程名后面圆括号内的变量是形式参数,简 称为形参。过程SUB(x: Var yy: boolean) 中的x是值形参,而前面冠有Var的yy 是变量形参。 值形参只能从外界向过程传入信息,但不能传出信息;变量形参既能传入又能传 出信息。本程序过程SUB中的x是由调用过程的实在参数b传入值,进行处理后,不需传出; 而yy是把过程处理结果用逻辑值传出,供调用程序使用。 试把[例4.3]程序中的过程 SWAP(Val x,y: integer),将x,y前面的Var去掉,就变成 了纯粹的值形参,就不能将过程所处理的结果传出去,也就无法得到处理后的结果,通过运36 行程序比较,可以非常明显地看到值形参和变量形参的区别。 调用过程的格式为: 过程名(实在参数表) ; 调用过程名后面圆括号内的实在参数与定义过程的形参表必须相对应,调用过程相当于 一个独立语句,可单独使用。 [例4.5]将合数483的各位数字相加(4+8+3)=15,如果将483分解成质因数相乘: 483=3*7*23,把这些质因数各位数字相加(3+7+2+3),其和也为15。即某合数的各位数字 之和等于它所有质因数的各数字之和。求500以内具有上述特点的所有合数。 解:①设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。 PASCAL程序: program exam45; var n,t1,t2,tatol: yes: procedure sub1(x: var t:integer); {过程:分离x的各位数字 } begin {并求各位数字之和 } repeat t:=t+x mod 10; x:=x div 10; until x=0 procedure sub2(x: var t: integer); var xx,tt: begin xx:=2; while x&1 do if x mod xx=0 then begin tt:=0; sub1(xx,tt); t:=t+ x:=x div xx end else inc(xx) {过程:分解质因数 }37 procedure sub3(x:var yy: boolean); var k,m: begin k:=trunc(sqrt(x)); for m:=2 to k do if x mod m=0 then yy:= begin for n:=1 to 500 do begin t1:=0;t2:=0; yes:= sub3(n,yes); if not yes then begin sub1(n,t1); sub2(n,t2); if t1=t2 then write(n:6); readln end.{过程:判断x是否为素数 }{主程序}{调用过程求素数 } {如果非素数就? } {调用过程求n的各位数字之和 } {调用过程求n的各质因数的数字之和 } {打印合格的合数 }程序定义了三个过程SUB1,SUB2,SUB3,其中SUB2过程中又调用了SUB1。在过程中定义 的变量或参数,只在本过程内部使用有效。这些变量称为局部变量。如SUB2中的xx只在SUB2 中使用,属于局部变量。 习题:4.2 1.输入自然数n,求前n个合数(非素数),其素因子仅有2,3,或5。 2.自然数a的因子是指能整除a的所有自然数, 但不含a本身。 例如12的因子为: 1,2,3,4,6。 若自然数a的因子之和为b,而且b的因子之和又等于a,则称a,b为一对“亲和数” 。求最小 的一对亲和数。 3.求前n个自然数的平方和,要求不用乘法。例如:3的平方不用3*3,可用3+3+3。 4.试用容积分别为17升、13升的两个空油桶为工具,从大油罐中倒出15升油来,编程显 示出具体的倒油过程。 5.如果一个数从左边读和从右边读都是同一个数,就称为回文数。例如6886就是一个回 文数,求出所有的既是回文数又是素数的三位数。 6. 任何大于2的自然数都可以写成不超过四个平方数之和。如: 2 2 2 2 2 8=2 +2 ; 14=1 +2 +3 由键盘输入自然数N(2 & N & 2000) ,输出其不超过四个平方数之和的表示式。38 第五章Pascal 的自定义数据类型Pascal系统允许用户自定义的数据类型有:数组类型、子界类型、枚举类型、集合类型、 记录类型、文件类型、指针类型。第一节序号 品名 件数 单价 1 圆珠笔 24 1.18 2 铅笔 110 0.45 3 60 1.8数组与子界类型4 16 8.8 5 26 78.50 6 32 3.28 7 圆规 32 4.20 8 文件夹 42 2.16[例5.1]总务室在商店购买了八种文具用品,其数量及单价如下表: 笔记本 订书机 计算器 三角板编程计算各物品计价及总计价。 解:表中有两组数据,设表示物品件数的一组为a,表示物品单价的一组为b。 a,b两组数据以序号为关联,具有相应的顺序关系。按如下方法处理: ①定义s,a,b三个数组,按相应顺序关系,给a,b赋值(件数和对应单价) ; ②每读入一对数据(件数和对应单价),以同一序号的件数和对应单价计算出同一物品 的计价: s[ i ]=a[ i ]* b[ i ] ; { 用s[ i] 记入第i种物品的计价} t = t + s[ i ] { 用简单变量累加总计价 } ③循环做步骤②,做完后输出s数组所记入的各物品计价及总计价t。 Pascal程序: Program Exam51; Var a: array[1..8] {a数组为整数型} s,b: array[1..8] {s和b数组为实数型} t: i: Begin t:=0; for i:=1 to 8 do {输入并计算八种物品 } begin write('a[', i, ']=') ; Readln(a[ i ]) ; {输入单价} write('b[', i, ']=') ; readln(b[ i ]); {输入件数} s[ i ]:=a[ i ]* b[ i ]; t:=t+s[ i ] write('i':2, ' ':2);39 for i:=1 to 8 do {打印物品序号} write(i:8); {输出项宽度为8} write('a':2, ' ':2); {输出项宽度为2} for i:=1 to 8 do {打印物品件数a数组} write(a[ i ]:8); {输出项宽度为8} {换行} write('b':2, ' ':2); for i:=1 to 8 do {打印物品件数b数组} write(b[ i ]:8:2); {输出项宽度为8,小数2位} {换行} write('s':2, ' ':2); for i:=1 to 8 do {打印物品计价s数组} write(s[ i ]:8:2); {输出项宽度为8,小数2位} {换行} writeln('Totol=', t:8:2); {打印总价t} Readln end. 输出语句为 write(实数:n:m) 的形式时,则输出该实数的总宽度为n,其中小数 m位,此时的实数不以科学计数形式显示。 程序中用来表示如物品件数和物品单价等属性相同的有序数据,Pascal语言把它归为数 组。数组成员(分量)称为数组元素。数组必须在说明部分进行定义:确定数组名,数组分 量(元素)的个数及类型。一般格式有: Var 数组名:array[下标类型] of 数组元素类型 ; 本程序中a数组和b数组中8个元素的数据都是已知数据,可当作常量,用常量说明语句 给数组元素赋初值,所以上面的程序Exam51可改为如下形式: Program Exam51_1; const a: array[1..8] of integer =(24,110,60,16,26,32,32,42); {给a数组赋初值} b:array[1..8] of real =(1.18,0.45,1.80,8.8,78.50,3.28,4.20,2.16); {给b数组赋初值} Var s: array[1..8] t: i: Begin t:=0; for i:=1 to 8 do begin s[ i ]:=a[ i ]* b[ i ]; t:=t+s[ i ] write('i':2, ' ':2); for i:=1 to 8 do write(i:8);40
write('a':2, ' ':2); for i:=1 to 8 do write(a[ i ]:8:); write('b':2, ' ':2); for i:=1 to 8 do write(b[ i ]:8:2); write('s':2, ' ':2); for i:=1 to 8 do write(s[ i ]:8:2); writeln('Totol=', t:8:2); Readln end. 数组常量说明格式为: Const 数组名:array[下标类型]of 数组元素类型=(常量表); 程序中对数组的输入、输出处理,常用循环语句控制下标,进行有序地直接操作每个数 组元素。 [例5.2]编程输入十个正整数,然后自动按从大到小的顺序输出。 解:①用循环把十个数输入到A数组中; ②从A[1]到A[10],相邻的两个数两两相比较,即: A[1]与A[2]比,A[2]与A[3]比,??A[9]与A[10]比。 只需知道两个数中的前面那元素的标号,就能进行与后一个序号元素(相邻数)比较, 可写成通用形式A[ i ]与A[ i +1]比较,那么,比较的次数又可用1~( n - i )循环进行控 制 (即循环次数与两两相比较时前面那个元素序号有关) ; ③在每次的比较中, 若较大的数在后面, 就把前后两个对换, 把较大的数调到前面, 否则不需调换位置。 下面例举5个数来说明两两相比较和交换位置的具体情形: 5 6 4 3 7 5和6比较,交换位置,排成下行的顺序; 6 5 4 3 7 5和4比较,不交换,维持同样的顺序; 6 5 4 3 7 4和3比较,不交换,顺序不变 6 5 4 3 7 3和7比较,交换位置,排成下行的顺序; 6 5 4 7 3 经过(1~(5-1))次比较后,将3调到了末尾。 经过第一轮的1~ (N-1)次比较,就能把十个数中的最小数调到最末尾位置,第二轮比 较1~ (N-2)次进行同样处理,又把这一轮所比较的“最小数”调到所比较范围的“最末尾” 位置;??;每进行一轮两两比较后,其下一轮的比较范围就减少一个。最后一轮仅有一次 比较。在比较过程中,每次都有一个“最小数”往下“掉”,用这种方法排列顺序,常被称 之为“冒泡法”排序。 Pascal程序: Program Exam52; const N=10; Var a: array[1..N] {定义数组} i,j:41 procedure Swap(Var x,y: integer); {交换两数位置的过程} Var t: begin t:=x; x:=y; y:= Begin for i:=1 to N do {输入十个数} begin write(i, ':'); Readln(a[ i ]) for j:=1 to N-1 do {冒泡法排序} for i:=1 to N-j do {两两相比较} if a[ i ] & a[i+1] then swap(a[ i ], a[i+1]); {比较与交换} for i:=1 to N do {输出排序后的十个数} write(a[ i ]:6); Readln end. 程序中定义a数组的下标类型为 1.. N ,这种类型规定了值域的上界和下界,是从一个 有序类型范围取出一个区段,所以称为子界类型,子界类型也是有序类型。 例[5.3] 用筛法求出100以内的全部素数,并按每行五个数显示。 解:⑴ 把2到100的自然数放入a[2]到a[100]中(所放入的数与下标号相同); ⑵ 在数组元素中,以下标为序,按顺序找到未曾找过的最小素数minp,和它的位置 p(即下标号); ⑶ 从p+1开始,把凡是能被minp整除的各元素值从a数组中划去(筛掉),也就是 给该元素值置 0; ⑷ 让p=p+1,重复执行第②、③步骤,直到minp&Trunc(sqrt(N)) 为止; ⑸ 打印输出a数组中留下来、未被筛掉的各元素值,并按每行五个数显示。 用筛法求素数的过程示意如下(图中用下划线作删去标志) : ① 2 3 4 5 6 7 8 9 10 11 12 13 14 15?98 99 100 {置数} ② 2 3 4 5 6 7 8 9 10 11 12 13 14 15…98 99 100 {筛去被2整除的数 } ③ 2 3 4 5 6 7 8 9 10 11 12 13 14 15…98 99 100 {筛去被3整除的数 } …… 2 3 4 5 6 7 8 9 10 11 12 13 14 15…98 99 100 {筛去被整除的数 } Pascal程序: Program Exam53; const N=100; type xx=1 .. N; {自定义子界类型xx (类型名) } Var a: array[xx] i,j:42 Begin Fillchar(a,sizeof(a),true); a[1] := F for i:=2 to Trunc(sqrt(N)) do if a[I] then for j := 2 to N div I do a[I*j]:= F t:=0; for i:=2 to N do if a[i] then Begin write(a[ i ]:5); inc(t); if t mod 5=0 readln End. 程序中自定义的子界类型,在用法上与标准类型(如integer)相同,只是值域上界、 下界在说明中作了规定,而标准类型的值域由系统内部规定,其上界、下界定义是隐含的, 可直接使用。例如: Type integer= -32768 ... 32768; Pascal系统已作了标准类型处理,不必再作定义。 [例5.4]在一次宴会上,有来自八个不同国家的宾客被安排在同一张圆桌就坐。A是中国 人,会讲英语;B是意大利人,他能讲西班牙语;C是英国人,会讲法语;D是日本人,能讲 汉语;E是法国人,会讲德语;F是俄国人,懂意大利语;G是西班牙人,能讲日语;最后一 个是德国人,懂俄语。编程序安排他们的座位,使他们在各自的座位上能方便地跟两旁的客 人交谈。 解:①根据题目提供条件与数据,建立如下关系代码表: 国家名 宾客代码 语言代号 懂外语代号 总代码 中国 A 1 3 A13 意大利 B 2 7 B27 英国 C 3 5 C35 日本 D 4 1 D41 法国 E 5 8 E58 俄国 F 6 2 F62 西班牙 G 7 4 G74 德国 H 8 6 H86表中总代码实际上是前三项代码的归纳:第一个字母表示哪国人;第二个数字表示本国 语代号;第三个数字表示懂哪国外语。如A13,A表示中国人,1表示汉语(本国语),3表示 会说英语。所以每个宾客的情况均用总代码(三个数据组成的字符串)表示; ②定义由8个元素组成的数组(NAME),元素类型为字符串类型(String); ③元素的下标号影响各人座位关系,必须满足后一个元素的下标号应与前一个元素字符 串中的第三个数据相同。例如:若第一个位置总代码为A13,则第二个位置应根据A13中最后 的3,安排C35。即A与C可以交谈。以此类推。 用字符串处理函数COPY, 截取字符串的第一个字母作为宾客代码打印, 再取第三个字符, 用VAL将其转换成数字,将这个数字作为下标号,把这个下标号的元素安排在旁边(相邻);43 ④重复步骤③的方法,安排其后的元素,直到八个数据全部处理完为止。 Pascal程序: Program Exam54; const name : array[1..8]of string {定义字串类型数组并赋常量} =('A13','B27','C35','D41','E58','F62','G74','H86'); Var i, code: {整数类型} x: 1..8; {子界类型} s : {字符串类型} Begin s:=copy(name[1],1,1); {截取第一个元素字串的第一个字符} write(s:4); {确定第一个位置} s:=copy(name[1],3,1); {截取元素字串的第三个字符作为相邻} Val(s,x,code); {将字串s的值转换成数字存入 x} for i:=1 to 7 do {确定后面7个位置} Begin s:=copy(name[x],1,1); {找到相邻者的代码} write(s:4); {打印相邻者代码} s:=copy(name[x],3,1); {确定下一个相邻元素} Val(s,x,code); readln End. Pascal常用的字符串处理标准函数有7个: 设变量s, str, str1, str2均为字符串类型 (string) {多个字符} ch为字符类型 ; (char) {单个字符}; (1)copy(str,n,m)从字符串str的左边第n个开始截取m个字符; 如:copy(' Pascal '?,3,2)的结果为'sc?' ; (2)concat(str1,str2)将两个字串连接成为一个新的字串; 如:s:=str1+str2;同等于两串字符相加 (3)Length(str)求字串str的长度(字符个数); (4)chr(x) 求x(x为1?255整数)的ASII代码对应的字符; 如:chr(65)结果为 'A'。 (5)ord(ch)求字符ch对应的ASCII代码值;如 ord ( 'A' )结果为65; (6)pos(str1,str2)求字串str1在字串中开始的位置; 如: pos('sca','pascal')结果为3; (7)upcase(ch)将字符ch转为大写字母,如 upcase( 'a' )结果为'A' ; Pascal常用的字符串处理标准过程有4个: (1)Val(str,x,code)将数字型字串转为数字并存入变量x中; 如: Val(‘768’,x,code),x值为768, code为检测错误代码, 若code=0表示没有错误; (2)str(n,s)将数字n转化为字串存入s中,如str(768,s)s的结果为 ' 768' ; (3)insert(str1,str2,n)把字串str1插入在字串str2的第n个字符之前,结果在str244 中;{此过程中的str2为变量形参,具有传入传出的功能}; (4)delete(str,n,m)从字串str的第n个开始,删除m个字符,把剩余的字符存在str 中,{此过程中的str为变量形参,具有传入传出的功能}; [例5.5]一个两位以上的自然数,如果左右数字对称,就称为回文数,编程找出所有不 超过6位数字的回文数,同时又是完全平方数的数。 如121是回文数,又是11的平方,所以是完全平方数。 解:①不超过6位数的完全平方数用循环在10~999范围产生(for i:=10 to 999) ; ②将完全平方数 (i*i)转成字串类型存入s中; ③逐个取s的左右字符,检查是否相同(对称),检查对数不超过总长度的一半; ④如果是回文数,就调用打印过程(Print)。 Program Exam55; Var n, k, j ,t : s : {字符串类型 } i: {长整数类型 } Procedure P {打印过程(无形参)} begin write(s : 10); inc(t); {打印s, 用t 计数 } if t mod 6=0 then writeln {打印6个换行 } Begin t:=0; for i:=10 to 999 do begin str(i*i,s); {将完全平方数转换成字串 } k:=length(s); {计算字串长度 } n:=k div 2; {计算字串长度的一半 } j:=1; while j & = n do {取左右字符检查是否对称 } if copy(s,j,1) & & copy(s,k+1-j,1) then j:=1000 else inc( j ) ; {若不对称让j=1000,退出循环 } if j &1000 then Print { j &1000即是回文数,调打印 } writeln('Total=':8, t); {打印总个数 } readln End.习题5.1 1.裴波那契数列:数列1、1、2、3、5、8、13、21…称为裴波那契数列,它的特点是: 数列的第一项是1,第二项也是1,从第三项起,每项等于前两项之和。编程输入一个正整数45 N,求出数列的第N项是多少?(N不超过30)。 2.下面的竖式是乘法运算,式中P表示为一位的素数,编程输出此乘法竖式的所有可能 方案。xPPPP P PPPPP3.节目主持人准备从N名学生中挑选一名幸运观众,因为大家都想争当幸运观众,老师 只好采取这样的办法:全体同学排成一列,由前面往后面依顺序报数1,2,1,2,?,报单 数的同学退出队伍,余下的同学向前靠拢后再重新由前往后1,2,1,2,?报数,报单数者 退出队伍, 如此下去最后剩下一人为幸运观众。 编程找出幸运观众在原队列中站在什么位置 上?(N由键盘输入,N & 255)。 4. 05289,表明等式右边是一个七位的完全平方数,而这七个数字互不 相同。编程求出所有这样的七位数。 5. 校女子100米短跑决赛成绩如下表,请编程打印前八名运动员的名次、运动员号和成 绩。(从第一名至第八名按名次排列) 运动员号 017 168 088 105 058 123 142 055 113 136 020 032 089 010 成绩(秒) 12.3 12.6 13.0 11.8 12.1 13.1 12.0 11.9 11.6 12.4 12.9 13.2 12.2 11.4 6. 求数字的乘积根。正整数的数字乘积这样规定:这个正整数中非零数字的乘积。例 如整数999的数字乘积为9*9*9,得到729;729的数字乘积为7*2*9,得到126;126的数字乘 积为1*2*6,得到12;12从数字乘积为1*2,得到2。如此反复取数字的乘积,直至得到一位 数字为止。999的数字乘积根是2。编程输入一个长度不超过100位数字的正整数,打印出计 算数字乘积根的每一步结果。输出格式如下: (N=)
0 12 2 7. 有一组13个齿轮互相啮合,各齿轮啮合的齿数依次分别为6,8,9,10,12,14,15,16,18, 20,21,22,24, 问在转动过程中同时啮合的各齿到下次再同时啮合时,各齿轮分别转过了多 少圈? 8. 集合M的元素的定义如下: (1) 数1属于M; (2) 若X属于M, 则A=2X+1, B=3X+1, C=5X+1, 也属于M; (3) 再没有别的数属于M。(M={1,3,4,6,7,9,10,13,15,16...,如果M中的元素是按 递增次序排列的,求出其中的第201,202和203个元素。 9. 一个素数,去掉最高位,剩下的数仍是素数;再去掉剩下的数的最高位,余留下来的数 还是素数,这样的素数叫纯粹素数。求所有三位数的纯粹素数。 2 2 2 2 10. 自然数4,9,16,25等叫做完全平方数,因为2 =4, 3 =9, 4 =16,5 =25, 当某一对 自然数相加和相减, 有时可各得出一个完全平方数。 例如: 8与17这对自然数: 17+8=25 17―8= 946 试编程,找出所有小于100的自然数对,当加和减该数对时,可各得出一个完全平方数。第二节二维数组与枚举类型[例 5.6]假设四个商店一周内销售自行车的情况如下面表一所示, 自行车牌号 第一商店 第二商店 第三商店 第四商店 永久牌 35 20 10 38 飞达牌 40 50 32 36 五羊牌 55 64 18 28表一 几种牌号自行车的单价如表二所示。求各店本周出售自行车的总营业额。 单价 永久牌 飞达牌 五羊牌 元 395 398 384表二 解:①把表一看成是由行(每个店占一行)与列(每种牌号占一列)共同构成的数据组, 按表格排列的位置顺序,用 A 数组表一各数据表示如下: A[1,1]=35 A[1,2]=40 A[1,3]=55 {第一行共三个数据} A[2,1]=20 A[2,2]=50 A[2,3]=64 {第二行共三个数据} A[3,1]=10 A[3,2]=32 A[3,3]=18 {第三行共三个数据} A[4,1]=38 A[4,2]=36 A[4,3]=28 {第四行共三个数据} A 数组有 4 行 3 列,每个数组元素由两个下标号表示,这样的数组称为二维数组。 ②表二的数据按排列顺序用 B 数组表示如下: B[1]=395 B[2]=398 B[3]=3

我要回帖

更多关于 人和电脑下象棋 的文章

 

随机推荐