Pascal现在还有人想学习吗?先给出一本不错的Pascal教程,ObjectPascal的教程我日后给出。
Pascal基础教程
第一课初识PASCAL语言……………………1
第二课赋值语句与简单的输出语句……………………5
第三课带格式的输出语句输入语句……………………12
第四课简单的分支结构程序设计……………………19
第五课if嵌套与case语句……………………23
第六课for循环……………………29
第七课while循环与repeat-until循环…………………30
第八课一维数组……………………35
第九课多维数组……………………39
第十课字符数组与字符串……………………45
第十一课枚举、子界、集合及记录类型……………………51
第十二课过程与函数……………………66
第十三课动态数据类型(指针类型)……………………76
第十四课文件……………………89
附录一Pascal中的字符串函数和数学函数………………111
附录二关于fillchar的使用和讨论……………………116
附录三程序的调试技巧……………………117
附录四Pascal的多种退出语句用法……………………123
第一课初识Pascal语言
信息学奥林匹克竞赛是一项益智性的竞赛活动,核心是考查选手的智力和使用计算机解题的能力。选手首先应针对竞赛中题目的要求构建数学模型,进而构造出计算机可以接受的算法,之后要写出高级语言程序,上机调试通过。程序设计是信息学奥林匹克竞赛的基本功,在青少年朋友参与竞赛活动的第一步必须掌握一门高级语言及其程序设计方法。
一、Pascal语言概述
PASCAL语言也是一种算法语言,它是瑞士苏黎世联邦工业大学的N.沃思(NiklausWirth)教授于1968年设计完成的,1971年正式发表。1975年,对PASCAL语言进行了修改,作为"标准PASCAL语言"。
PASCAL语言是在ALGOL60的基础上发展而成的。它是一种结构化的程序设计语言,可以用来编写应用程序。它又是一种系统程序设计语言,可以用来编写顺序型的系统软件(如编译程序)。它的功能强、编译程序简单,是70年代影响最大一种算法语言。
二、Pascal语言的特点
从使用者的角度来看,PASCAL语言有以下几个主要的特点:
⒈它是结构化的语言。PASCAL语言提供了直接实现三种基本结构的语句以及定义"过程"和"函数"(子程序)的功能。可以方便地书写出结构化程序。在编写程序时可以完全不使用GOTO语句和标号。这就易于保证程序的正确性和易读性。PASCAL语言强调的是可靠性、易于验证性、概念的清晰性和实现的简化。在结构化这一点上,比其它(如BASIC,FORTRAN77)更好一些。
⒉有丰富的数据类型。PASCAL提供了整数、实型、字符型、布尔型、枚举型、子界型以及由以上类型数据构成的数组类型、集合类型、记录类型和文件类型。此外,还提供了其它许多语言中所没有的指针类型。沃思有一个著名的公式:"算法+数据结构=程序"。指出了在程序设计中研究数据的重要性。丰富的数据结构和上述的结构化性质,使得PASCAL可以被方便地用来描述复杂的算法,得到质量较高的程序。
⒊能适用于数值运算和非数值运算领域。有些语言(如FORTRAN66,ALGOL60)只适用于数值计算,有些语言(如COBOL)则适用于商业数据处理和管理领域。PASCAL的功能较强,能广泛应用于各种领域。PASCAL语言还可以用于辅助设计,实现计算机绘图功能。
⒋PASCAL程序的书写格式比较自由。不象FORTRAN和COBOL那样对程序的书写格式有严格的规定。PASCAL允许一行写多个语句,一个语句可以分写在多行上,这样就可以使PASCAL程序写得象诗歌格式一样优美,便于阅读。
由于以上特点,许多学校选PASCAL作为程序设计课程中的一种主要的语言。它能给学生严格而良好的程序设计的基本训练。培养学生结构化程序设计的风格。但它也有一些不足之处,如它的文件处理功能较差等。三、Pascal语言程序的基本结构
任何程序设计语言都有着一组自己的记号和规则。PASCAL语言同样必须采用其本身所规定的记号和规则来编写程序。尽管不同版本的PASCAL语言所采用的记号的数量、形式不尽相同,但其基本成分一般都符合标准PASCAL的规定,只是某些扩展功能各不相同罢了。下面我们首先来了解Pascal语言的程序基本结构。
为了明显起见先举一个最简单的PASCAL程序例子:【例1】
从这个简单的程序可以看到:
⒈一个PASCAL程序分为两个部分:程序首部和程序体(或称分程序)。
⒉程序首部是程序的开头部分,它包括:⑴程序标志。用"program"来标识"这是一个PASCAL程序"。PASCAL规定任何一个PASCAL程序的首部都必须以此字开头。在turbopascal语言中,首部也可省略。⑵程序名称。由程序设计者自己定义,如例中的exam1。在写完程序首部之后,应有一个分号。
⒊程序体是程序的主体,在有的书本里也称"分程序"。程序体包括说明部分(也可省略)和执行部分两个部分。⑴说明部分用来描述程序中用到的变量、常量、类型、过程与函数等。本程序中第二行是"变量说明",用来定义变量的名称、类型。PASCAL规定,凡程序中用到所有变量、符号常量、数组、标号、过程与函数、记录、文件等数据都必须在说明部分进行定义(或称"说明")。也就是说,不允许使用未说明先使用。⑵执行部分的作用是通知计算机执行指定的操作。如果一个程序中不写执行部分,在程序运行时计算机什么工作也不做。因此,执行部分是一个PASCAL程序的核心部分。执行部分以"begin"开始,以"end"结束,其间有若干个语句,语句之间以分号隔开。执行部分之后有一个句点,表示整个程序结束。
⒋PASCAL程序的书写方法比较灵活。当然,书写不应以节省篇幅为目的,而应以程序结构清晰、易读为目的。在编写程序时尽量模仿本书中例题程序格式。
⒌在程序中,一对大括号间的文字称为注释。注释的内容由人们根据需要书写,可以用英语或汉语表示。注释可以放在任何空格可以出现的位置。执行程序时计算机对注释不予理睬。
四、TurboPascal语言系统的使用
目前,常用的Pascal语言系统有TurboPascal7.0与BorlandPascal7.0,下面我们就来学习TurboPascal7.0系统的使用。1.系统的启动
在运行系统目录下的启动程序TURBO.EXE,即可启动系统。屏幕上出现如图1所示的集成环境。
2.TurboPascal系统集成环境简介
最顶上一行为主菜单。中间蓝色框内为编辑窗口,在它个编辑窗口内可以进行程序的编辑。最底下一行为提示行,显示出系统中常用命令的快捷键,如将当前编辑窗口中文件存盘的命令快捷键为F2,获得系统帮助的快捷键为F1,等等。
3.新建程序窗口
按F10进行主菜单,选择FILE菜单,执行其中New命令。就可建立一个新的程序窗口(默认文件名为Noname00.pas或Noname01.pas等)。
4.程序的输入、编辑与运行
在当前程序窗口中,一行一行的输入程序。事实上,程序窗口是一个全屏幕编辑器。所以对程序的编辑与其它编辑器的编辑方法类似,这里不再重复。
当程序输入完毕之后,一般要先按Alt+F9(或执行compile菜单中compile命令)对程序进行编译。如果程序有语法错误,则会在程序窗口的第一行处显示第一个红色错误信息。若无语法错误,则窗口正中央会出现一个对话框,提示编译成功。接下来,我们可以运行程序了。程序的运行可以通过按ALT+R打开RUN菜单中的RUN命令,或直接按快捷键CTRL+F9。则可以在用户窗口中输出运行结果。通常在程序运行结束后系统回到Pascal系统的集成环境,因此要查看运行结果,要按ALT+F5将屏幕切换到用户屏幕。
5.程序的保存与打开
当我们想把程序窗口中的程序存入磁盘时,可以通过按F2键(或执行File菜单中的save命令)来保存程序。第一次保存文件时屏幕上会出现一个对话框要求输入文件名(默认扩展名为.pas)。
当我们要将磁盘上的程序文件中的PASCAL程序装入窗口时,可按F3(或执行File菜单中的Open命令)来装入程序,此时系统也会弹出一个对话框要求输入要打开的文件名,或直接在文件对话框列表中选择所要的文件,然后回到打开文件。
五、第一个程序
下面程序在运行时,会提示输入一个圆的半径,然后会在屏幕上画一个圆。按回车后程序结束回到程序窗口。
Programex1;Usesgraph;VarGm,Gd,R:integer;BeginGd:=0;Write('Pleaseentertheradius:');readln(R);Initgraph(Gm,Gd,'');Setcolor(Green);Circle(320,240,R);Readln;Closegraph;End.
注意,如果上面程序运行时会出现初始化图形错误,请将系统目录下BGI子目录EGAVGA.BGI和UNITS子目录中的Graph.tpu拷贝到系统目录下BIN目录即可。
请输入上面的程序,并练习将其存盘、打开与运行上面程序。
第二课赋值语句、输出语句
上节课,我们学习了Pascal语言的程序基本结构,在一个程序中,所有的操作都由执行部分来完成,而执行部分又都是由一个个语句组成的。因此,下面开始我们要学习pascal语言的基本语句,并且在学习过程中逐步学会程序设计的基本方法。这节课我们要学习两种语句,即赋值语句与输出语句。在语句学习之前我们要先了解一些pascal语言的基础知识。
一、常量、变量与算术表达式
(一)常量
在程序运行过程中,其值不能被改变的量称为常量。如123,145.88,'abc',true等。
⒈整型常量
整型常量采用我们平常使用的十进制整数表示。如138,0,-512等都是整型常量,而18.或18.0都不是整型常量。pascal中有一个标准标识符Maxint,它代表所使用的计算机系统允许的最大整型数,而最小的整型数即为-Maxint-1。
一个整型数据用来存放整数。TurboPascal支持五种预定义整型,它们是shortint(短整型)、integer(整型)、longint(长整型)、byte(字节型)和word(字类型),TurboPascal分别用相同的名字作为他们的表识符。每一种类型规定了相应的整数取值范围以及所占用的内存字节数。
类型数值范围占字节数格式shortint-128..1281带符号8位inteter-32768..327672带符号16位longint-2147483648..21474836474带符号32位byte0..2551带符号8位word0..655352带符号16位
TurboPascal规定了两个预定义整型常量表识符maxint和maxlonint,他们各表示确定的常数值,maxint为32767,maxlongint为2147483647,他们的类型分别是integer和longint。
⒉实型常量
实型常量包括正实数、负实数和实数零。pascal中表示实型常量的形式有两种。
⑴十进制表示法
这是人们日常使用的带小数点的表示方法。如0.0,-0.0,+5.61,-8.0,-6.050等都是实型常量,而0.,.37都不是合法的实数形式。
⑵科学记数法
科学记数法是采用指数形式的表示方法,如1.25×105可表示成1.25E+05。在科学记数法中,字母"E"表示10这个"底数",而E之前为一个十进制表示的小数,称为尾数,E之后必须为一个整数,称为"指数"。如-1234.56E+26,+0.268E-5,1E5是合法形式,而.34E12,2.E5,E5,E,1.2E+0.5都不是合法形式的实数。
无论实数是用十进制表示法还是科学表示法,它们在计算机内的表示形式是一样的,总是用浮点方式存储。
和整数相比,实数能表示的范围大得多,但值得注意的是实数的运算整数的运算速度慢且无法像整数那样精确表示,只能近似表示。
一个实型数据用类存放实数。TurboPascal支持五种预定义实型,它们是real(基本实型)、single(但精度实型)、double(双精度实型)、extended(扩展实型)、comp(装配实型),TurboPascal分别用相同的名字作为他们的表识符。每一种类型规定了相应的实数取值范围、所占用的内存字节数以及它们所能达到的精度。
类型数值范围占字节数有效位数real2.9e-39..1.7e38611..12single1.5e-45..3.4e3847..8double5.0e-324..1.7e308815..16extended3.4e-4932..1.1e49321019..20comp-2**63+1..2**63-1819..20
TurboPascal支持两种用于执行实型运算的代码生成模式:软件仿真模式和80x87浮点模式。除了real可以在软件仿真模式下直接运行以外,其他类型必须在80x87浮点模式下运行。
⒊字符常量
在Pascal语言中,字符常量是由单个字符组成,所有字符来自ASCII字符集,共有256个字符。在程序中,通常用一对单引号将单个字符括起来表示一个字符常量。如:'a','A','0'等。特殊地,对于单引号字符,则要表示成''''。对于ASCII字符集中,按每个字符在字符集中的位置,将每个字符编号为0-255,编号称为对应字符的序号。
4.布尔常量
布尔型常量仅有两个值,真和假,分别用标准常量名true和false表示。它们的序号分别为1和0。
5.符号常量
一个常量即可以直接用字面形式表示(称为直接常量,如124,156.8),也可以用一个标识符来代表一个常量,称为"符号常量"。但符号常量必须在程序中的说明部分定义,也就是说先定义,后使用。
定义符号常量的一般格式:
CONST<常量标识符>=<常量>
说明:常量说明部分以关键字const开头,后面的标识符为常量标识符,其中"="号后的常量为整数、实数、字符、字符串(字符、字符串常量在后面章节中将作介绍)。而且,在常量说明部分可以将几个常量说明成符号常量,共用一个关键字"const"。例如:
则在本程序中pi和zero作为符号常量,分别代表实数3.14159和整数0。也就是说,常量说明部分既定义了常量名及其值,又隐含定义了常量的类型。关于符号常量,应注意下列几点:
⑴符号常量一经定义,在程序的执行部分就只能使用该常量标识符,而不能修改其值。⑵使用符号常量比直接用数值更能体现"见名知义"的原则,也便于修改参数,故一个较好的程序中,应尽量使用符号常量,在执行部分基本上不出现直接常量。
(二)变量
变量代表了一个存储单元,其中的值是可变的,故称为变量。如游戏"魂斗罗"中玩者命的个数最初为3,当你死了一次命减少一,这里命的个数就是一个变量(或者说命的个数存储在一个存储单元中)。即在程序运行过程中,其值可以改变的量,称为变量。
变量有三个要素是:变量名、变量类型、变量值。
一个程序中可能要使用到若干个变量,为了区别不同的变量,必须给每个变量(存贮单元)取一个名(称为变量名),该变量(存贮单元)存放的值称为变量的值,变量中能够存放值的类型为变量的类型。例如"魂斗罗"游戏中用于存放"命"的变量,在游戏程序中的名字可取为N,它的类型为整型,游戏初始时这个变量的值为3。
1.变量名
用一个合法的标识符代表一个变量。如n,m,rot,total等都是合法变量名。在程序中用到的变量必须在说明部分加以说明,变量名应遵循自定义标识符的命名规则,并注quot;见名知义"的原则,即用一些有意义的单词作为变量名。
"自定义标识符"的命名规则为:自定义标识符必须以字母(包含下划线"_")开头,后面的字符可以是字母或数字。标识符长度不超过63个字符。
2.变量的类型
常量是有类型的数据,变量在某一固定时刻用来存放一个常量,因此也应有相应的类型。如整型变量用来存放整数,实型变量用来存放实数。
3.变量说明
在程序中若要使用变量,变量的名称及类型在程序的变量说明部分加以定义,变量的值则在程序的执行部分中才能赋给。
变量说明的一般格式:
VAR<变量标识符>[,<变量标识符>]:<类型>;(中括号内部分表示可省,下同)
其中VAR是pascal保留字,表示开始一个变量说明段,每个变量标识符或由逗号隔开的多个变量标识,必须在它的冒号后面说明成同一类型。一个程序中,可以说明许多不同类型的变量,每种类型变量之间用分号隔开,共用一个VAR符号。
例如:varage,day:integer;amount,average:real;
其中,Integer(整型)、Real(实型)是标准标识符,它们是"类型标识符",代表了确定的类型,如age和day被定义为整型变量,amount和average被定义为实型变量。一旦定义了变量,就确定了它的类型,也就是说,就确定了该变量的取值范围和对该变量所能进行的运算。
(三)算术表达式
⑴算术表达式的定义
pascal语言中的算术表达式是由符合pascal语法规定的运算对象(包括常量、变量、函数)、算术运算符、圆括号组成的有意义的式子。如:A+3.14159*5/8.4-Abs(-1123)
⑵算术运算符
常用的有以下6个算术运算符:
①+(加)②-(减)③*(乘)④/(实数除)得到结果为实型.如5.0/2.0=2.5,5/2=2.5,4/2=2.0而不等于2。⑤DIV(整除)DIV它要求除数和被除数均为整型,结果也为整型。如10DIV2=5,10DIV3=3,5DIV10=0.-15DIV4=-3。DIV运算只取商的整数部分,参与DIV运算的两个对象不能为实型。⑥mod(求余),也只能用于整数运算,结果为整数。例如:10mod4=2,-17mod4=-1,4mod(-3)=1,-4mod3=-1,即amodb=a-(adivb)*b。
(3)运算优先顺序
如果一个表达式里出现两个或两个以上的运算符,则必须规定它们的运算次序。pascal规定:
①表达式中相同优先级的运算符,按从左到右顺序计算;②表达式中不同优先级的运算符,按从高到低顺序计算;③括号优先级最高,从内到外逐层降低;在算术运算中运算符的优先顺序与数学上的四则运算一致,即"先乘除后加减"(注:"MOD"、"DIV"运算的优先级与"*"、"/"相同)。
二、赋值语句
变量既然代表一个存储单元,其值是可变的,那么其中的值是怎么提供的,又是怎么改变的呢?可以通过赋值语句来进行。
1、赋值语句的格式
变量名:=表达式;其中":="称为赋值号。
2、执行过程
计算机先计算赋值号右边表达式的值,然后将表达式的值赋给变量名代表的变量。如:A:=(9*8)-(2-1);A:=A+1
三、输出语句
输出语句的作用是将程序运算的结果输出到屏幕或打印机等输出设备。这里通常是指输出到屏幕。
(一)输出语句的两种格式
1、write语句格式Write(表达式1,表达式2,……);如:write(1,2,3,4);write(1.2,3.4,5);write('MynameisLiping');2、writeln语句格式:Write(表达式1,表达式2,……)或writeln
(二)输出语句的功能
计算机执行到某一输出语句时,先计算出输出语句中的每个表达式的值,并将每一个表达式的值一个接一个地输出到屏幕上。Write语句与writeln语句格式上都相似,但它们在功能上有所不同,两个语句的区别在于,write语句将其后括号中的表达式一个接一个输出后,没有换行。而writeln语句则在输出各个表达式的值后换行。
例如以下两个程序段的输出分别为:write(1,2,3,4);write(5,6);
输出为:123456writeln(1,2,3,4);write(5,6);
输出为:123456
四、应用例析
例1:某仓库5月1日有粮食100吨,5月2日又调进20吨,5月3日卖出库存的3分之二,5月4日又调进库存的3倍粮食,问该仓库从5月1日到5月4日期间每天的粮食分别是多少吨?(输出每天的库存量)分析:在这个问题中,主要要描述从5月1日到5月4日期间仓库的粮食库存量,且易知它是不断变化的。因此我们可以用一个变量A来描述仓库的粮食库存量。
程序可写如下:Programex1;VarA:integer;BeginA:=100;Writeln('5/1:',A);A:=A+20;Writeln('5/2:',A);A:=Adiv3;writeln('5/3:',A);A:=A*4;writeln('5/4:',A);Readln;End.
例2:有三个小朋友甲乙丙。甲有50粒糖果,乙有43粒糖果,两有13粒糖果。现在他们做一个游戏。从甲开始,将自己的糖分三份,自己留一份,其余两份分别给乙与丙,多余的糖果自己吃掉,然后乙与丙也依次这样做。问最后甲、乙、丙三人各有书多少粒糖果?
分析:这个问题中我们关心的是在游戏过程中每个小朋友的糖果个数,且他们所拥有的的糖果数是在变化的。因此可用a,b,c三个变量分别存放甲乙丙三个小朋友在某一时刻所拥有的糖果数。对于每人,分糖后,他的糖果数一定为原来的糖果数div3(因为分糖过程糖果的数目不一定都刚好分完,用整除恰恰可以表示多余的糖自己吃掉)。而其他两人则增加与这个小朋友现在拥有的一样的糖果。
程序可写如下:
programex2;varA,B,C:integer;beginA:=50;B:=43;C:=13;{初始时每个小朋友所拥有的糖果数}A:=Adiv3;B:=B+A;C:=C+A;{甲小朋友分糖果后,每个人拥有的糖果数变化情况}B:=Bdiv3;A:=A+B;C:=C+B;{乙小朋友分糖果后,每个人拥有的糖果数变化情况}C:=Cdiv3;A:=A+C;B:=B+C;{丙小朋友分糖果后,每个人拥有的糖果数变化情况}writeln('A=',A,'B=',B,'C=',C);{输出结果}readln;end.
注:上程序中倒数第三行中'A='表示一个字符串(即用一对单引号括起来的一串字符),对于字符串,输出字符串的内容(即引号内的所得字符,而引号不输出)。以上程序的运行结果为:A=51B=35C=16
练习二
1、已知某梯形的上底A=13,下底B=18,高H=9,求它的面积S。
2、某机关组织游泳比赛。将一堆西瓜分给前三名,把该堆西瓜中的一半又半个西瓜奖给第一名;剩下的一半又半个西瓜给第二名;把最后剩下的一半又半个西瓜给第三名,但每次分时并没切开任何一个西瓜,且刚好西瓜分完。问前三名各分到多少个西瓜
3、已知某圆的半径R=139,求该圆的周长C与面积S?
第三课带格式的输出语句及输入语句
一、写语句的输出格式
在pascal语言中输出数据时是可以按照一定格式的,对整数隐含的输出形式为按十进制数形式。对实数的输出,隐含的形式是科学记数法形式(如果不想用科学记数法输出而用小数形式输出,要自己另行定义)。
事实上,输出语句中的每个输出项中的表达式之后可以加上格式说明,若输出项后没有加格式说明,则数据按系统隐含的格式输出,还可加上一定格式符号按特定格式输出。
⒈隐含的输出格式
pascal语言为整型量、实型量、布尔型量和字符串(用一对单引号括起来的字符序列)规定了每种数据所占的宽度(即一个数据占几列),一个数据所占的宽度称为"场宽"或"字段宽"。系统给出的隐含场宽称为标准场宽。每一种pascal版本给定的标准场宽不尽相同。下表给出标准pascal和pc机上两种pascal版所规定的标准场宽。标准场宽━━━━━━━━━━━━━━━━━数据类型标准pascalTurbopascal─────────────────integer10实际长度real2217布尔型104或5字符串串长串长━━━━━━━━━━━━━━━━━在TurboPascal系统中,对于整型字符串的输出都是按数据本身长度输出,对于布尔型数据(只有True和False两种值),TRUE为4列,FALSE为5列,一律采用大写输出。而real型数据的输出时,则按17列输出,其中第一列为符号位,正号不显示,后四位为"E±nn",中间的12列为尾数部分。如:
writeln(sqrt(75));则输出□8.6602540379E+00。而writeln(sqrt(81));则输出□9.0000000000E+00。有时,在程序中往往根据实际情况,需要自己定义场宽。
⒉指定场宽
在写语句中输出项含有格式符号时,就是为了指定场宽。
⑴指定单场宽.
格式:write(表达式:N)或writeln(表达式:N),其中N为自然数,指定单场宽后,所有数据不再按标准场宽输出,而按指定场宽输出。若数据实际长度小于指定场宽时,则一律"向右靠齐,左留空格"。
如write(1234:8);write('abcdef':12)输出结果:□□□□1234□□□□□□abcdef
对于标准实型数据指定单场宽时,如果场宽大于标准场宽时,右靠齐按标准场宽格式输出17位,左留空格。若场宽小于标准场宽时,第一位仍为符号位,最后四位仍为"E±nn",中间部分为尾数显示部分。如果指定的宽度小于8位,则数据按8位格式"*.*E±nn"输出。
⑵指定双场宽
如果输出项是实数时,如果希望输出的实数不用科学记数法输出,而用小数形式输出,可以用指定双场宽方法输出。双场宽输出格式为:write(实型表达式:m:n),其中m和n都是自然数,m用以指定整个数据所占的宽度,n指定输出实数的小数位数。
如:write(sqrt(75):9:4);输出:□□□8.6602
如果双场宽不能满足输出数据的最低要求,系统自动突破指定的场宽限制,按实际长度输出。如:write(sqrt(75):5:4);要使小数点后有4位数字,而总场宽为5,是不可能的(因为还有一个小数点,小数点前面还有一个数字)。它最低限度要有6列,即输出为:8.6602
例1写出下列程序在turbopascal下的输出结果.
programex;consts='abcdefg';vari:integer;r:real;c:char;b:boolean;begini:=1234;r:=1234.5678;c:='#';b:=true;writeln(i,i:6,i:3);writeln(r,r:12:5,r:8:5);writeln(c,c:5);writeln(s,s:10,s:5);writeln(b,b:5,b:3);end.
运行结果如下:
1234□□12341234□1.2345678000E+03□□1234.567801234.56780#□□□□#abcdefg□□□abcdefgabcdefgTRUE□TRUETRUE
3.应用例析
例2:已知A=253,B=43,输出A*B的运算式子。即输出如下:
253*43=10879253*43759+101210879
分析:对于该问题,我们只要控制好输出时右靠齐即可。即前四行的总宽度一样(例如为12),第五行总宽度比前面少1。第六、七行总宽度与前四行一样。参与程序如下:
vara,b:integer;begina:=253;b:=43;writeln(a:10,'*',b,'=',a*b);writeln(a:12);write('*':8);writeln(b:4);writeln('--------':12);writeln(a*3:12);write('+':6);writeln(a*4:5);writeln('--------':12);writeln(a*b:12);end.
二、输入语句(读语句)在程序中变量获得一个确定的值,固然可以用赋值语句,但是如果需要赋值的变量较多,或变量的值经常变化,则使用本节介绍的输入语句──读语句,将更为方便。读语句是在程序运行时由用户给变量提供数据的一种很灵活的输入动作,它有两种格式:
1.读语句的一般格式:
read(<变量名表>);readln[(<变量名表>)];
其中变量名表是用逗号隔开的若干个变量名组成的。功能:从标准输入文件(即INPUT,一般对应着键盘)中读入数据,并依次赋给相应的变量。说明:①read和readln是标准过程名,它们是标准标识符。②执行到read或readln语句时,系统处于等待状态,等待用户从键盘上输入数据,系统根据变量的数据类型的语法要求判断输入的字符是否合法。如执行read(a)语句,a是整型变量,则输入的字符为数字字符时是合法的,当输入结束时,则自动将刚接受的一串数字字符转换为整数赋给变量a。③在输入数值型(整型或实型)数据时,数据间要用空格或回车分隔开各个数据,输入足够个数的数据,否则仍要继续等待输入,但最后一定要有回车,表示该输入行结束,直到数据足够,该读语句执行结束,程序继续运行。
例3.设a、b、c为整型变量,需将它们的值分别赋以10,20,30,写出对应下列语句的所有可能输入格式。Read(a,b,c);
解根据③,即可列出所有可能输入格式(a)10□20□30←┘(b)10□20←┘30←┘(c)10←┘20□30←┘(d)10←┘20←┘30←┘其中"←┘"表示回车键。下同。
④read语句与readln语句的第一个区别是:read语句是一个接一个地读数据,在执行完本Read语句(读完本语句中变量所需的数据)后,下一个读语句接着从该数据输入行中继续读数据,也就是说,不换行。如:
Read(a,b);Read(c,d);Read(e);
如果输入数据行如下:
1□2□3□4□5□6□←┘
则a,b,c,d,e的值分别为1,2,3,4,5,如果后面无读语句则数据6是多余的,这是允许的。Readln则不同,在读完本Readln语句中变量所需的数据后,该数据行中剩余的数据多余无用,或者说,在读完本Readln语句中变量所需数据后,一定要读到一个回车,否则多余的数据无用。
例4设要达到例1同样的目的,但语句改为:readln(a,b);readln(c)则例3中的4种输入格式只有(b)(d)是有效的.
⑤readln语句与read语句的第二个区别是:read后一定要有参数表,而readln可以不带参数表,即可以没有任何输入项,只是等待读入一个换行符(回车)。经常用于暂停程序的运行,直到输入一个回车。例5设有下列语句:read(a,b,c);readln(d,e);readln;readln(f,g);
其中,所有变量均为整型。再设输入的数据如下:1□2←┘3□4□5□6□7□8←┘9□10←┘11←┘12□13←┘
列表给出每个变量的值.
分析:可以假想有一"数据位置指针",每读一个数据后,指针后移到该数据之后,每执行一个readln语句后,指针移到下一个数据行的开头。各变量的值如下表所示。
━━━━━━━━━━━━━━━━━━━━━━━━━━变量名abcdefg──────────────────────────值123451112──────────────────────────⑥为了避免可能出现的错误,建议在程序中按下列原则使用读语句:(A)如果没有特殊需要,在一个程序中尽量避免混合使用read语句和readln语句;(B)尽量用readln语句来输入数据,一个数据行对应一个readln语句;(C)由于执行read或readln语句时,系统不会提供任何提示信息,因此,编程时最好在readln语句之前加以适当提示,例如:
write('Inputa,b,c:');readln(a,b,c);在执行时,屏幕上显示:Inputa,b,c:■其中,"■"为光标。执行readln语句后,系统处于待待输入状态,只有输入了所需数据后才继续往下执行。
三、顺序结构程序设计
到目前为止,我们可以用读、写语句和赋值语句编写一些简单的程序。通过阅读这些程序,可以逐步熟悉pascal程序的编写方法和应遵循的规则,为以后各章的学习打基础。例6试编一程序,输入一梯形的上底、下底、高,求该梯形的面积。分析:整个程序分为三段:输入、计算、输出。程序中用a,b,h三个变量分别存放梯形的上、下底与高,S存放面积。要而使用这些变量都要先说明,程序的执行部分中先输入上、下底与高,接着求面积S,最后输出结果S。
源程序如下:programTixing;{程序首部}vara,b,h,s:real;{程序说明部分}beginwrite('Inputa,b,h:');readln(a,b,h);{程序执行部分}s:=(a+b)*h/2;write('s=',s:10:3);end.
例7某幼儿园里,有5个小朋友编号为1,2,3,4,5,他们按自己的编号顺序围坐在一张圆桌旁。他们身上都有若干个糖果,现在他们做一个分糖果游戏。从1号小朋友开始,将他的糖果均分三份(如果有多余的,则他将多余的糖果吃掉),自己留一份,其余两份分给他的相邻的两个小朋友。接着2号、3号、4号、5号小朋友也这如果做。问一轮后,每个小朋友手上分别有多少糖果。
分析:这道问题与第二课中的例2基本一样,只不过这里有5位小朋友,且他们初始时糖果的数目不确定。这里用a,b,c,d,e分别存放5个小朋友的糖果。初始时它们的值改为由键盘输入。其它都与第二课中的例2类似。参考程序如下:
programfentang;vara,b,c,d,e:integer;beginwrite('PleaseEnterinitnumbers');readln(a,b,c,d,e);a:=adiv3;b:=b+a;e:=e+a;{1号均分后,1、2、5号的糖果数变化情况}b:=bdiv3;c:=c+b;a:=a+b;{2号均分后,1、2、3号的糖果数变化情况}c:=cdiv3;b:=b+c;d:=d+c;{3号均分后,2、3、4号的糖果数变化情况}d:=ddiv3;c:=c+d;e:=e+d;{4号均分后,3、4、5号的糖果数变化情况}e:=ediv3;d:=d+e;a:=a+e;{5号均分后,4、5、1号的糖果数变化情况}{输出结果}writeln('a=',a);writeln('b=',b);writeln('c=',c);writeln('d=',d);writeln('e=',e);readln;{暂停}end.
例8编一程序求半径为R的圆的周长与面积分析:程序要先输入半径R,然后求周长c和面积s,最后输出c和s.源程序如下:
programcircle;constPI=3.14159;varr,c,s:real;beginwrite('EnterR=');readln(r);c:=2*pi*r;s:=pi*sqr(r);writeln('c=',c:10:2);writeln('s=',s:10:2);end.在程序中,为了输出实型周长C和面积S时,按照小数形式输出,采用了指定双场宽格式。
练习三
1.编一程序,将摄氏温度换为华氏温度。公式为:
其中f为华氏温度,c是摄氏温度。
2.编一程序,输入三角形的三边a、b、c(假设这三边可以构成一个三角形),求三角形的面积S?(提示:可利用海伦公式
第四课简单的分支结构程序设计
在现实生活中,我们每天都要进行根据实际情况进行选择。例如,原打算明天去公园,但如果明天天气不好,将留在家里看电视。所以人也会根据条件进行行为的选择。计算机也会根据不同情况作出各种逻辑判断,进行一定的选择。在这课与下一课中,我们将会发现,我们是通过选择结构语句来实现程序的逻辑判断功能。
一、PASCAL中的布尔(逻辑)类型
在前面,我们学习了整型(integer)与实型(real)。其中integer型数据取值范围为-32768到32767之间所有整数。而real型数据取值范围为其绝对值在10-38到1038之间的所有实数。它们都是数值型的(即值都为数)。布尔型(Boolean)是一种数据的类型,这种类型只有两种值,即"真"与"假"。
1、布尔常量
在Pascal语言中"真"用ture表示,"假"用False表示。所以布尔类型只有TRUE与FALSE两个常量。
2、布尔变量(BOOLEAN)
如果我们将某些变量说明成布尔型,那么这些变量就是布尔变量,它们只能用于存放布尔值(ture或false)。例如,VARA,B:BOOLEAN;
3、布尔类型是顺序类型
由于这种类型只有两个常量,Pascal语言中规定ture的序号为1,false的序号为0。若某种类型的常量是有限的,那么这种类型的常量通常都有一个序号,我们称这种类型为顺序类型。如前面我们学过的整型(integer),以及后面要学到的字符型(char)都是顺序类型。
4、布尔类型的输入与输出
a)输出VARA,B:BOOLEAN;BEGINA:=TRUE;B:=FALSE;WRITELN(A,B);END.TRUEFALSE
b)布尔类型变量不能直接用读语句输入布尔类型变量不能通过读语句给它们提供值。事实上,我们可以通过间接方式对布尔变量进行值的输入。
例如,以下程序是错误的:vara,b,c:Boolean;beginreadln(a,b,c);{错误语句}writeln(a,b,c);end.
二、关系表达式与布尔表达式
1、什么是关系表达式用小括号、>、<、>=、<=、=、<>将两个算术表达式连接起来的式子就称为关系表达式(比较式)。如:3+7>8,x+y<10,2*7<=13等都是关系表达式。
2、关系表达式的值
很显然,这几个关系表达式中第一个是正确的,第三个是错误的,而第二个表达式可能是对的,也可能是错的。所以我们很容易发现,这些表达式的值是"对"的或"不对"的(或者说,是"真"的或"假"的),即关系表达式的值为布尔值。表示该比较式两端式子的大小关系是否成立。如3+2>6是错的,故它的值为FALSE。同样,45>=32是对的,故该表达式的值为true。
关系表达式用于表示一个命题。如:"m为偶数"可表示为:mmod2=0。"n为正数"可表示为:n>0。
3.布尔运算及布尔表达式
为了表示更复杂的命题,Pascal还引入三种逻辑运算符:not、and、or。它们分别相当于数学上的"非"、"且"和"或"的意义。
这三个运算符的运算对象为布尔量,其中not为单目运算,只有一个运算对象,and与or为双目运算,有两个运算对象。它们的运算真值表如下:
a
b
Nota
aandb
aorb
axorb
false
true
ture
于是,对于一个关系表达式,或多个关系表达式用布尔运算符连接起来的式子就称为布尔表达式。布尔表达式的值也为布尔值。
如果一个表达式里出现两个或两个以上的运算符,则必须规定它们的运算次序。pascal规定:①表达式中相同优先级的运算符,按从左到右顺序计算;②表达式中不同优先级的运算符,按从高到低顺序计算;③括号优先级最高,从内到外逐层降低;
对于一个复杂的表达式可能同时包含算术运算、关系运算和逻辑运算以及函数运算。运算的优先顺序为:括号à函数ànotà*、/、div、mod、andà+、-、or、xorà关系运算。对于复杂的命题,我们可以用布尔表达式来表示。例如,命题:"m,n都是偶数或都是奇数"可表示为"(mmod2=0)and(nmod2=0)or(mmod2=1)and(nmod2=1)"。
三、简单的IF语句
1、格式
Ⅰ、IF<布尔表达式>THEN语句;Ⅱ、IF<布尔表达式>THEN语句1ELSE语句2;(注意Ⅱ型IF语句中语句1后无";"号)
2、功能Ⅰ、执行IF语句时,先计算<布尔表达式>的值,若为TRUE则执行语句,否则不执行任何操作。Ⅱ、执行IF语句时,先计算<布尔表达式>的值,若为TRUE则执行语句1,否则执行语句2;
3、示例
1)例4.2输入一个整数a,判断是否为偶数。(是输出"yes"否则输出"no")。
Programex4_2;Vara:integer;BeginWrite('a=');readln(a);If(amod2=0)thenwriteln('yes')Elsewriteln('no');Readln;End.
2)华榕超市里卖电池,每个电池8角钱,若数量超过10个,则可打75折。
Programex4_3;VarNum:integer;Price,Total:real;BeginWrite('Num=');readln(Num);Price=0.8;IfNum>10thenPrice:=Price*0.75;Total:=Num*Price;Writeln('Total=',Total:0:2);Readln;End.
3)编写一与电脑猜"红"或"黑"的游戏。
分析:用1代表红,0代表黑。先由计算机先出答案,然后再由人猜,猜对输出"YOUWIN"否则输出"YOULOST"。为了模拟猜"红"或"黑"的随意性,程序中需要用到随机函数random(n)。
函数是什么呢,例如大家都知道|-2|=2,|58|=58,那么|x|=。
如果我们用y表示|x|,那么.这里y=|x|就是一个函数,也就是说函数是一个关于一个或多个自变量(未知量,如上例中的x)的运算结果。
在pascal语言中,系统提供了许多内部函数,其中包括|x|函数,当然它用abs(x)表示。我们如果要求x2-y的绝对值,可以调用内部函数abs(x*x-y)即可求得。Random(n)也是一个内部函数,调用它能得到0~n-1之间的整数(但它不确定的,或说是随机的)。同时由于函数是一个运算结果,所以函数的调用只能出现在表达式中。
Programex4_3;Usescrt;VarComputer,People:integer;BeginRandomize;Computer:=random(2);Write('Youguess(0-Red1-Black):');readln(People);IfPeople=Computerthenwriteln('YOUWIN')Elsewriteln('YOULOST');Readln;End.
作业:.某车站行李托运收费标准是:10公斤或10公斤以下,收费2.5元,超过10公斤的行李,按每超过1公斤增加1.5元进行收费。试编一程序,输入行李的重量,算出托运费。
第五课if嵌套与case语句
练习
1.输入三角形的三个边,判断它是何类型的三角形(等边三角形?等腰三角形?一般三角形?)。2.输入三个数,按由大到小顺序打印出来。3.计算1901年2099年之间的某月某日是星期几。4.输入两个正整数a,b。b最大不超过三位数,a不大于31。使a在左,b在右,拼接成一个新的数c。例如:a=2,b=16,则c=216;若a=18,b=476,则c=18476。提示:求c的公式为:c=a×K+b其中:
第六课for循环语句
1.求s=1+4+7+…+298的值。2.编写一个评分程序,接受用户输入10个选手的得分(0-10分),然后去掉一个最高分和一个最低分,求出某选手的最后得分(平均分)。3.用一张一元票换1分、2分和5分的硬币,每种至少一枚,问有哪几种换法(各几枚)?
第七课WHILE循环与REPEAT
1、输入一个正整数n,将n分解成质因数幂的乘积形式。例如:36=22*322、输出如下图形。3、编写一程序,验证角谷猜想。所谓的角谷猜想是:"对于任意大于1的自然数n,若n为奇数,则将n变为3*n+1,否则将n变为n的一半。经过若干次这样的变换,一定会使n变为1。"4.有一堆100多个的零件,若三个三个数,剩二个;若五个五个数,剩三个;若七个七个数,剩五个。请你编一个程序计算出这堆零件至少是多少个?
第八课一维数组
一、为什么要使用数组例1输入50个学生的某门课程的成绩,打印出低于平均分的同学号数与成绩。分析:在解决这个问题时,虽然可以通过读入一个数就累加一个数的办法来求学生的总分,进而求出平均分。但因为只有读入最后一个学生的分数以后才能求得平均分,且要打印出低于平均分的同学,故必须把50个学生的成绩都保留下来,然后逐个和平均分比较,把高于平均分的成绩打印出来。如果,用简单变量a1,a2,…,a50存放这些数据,可想而知程序要很长且繁。要想如数学中使用下标变量ai形式表示这50个数,则可以引入下标变量a[i]。这样问题的程序可写为:tot:=0;{tot表示总分}fori:=1to50do{循环读入每一个学生的成绩,并累加它到总分}beginread(a[i]);tot:=tot+a[i];end;ave:=tot/50;{计算平均分}fori:=1to50doifa[i] 即typearraytype=array[1..8]ofinteger;vara1,a2:arraytype;相当于vara1,a2:array[1..8]ofinteger;一般我们使用第二种定义方法。 当在说明部分定义了一个数组变量之后,pascal编译程序为所定义的数组在内存空间开辟一串连续的存储单元。例如,设程序中有如下说明:vara:array[1..8]ofinteger;则pascal编译程序就在内存中定义了如下一串变量:a[1]、a[2]a[3]a[4]a[5]a[6]a[7]a[8]这个数组变量。2、一维数组的引用当定义了一个数组,则数组中的各个元素就共用一个数组名(即该数组变量名),它们之间是通过下标不同以示区别的。对数组的操作归根到底就是对数组元素的操作。 一维数组元素的引用格式为:数组名[下标表达式]说明:①下标表达式值的类型,必须与数组类型定义中下标类型完全一致,并且不允许超越所定义的下标下界和上界。②数组是一个整体,数组名是一个整体的标识,要对数组进行操作,必须对其元素操作。数组元素可以象同类型的普通变量那样作用。如:a[3]:=34;是对数组a中第三个下标变量赋以34的值。read(a[4]);是从键盘读入一个数到数组a第4个元素中去。 例4输入一个不超过30000的正整数,按从低位到高位输出每一位上的数字。如:输入2645,输出5462分析:对2645,先以2645mod10取出个位数,放到a[1]中,以2645div10得到剩下的数264,依次类推,再以264mod10得到十位数4,放到a[2]中,以264div10得到剩下的数26,再以26mod10得到百位数6,放到a[3]中,以26div10得到剩下的数2,以2mod10得到千位数2,以2div10得到剩下的数为0。程序结束。程序如下:programex5_4vara:array[1..10]ofinteger;n,i,k:integer;{n为输入的任意正整数,k为n的位数}beginreadln(n);k:=0;whilen>0do{从低位向高位取出n的每一位数,放到数组a中}begink:=k+1;a[k]:=nmod10;n:=ndiv10;end;fori:=1tokdo{输出数组a中的每一个元素的值}write(a[i],’’);end. 2.输入10个数,输出大于6的个数。 3.输入一个不超过30000的正整数,输出所有位上数字的和。例:输入2546,输出17。即2+5+4+6=17 4.输入一串小写字母(以"."为结束标志),统计出每个字母在该字符串中出现的次数(若某字母不出现,则不要输出)。例:输入:aaaabbbccc.输出:a:4b:3c:35.输入一个不大于32767的正整数N,将它转换成一个二进制数。例如:输入:100输出:11001006.输入一个由10个整数组成的序列,其中序列中任意连续三个整数都互不相同,求该序列中所有递增或递减子序列的个数。例如:输入:11085932674输出:6对应的递增或递减子序列为:11010855993226774 第九课多维数组 四、数组类型的应用例3输入一串字符,字符个数不超过100,且以"."结束。判断它们是否构成回文。分析:所谓回文指从左到右和从右到左读一串字符的值是一样的,如12321,ABCBA,AA等。先读入要判断的一串字符(放入数组letter中),并记住这串字符的长度,然后首尾字符比较,并不断向中间靠拢,就可以判断出是否为回文。源程序如下:programex5_5;varletter:array[1..100]ofchar;i,j:0..100;ch:char;begin{读入一个字符串以'.'号结束}write('Inputastring:');i:=0;read(ch);whilech<>'.'dobegini:=i+1;letter[i]:=ch;read(ch)end;{判断它是否是回文}j:=1;while(j=ithenwriteln('Yes.')elsewriteln('No.');end. 例4奇数阶魔阵魔阵是用自然数1,2,3…,n2填n阶方阵的各个元素位置,使方阵的每行的元素之和、每列元素之和及主对角线元素之和均相等。奇数阶魔阵的一个算法是将自然数数列从方阵的中间一行最后一个位置排起,每次总是向右下角排(即Aij的下一个是Ai+1,j+1)。但若遇以下四种情形,则应修正排数法。(1)列排完(即j=n+1时),则转排第一列;(2)行排完(即i=n+1时),则转排第一行;(3)对An,n的下一个总是An,n-1;(4)若Aij已排进一个自然数,则排Ai-1,j-2。例如3阶方阵,则按上述算法可排成:438951276 有了以上的算法,解题主要思路可用伪代码描述如下:1indiv2+1,yn/*排数的初始位置*/2a[i,j]1;3fork:=2tonndo4计算下一个排数位置(i,j);5ifa[i,j]<>0then6ii-1;7jj-2;8a[i,j]k;9endfor对于计算下一个排数位置,按上述的四种情形进行,但我们应先处理第三处情况。算法描述如下:1if(i=n)and(j=n)then2jj-1;/*下一个位置为(n,n-1)*/;3else4iimodn+1;5jjmodn+1;6endif;源程序如下:programex5_7;vara:array[1..99,1..99]ofinteger;i,j,k,n:integer;beginfillchar(a,sizeof(a),0);write('n=');readln(n);i:=ndiv2+1;j:=n;a[i,j]:=1;fork:=2ton*ndobeginif(i=n)and(j=n)thenj:=j-1elsebegini:=imodn+1;j:=jmodn+1;end;ifa[i,j]<>0thenbegini:=i-1;j:=j-2;end;a[i,j]:=k;end;fori:=1tondobeginforj:=1tondowrite(a[i,j]:5);writeln;end;end. 练习:1、输入N个同学的语、数、英三科成绩,计算他们的总分与平均分,并统计出每个同学的名次,最后以表格的形式输出。2、输出杨辉三角的前N行(N<10)。111121133114641 第十课字符与字符串处理 TurboPascal提供了八个标准函数和标准过程,见下表,利用这些标准函数与标准过程,一些涉及到字符串的问题可以灵活解决。 函数和过程名 功能 说明 copy(s,m,n) 取s中第m个字符开始的n个字符 若m大于s的长度,则返回空串;否则,若m+n大于s的长度,则截断 length(s) 求s的动态的长度 返回值为整数 pos(sub,s) 在s中找子串sub 返回值为sub在s中的位置,为byte型 insert(sour,s,m) 在s的第m个字符位置处插入子串sour 若返回串超过255,则截断 delete(s,m,n) 删除s中第m个字符开始的n个字符串 若m大于s的长度,则不删除;否则,若m+n大于s的长度,则删除到结尾 Str(x[:w[:d]],s) 将整数或实数x转换成字符串s w和d是整型表达式,意义同带字宽的write语句 val(s,x,code) 将字符串S转换成整数或实数x 若S中有非法字符,则code存放非法字符在S中的下标;否则,code为零。code为整型 upcase(ch) 将字母ch转换成大写字母 若ch不为小写字母,则不转换 分析:程序中,输入要查找的字符串及要置换的字符串,充分用上了字符串处理的标准过程delete、insert及标准函数pos。 第十一课枚举、子界、集合及记录类型 在前面几章中我们用到了整型、实型、布尔型、字符型的数据。以上数据类型是由pascal规定的标准数据类型,只要写integer,real,boolean,char,pascal编译系统就能识别并按这些类型来处理。pascal还允许用户定义一些类型,这是其它一些语言所没有的,这就使得pascal使用灵活、功能丰富。 三、集合类型 1.一家水果店出售四种水果,每公斤的价格是:苹果1.50元,桔子1.80元,香蕉2.0,菠萝1.60元。编一个程序,使售货员只要从键盘输入货物的代码及重量,计算机便能显示货物的名称、单价、重量及总价。2.输入一个英语句子,以句号.为结束标志,统计句子中元音字母出现的次数,把句子所有辅音字母组成一个集合,并把这些辅音字母打印出来。3.编程序建立某班25人的数学课程成绩表,要求用数组类型和记录类型,其成绩表格式如下:姓名性别平时成绩期中考试期终考试总评成绩张良男908592王心男708271……李英女828475其中总评成绩=平时成绩×20%+期中考试×30%+期终考试×%50。 4.输入五个学生的出生日期(月/日/年)和当天的日期,然后用计算机计算出每个人到当天为止的年龄各是多少(如某人1975年10月1日出生,今天是94年12月1日,则他的年龄应为19岁,而另一人的出生日期为76年12月30日,则他的年龄为17岁。) 第十二课过程与函数 begint:=6;whilet<=60dobegint1:=1;repeatt1:=t1+2;untilprime(t1)andprime(t-t1);writeln(t,'=',t1,'+',t-t1);t:=t+2;end;end. 例6编写一个给一个分数约分的程序。源程序如下:programex7_6;┌──变量参数vara,b:integer;↓procedurecommon(varx,y:integer);vari,j,k:integer;begin{求x,y的最大公约数}i:=x;j:=y;repeatk:=imodj;i:=j;j:=k;untilk=0;{对x,y进行约分}x:=xdivi;y:=ydivi;end;beginwrite('Inputa,b=');readln(a,b);common(a,b);writeln(a,b:5);end.如输入:Inputa,b=128则输出:32 1.输入5个正整数求它们的最大公约数。(提示:可用一个数组将5个数存放起来,然后求第一个数和第二个数的公约数,再求第三个数与前两个数公约数的公约数,这样求得前三个整数最大公约数……如此类推可求出5个整数的最大公约数)2.给一维数组输入任意6个整数,假设为:748915请建立一个具有以下内容的方阵:748915489157891574915748157489574891(请用子程序编写)。3.求两个正整数的最小公倍数。4.输入一个任意位的正整数,将其反向输出。5.有五位同学,其各科成绩如下:学号数学语文英语总分名次110897902988810031004389484635059787100(1)编写一个过程enter,输入每个学生成绩并计算各人的总分。(2)编写过程minci,用以排出每个人的名次。(3)按学号顺序输出。 第十三章动态数据类型 前面介绍的各种简单类型的数据和构造类型的数据属于静态数据。在程序中,这些类型的变量一经说明,就在内存中占有固定的存储单元,直到该程序结束。程序设计中,使用静态数据结构可以解决不少实际问题,但也有不便之处。如建立一个大小未定的姓名表,随时要在姓名表中插入或删除一个或几个数据。而用新的数据类型──指针类型。通过指针变量,可以在程序的执行过程中动态地建立变量,它的个数不再受限制,可方便地高效地增加或删除若干数据。 (a)编译时给(b)执行New(p)后(c)(b)的简略表示p分配空间生成新单元表示值不定新单元的地址为XXXX内存单元示意图 ②一个指针变量只能存放一个地址。如再一次执行New(p)语句,将在内存中开辟另外一个新的整型变量存储单元,并把此新单元的地址放在p中,从而丢失了原存储单元的地址。③当不再使用p当前所指的存储单元时,可以通过标准过程Dispose释放该存储单元。⒉释放动态存储单元dispose语句的一般格式:dispose(指针变量)功能:释放指针所指向的存储单元,使指针变量的值无定义。(三)动态存储单元的引用在给一个指针变量赋以某存储单元的地址后,就可以使用这个存储单元。引用动态存储单元一般格式:<指针变量>^说明:①在用New过程给指针变量开辟了一个它所指向的存储单元后,要使用此存储单元的唯一方法是利用该指针。②对动态存储单元所能进行的操作是该类型(指针的基类型)所允许的全部操作。例1设有下列说明:varp:^integer;i:integer;画出执行下列操作后的内存示意图:New(p);P^:=4;i:=p^;解:如下图所示。(a)编译时(b)执行New语句(c)执行P^:=4(d)执行i:=P^分配存储单元内存单元示意图 练习1、围绕着山顶有10个洞,一只兔子和一只狐狸各住一个洞,狐狸总想吃掉兔子。一天兔子对狐狸说,你想吃我有一个条件,你先把洞编号1到10。你从第10号洞出发,先到第1号洞找我,第二次隔一个洞找我,第三次隔两个洞找我,以后依次类推,次数不限。若能找到我,你就可以饱餐一顿,在没找到我之前不能停止。狐狸一想只有10个洞,寻找的次数又不限,哪有找不到的道理,就答应了条件。结果就是没找着。利用单链环编程,假定狐狸找了1000次,兔子躲在哪个洞里才安全。2、某医院病房的订位管理中,将病人的记录按姓名的字母顺序排成一个链表。试编写程序,从键盘上输入下列字母,就可对病员记录进行管理:(1)i───新病人入院(插入一个病员记录)。(2)d───病人出院(删除一个病员记录,并显示该记录)。(3)s───查询某病员记录(显示该记录或"未找到")。(4)q───在屏幕上列出所有的病员记录并结束程序。 3、编写一个简单的大学生新生入校登记表处理程序。 第十四课文件 例5读入一个行长不定的文本文件。排版,建立一个行长固定为60个字符的文件,排版要求:(1)当行末不是一个完整单词时,行最后一个字符位用'-'代替,表示与下一行行头组成完整的单词;(2)第一行行头为两个空格,其余各行行头均不含有空格。分析(1)建立原始数据文件。(2)程序边读入原始数据文件内容,边排版。(3)每排完一行行长为60字符,并符合题中排版条件,写入目标文件中。设原始数据TEXTCOPY.DAT文件内容如下:Pavelwasarrested.ThatdatMotherdidnotlightthestove.Eveningcameandacoldwindwasblowing.Therewasaknockatthewindow.Thenanother.Motherwasusedtosuchknocks,butthistimeshegavealittlestartofjoy.Throwingashawloverhershoulders,sheopenedthedoor.程序:对TEXTCOPY.DAT文本文件运行程序得到排版结果文件TEXTCOPY.RES内容如下:Pavelwasarrested.ThatdatMotherdidnotlightthestov-eveningcameandacoldwindwasblowing.Therewasaknockatthewindow.Thenanother.Motherwasusedtosuchknocks,b-utthistimeshegavealittlestartofjoy.Throwingashawloverhershoulders,sheopenedthedoor. 例7产生数1-16的平方、立方、四次方表存入有类型文件中,并用顺序的方式访问一遍,用随机方式访问文件中的11和15两数及相应的平方、立方、四次方值。分析:建立有类型文件文件名为BIAO.FIL,文件的类型为实数型。(1)产生数1-16及其平方、立方、四次方值,写入BIAO.FIL,并顺序读出输出;(2)用SEEK指针分别指向11和15数所在文件的位置,其位置数分别为10×4和14×4(注意文件的第一个位置是0),读出其值及相应的平方、立方、四次方值输出。程序:程序运行结果如下:另外,TurboPascal还提供了第三种形式文件即无类型文件,无类型文件是低层I/O通道,如果不考虑有类型文件、文本文件等存在磁盘上字节序列的逻辑解释,则数据的物理存储只不过是一些字节序列。这样它就与内存的物理单元一一对应。无类型文件用128个连续的字节做为一个记录(或分量)进行输入输出操作,数据直接在磁盘文件和变量之间传输,省去了文件缓解区,因此比其它文件少占内存,主要用来直接访问固定长元素的任意磁盘文件。无类型文件的具体操作在这里就不一一介绍,请参看有关的书籍。 程序:得到CITY.RES文件内容如下:101fuzhou2beijin3shanghai4wuhan5hongkong6tiangjin7shenyan8nanchan9chansa10guangzhou0111100001101111111111000010111100000001110000000001000011000110010001010001000001100000001111001000例9对例12.3的FILEDATE.FIL文件内容按总分的高低顺序排序。分析:文件的排序就是将文本文件的各分量按一定要求排列使文件有序,文件排序有内排序和外排序二种,内排序是指将文件各分量存入一个数组,再对数组排列,最后将该数组存入原来的文件。外排列不同于内排列,它不是将文件分量存入数组,而是对文件直接排序,内排序比外排序速度要快,但当文件很大时,无法调入内存,此时用外排序法较合适。本程序使用过程SEEK,实现外排序。程序: 习题1、编一程序,计算文本文件中行结束标志的数目。2、计算文本文件的行长度的平均值、最大值和最小值。3、一文本文件FILE.DAT存放N个学生某学科成绩,将成绩转换成直方图存入FILE.RES文件中。如FILE.DAT内容为:57890877384得到直方图文件FILE.RES内容为:5*****************************************4、银行账目文件含有每一开户的账目细节:开户号、姓名、地址、收支平衡额。写一程序,读入每一开户的账目,生成银行账目文件。 附录一Pascal中的字符串函数和数学函数 字符串函数 求长度length定义:functionLength(S:String):Integer;例子:varS:String;beginReadln(S);Writeln('"',S,'"');Writeln('length=',Length(S));end. 复制子串copy定义:functionCopy(S:String;Index:Integer;Count:Integer):String;注意:S是字符串类型的表达式。Index和Count是整型表达式。Copy返回S中从Index开始,Count个字符长的一个子串。例子:varS:String;beginS:='ABCDEF';S:=Copy(S,2,3);{'BCD'}end. 插入子串insert定义:procedureInsert(Source:String;varS:String;Index:Integer);注意:Source是字符串类型的表达式。S是任意长度字符串类型变量。Index是整型表达式。Insert把Source插在S中Index处。如果结果字符串的长度大于255,那么255之后的字符将被删除。例子:varS:String;beginS:='HonestLincoln';Insert('Abe',S,8);{'HonestAbeLincoln'}end. 删除子串delete定义:procedureDelete(varS:String;Index:Integer;Count:Integer);注意:S是字符串类型变量。Index和Countare是整型表达式。Delete删除S中从Index开始的Count个字符。如果Index大于S的长度,则不删除任何字符;如果Count大于S中从Index开始的实际字符数,则删除实际的字符数。例子:vars:string;begins:='HonestAbeLincoln';Delete(s,8,4);Writeln(s);{'HonestLincoln'}Delete(s,9,10);Writeln(s);{'HonestL'}end. 字符串转为数值val定义:procedureVal(S;varV;varCode:Integer);在这里:S是由一系列数字字符构成的字符串类型变量;。V是整型或实型变量;Code是Integer型变量注意:Val将S转为它的数值形式。例子:vars:string;I,Code:Integer;begins:='1234';val(s,i,code);writeln(i);{1234}end. 数值转为字符串str定义:procedureStr(X[:Width[:Decimals]];varS:string);注意:将数值X转成字符串形式。例子:varS:string[11];beginStr(I,S);IntToStr:=S;end;beginWriteln(IntToStr(-5322));Readln;end. 求子串起始位置pos定义:functionPos(Substr:String;S:String):Byte;注意:Substr和S字符串类型表达式。Pos在S中搜索Substr并返回一个integer值。这个值是Substr的第一个字符在S中的位置。如果在S中没有找到Substr,则Pos返回0。例子:varS:String;beginS:='123.5';{Convertspacestozeroes}whilePos('',S)>0doS[Pos('',S)]:='0';end. 字符完全串连+定义:操作符+把两个字符串联在一起。例子:vars1,s2,s:string;begins1:='Turbo';s2:='pascal';s:=s1+s2;{'Turbopascal'}end. 字符串压缩空格串连-定义:操作符-去掉第一个字符串最后的空格后,将两个字符串联在一起。例子:vars1,s2,s:string;begins1:='Turbo';s2:='pascal';s:=s1-s2;{'Turbopascal'}end. Pascal中的数学函数 求绝对值函数abs(x)定义:functionAbs(X):(Sametypeasparameter);说明:X可以是整型,也可以是实型;返回值和X的类型一致例子:varr:Real;i:Integer;beginr:=Abs(-2.3);{2.3}i:=Abs(-157);{157}end. 取整函数int(x)定义:functionInt(X:Real):Real;注意:X是实型数,返回值也是实型的;返回的是X的整数部分,也就是说,X被截尾了(而不是四舍五入)例子:varR:Real;beginR:=Int(123.567);{123.0}R:=Int(-123.456);{-123.0}end.截尾函数trunc(x)定义:functionTrunc(X:Real):Longint;注意:X是实型表达式.Trunc返回Longint型的X的整数部分例子:beginWriteln(1.4,'becomes',Trunc(1.4));{1}Writeln(1.5,'becomes',Trunc(1.5));{1}Writeln(-1.4,'becomes',Trunc(-1.4));{-1}Writeln(-1.5,'becomes',Trunc(-1.5));{-1}end. 四舍五入函数round(x)定义:functionRound(X:Real):Longint;注意:X是实型表达式.Round返回Longint型的X的四舍五入值.如果返回值超出了Longint的表示范围,则出错.例子:beginWriteln(1.4,'roundsto',Round(1.4));{1}Writeln(1.5,'roundsto',Round(1.5));{2}Writeln(-1.4,'roundsto',Round(-1.4));{-1}Writeln(-1.5,'roundsto',Round(-1.5));{-2}end. 取小数函数frac(x)定义:functionFrac(X:Real):Real;注意:X是实型表达式.结果返回X的小数部分;也就是说,Frac(X)=X-Int(_X).例子:varR:Real;beginR:=Frac(123.456);{0.456}R:=Frac(-123.456);{-0.456}end.求平方根函数sqrt(x)和平方函数sqr(x)定义:平方根:functionSqrt(X:Real):Real;注意:X是实型表达式.返回实型的X的平方根.平方:functionSqr(X):(Sametypeasparameter);注意:X是实型或整型表达式.返回值的类型和X的类型一致,大小是X的平方,即X*X.例子:beginWriteln('5squaredis',Sqr(5));{25}Writeln('Thesquarerootof2is',Sqrt(2.0));{1.414}end. 附录三关于fillchar的使用和讨论 大家听说过fillchar这个标准过程吧。很好用的。vara:array[1..10]ofarrtype; 执行fillchar(a,sizeof(a),0);当arrtype为1.real(其他差不多)使得a中的元素全部成为0.02.integer(byte,word,longint,shortint都相同)全部为03.boolean全部为false4.char全部为#0 执行fillchar(a,size(a),1);写几个特殊的1.integer全部为157(不知道为什么)2.real很大的一个数,同上。3.boolean全部为true4.byte,shortint全部为1,所以integer不行可以暂时用这两个嘛。要不然就减去156 附录五程序的调试(一)——步骤法 任何一个天才都不敢说,他编的程序是100%正确的。几乎每一个稍微复杂一点的程序都必须经过反复的调试,修改,最终才完成。所以说,程序的调试是编程中的一项重要技术。我们现在就来掌握一下基本的程序调试。我们以下的示范,是以时下比较流行的BorlandPascal7.0为例子,其他的编程环境可能略有不同,但大致上是一致的。我们先编一个比较简单的程序,看看程序是如何调试的。 programtiaoshi;vari:integer;beginfori:=1to300dobeginifimod2=0thenifimod3=0thenifimod5=0thenwriteln(i);end;end.该程序是输出300以内同时能被2,3,5整除的整数。现在我们开始调试。调试有多种方法,先介绍一种,权且叫步骤法,步骤法就是模拟计算机的运算,把程序每一步执行的情况都反映出来。通常,我们有F8即STEP这个功能来实现,如图:不断地按F8,计算机就会一步步地执行程序,直到执行到最后的“end.”为止。可能你还没有发现F8的威力,我们不妨把上面的程序略微修改一下,再配合另外的一种调试的利器watch,你就会发现步骤法的用处。 programtiaoshi;vari:integer;a,b,c:boolean;beginfori:=1to300dobegina:=false;b:=false;c:=false;ifimod2=0thena:=true;ifimod3=0thenb:=true;ifimod5=0thenc:=true;ifaandbandcthenwriteln(i);end;end.如图,我们单击菜单栏中debug选项,里面有一项叫watch的选项,我们单击它。就会出现一个watch窗口:watch窗口可以让我们观察变量的变化情况,具体操作是在watches窗口内按Insert键:这时,屏幕上弹出一个菜单,我们输入所需要观察的变量名,我们分别输入i,a,b,c这4个变量名,于是watches窗口内就有如下的4个变量的状态:这时,我们再次使用步骤法,我们会发现,这4个变量的状态随着程序的执行而不断变化,比如:这样我们就可以方便地知道执行每一步之后,程序的各个变量的变化情况,从中我们可以知道我们的程序是否出错,在哪里出错,方便我们及时地修改。下一次,我们介绍另外的一种方法,断点法 程序的调试(二)——断点法 在前面我们已经学习了基本的程序调试方法——步骤法。步骤法有一个缺点,就是在遇到循环次数比较多或者语句比较多的时候,用起来比较费时,今天我们来学习一种新的也是常用的调试方法——断点法。所谓断点法,就是在程序执行到某一行的时候,计算机自动停止运行,并保留这时各变量的状态,方便我们检查,校对。我们还是以前面求同时能被2,3,5整除的3000以内的自然数为例,具体操作如下:我们把光标移动到程序的第14行,按下ctrl+F8,这时我们会发现,该行变成红色,这表明该行已经被设置成断点行,当我们每次运行到第14行的时候,计算机都会自动停下来供我们调试。我们必须学以致用,赶快运用刚学的watch方法,看看这家伙到底有多厉害。 请记住,计算机是执行到断点行之前的一行,断点行并没有执行,所以这时b:=true这一句并没有执行。断点行除了有以上用处之外,还有另外一个重要用处。它方便我们判断某个语句有没有执行或者是不是在正确的时刻执行,因为有时程序由于人为的疏忽,可能在循环或者递归时出现我们无法预料的混乱,这时候通过断点法,我们就能够判断程序是不是依照我们预期的顺序执行。 附录六Pascal的多种退出语句用法 1、break是用来退出其所在的循环语句 即:不论在任何一个循环语句中执行了break的话,马上退出这个语句。相当于:goto这一层循环语句最末尾一句的下一句。例如:vari:integer;beginfori:=1to10dobegin{1}writeln(i);break;writeln(i+1);end;readlnend.执行结果:1 可见第一次循环时,执行了{1}句后,执行break,然后马上退出了这个for语句。{*****}注意:以上两个语句只对它们所在的那层循环语句起作用,也就是说:如果有多个循环语句相嵌套,其中某一层执行了continue/break语句,它们并不能影响上面几层的循环语句。 2、exit是退出当前程序块; 即:在任何子程序中执行exit,那么将退出这个子程序;如果是在主程序中执行exit,那么将退出整个程序。相当于:goto这个程序块的末尾的end例如:试除法判断素数时,一旦整除,就把函数值赋为false,然后exit;{******}注意:类似上面的,exit也是只对当前这一个子程序产生作用,如果多重嵌套子程序,那么其中某个子程序执行了exit以后,将返回到调用它的那个语句的下一个语句。 3、halt:没什么好说的,退出整个程序,GameOver. 例如:搜索时,一旦找到一个解,就打印,然后执行halt,退出整个程序。使用exit,halt应该注意的地方:要注意所有可能会退出子程序或主程序的地方均要妥善处理好善后工作,比如文件是否关闭,输出是否完整等。 最后说一句,使用这些语句使得程序结构不止有一个出口,破坏了结构化程序设计的标准控制结构,使程序难以调试(但是往往便于编写),应尽量避免使用,因为它们完全可以用其它语句代替,所以,除非使用这些语句能给编写程序带来较大的方便,且可读性不受到影响,才值得一用。