发布时间:2025-12-09 16:09:49 浏览次数:6
Pascal现在还有人想学习吗?先给出一本不错的Pascal教程,Object Pascal的教程我日后给出。
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.沃思(Niklaus Wirth)教授于1968年设计完成的,1971年正式发表。1975年,对PASCAL语言进行了修改,作为"标准PASCAL语言"。
PASCAL语言是在ALGOL 60的基础上发展而成的。它是一种结构化的程序设计语言,可以用来编写应用程序。它又是一种系统程序设计语言,可以用来编写顺序型的系统软件(如编译程序)。它的功能强、编译程序简单,是70年代影响最大一种算法语言。
二、Pascal 语言的特点
从使用者的角度来看,PASCAL语言有以下几个主要的特点:
⒈它是结构化的语言。PASCAL语言提供了直接实现三种基本结构的语句以及定义"过程"和"函数"(子程序)的功能。可以方便地书写出结构化程序。在编写程序时可以完全不使用GOTO语句和标号。这就易于保证程序的正确性和易读性。PASCAL语言强调的是可靠性、易于验证性、概念的清晰性和实现的简化。在结构化这一点上,比其它(如BASIC,FORTRAN77)更好一些。
⒉有丰富的数据类型。PASCAL提供了整数、实型、字符型、布尔型、枚举型、子界型以及由以上类型数据构成的数组类型、集合类型、记录类型和文件类型。此外,还提供了其它许多语言中所没有的指针类型。沃思有一个著名的公式:"算法+数据结构=程序"。指出了在程序设计中研究数据的重要性。丰富的数据结构和上述的结构化性质,使得PASCAL可以被方便地用来描述复杂的算法,得到质量较高的程序。
⒊能适用于数值运算和非数值运算领域。有些语言(如FORTRAN 66,ALGOL 60)只适用于数值计算,有些语言(如COBOL )则适用于商业数据处理和管理领域。PASCAL的功能较强,能广泛应用于各种领域。PASCAL语言还可以用于辅助设计,实现计算机绘图功能。
⒋PASCAL程序的书写格式比较自由。不象FORTRAN和COBOL那样对程序的书写格式有严格的规定。PASCAL允许一行写多个语句,一个语句可以分写在多行上,这样就可以使PASCAL程序写得象诗歌格式一样优美,便于阅读。
由于以上特点,许多学校选PASCAL作为程序设计课程中的一种主要的语言。它能给学生严格而良好的程序设计的基本训练。培养学生结构化程序设计的风格。但它也有一些不足之处,如它的文件处理功能较差等。 三、Pascal语言程序的基本结构
任何程序设计语言都有着一组自己的记号和规则。PASCAL语言同样必须采用其本身所规定的记号和规则来编写程序。尽管不同版本的PASCAL语言所采用的记号的数量、形式不尽相同,但其基本成分一般都符合标准PASCAL的规定,只是某些扩展功能各不相同罢了。下面我们首先来了解Pascal语言的程序基本结构。
为了明显起见先举一个最简单的PASCAL程序例子: 【例1】
从这个简单的程序可以看到:
⒈一个PASCAL程序分为两个部分:程序首部和程序体(或称分程序)。
⒉程序首部是程序的开头部分,它包括:
⑴程序标志。用"program"来标识"这是一个PASCAL 程序"。PASCAL规定任何一个PASCAL程序的首部都必须以此字开头。在turbo pascal语言中,首部也可省略。
⑵程序名称。由程序设计者自己定义,如例中的exam1。
在写完程序首部之后,应有一个分号。
⒊程序体是程序的主体,在有的书本里也称"分程序"。程序体包括说明部分(也可省略)和执行部分两个部分。
⑴说明部分用来描述程序中用到的变量、常量、类型、过程与函数等。本程序中第二行是"变量说明",用来定义变量的名称、类型。
PASCAL规定,凡程序中用到所有变量、符号常量、数组、标号、过程与函数、记录、文件等数据都必须在说明部分进行定义(或称"说明")。也就是说,不允许使用未说明先使用。
⑵执行部分的作用是通知计算机执行指定的操作。如果一个程序中不写执行部分,在程序运行时计算机什么工作也不做。因此,执行部分是一个PASCAL程序的核心部分。
执行部分以"begin"开始,以"end"结束,其间有若干个语句,语句之间以分号隔开。
执行部分之后有一个句点,表示整个程序结束。
⒋PASCAL程序的书写方法比较灵活。当然,书写不应以节省篇幅为目的,而应以程序结构清晰、易读为目的。在编写程序时尽量模仿本书中例题程序格式。
⒌在程序中,一对大括号间的文字称为注释。注释的内容由人们根据需要书写,可以用英语或汉语表示。注释可以放在任何空格可以出现的位置。执行程序时计算机对注释不予理睬。
四、Turbo Pascal语言系统的使用
目前,常用的Pascal语言系统有Turbo Pascal7.0与Borland Pascal 7.0,下面我们就来学习Turbo Pascal 7.0系统的使用。 1. 系统的启动
在运行系统目录下的启动程序TURBO.EXE,即可启动系统。屏幕上出现如图1所示的集成环境。
2. Turbo Pascal系统集成环境简介
最顶上一行为主菜单。中间蓝色框内为编辑窗口,在它个编辑窗口内可以进行程序的编辑。最底下一行为提示行,显示出系统中常用命令的快捷键,如将当前编辑窗口中文件存盘的命令快捷键为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命令)来装入程序,此时系统也会弹出一个对话框要求输入要打开的文件名,或直接在文件对话框列表中选择所要的文件,然后回到打开文件。
五、第一个程序
下面程序在运行时,会提示输入一个圆的半径,然后会在屏幕上画一个圆。按回车后程序结束回到程序窗口。
Program ex1;
Uses graph;
Var Gm,Gd,R :integer;
Begin
Gd:=0;
Write('Please enter the radius:');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。
一个整型数据用来存放整数。Turbo Pascal支持五种预定义整型,它们是shortint(短整型)、 integer(整型)、 longint(长整型)、 byte(字节型)和 word(字类型),Turbo Pascal分别用相同的名字作为他们的表识符。每一种类型规定了相应的整数取值范围以及所占用的内存字节数。
类型 数值范围 占字节数 格式
shortint -128..128 1 带符号8位
inteter -32768..32767 2 带符号16位
longint -2147483648..2147483647 4 带符号32位
byte 0..255 1 带符号8位
word 0..65535 2 带符号16位
Turbo Pascal规定了两个预定义整型常量表识符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都不是合法形式的实数。
无论实数是用十进制表示法还是科学表示法,它们在计算机内的表示形式是一样的,总是用浮点方式存储。
和整数相比,实数能表示的范围大得多,但值得注意的是实数的运算整数的运算速度慢且无法像整数那样精确表示,只能近似表示。
一个实型数据用类存放实数。Turbo Pascal支持五种预定义实型,它们是real(基本实型)、 single(但精度实型)、double(双精度实型)、extended(扩展实型)、comp(装配实型),Turbo Pascal分别用相同的名字作为他们的表识符。每一种类型规定了相应的实数取值范围、所占用的内存字节数以及它们所能达到的精度。
类型 数值范围 占字节数 有效位数
real 2.9e-39..1.7e38 6 11..12
single 1.5e-45..3.4e38 4 7..8
double 5.0e-324..1.7e308 8 15..16
extended 3.4e-4932..1.1e4932 10 19..20
comp -2**63+1..2**63-1 8 19..20
Turbo Pascal支持两种用于执行实型运算的代码生成模式:软件仿真模式和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符号。
例如:
var
age,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它要求除数和被除数均为整型, 结果也为整型。如10 DIV 2=5,10 DIV 3=3, 5 DIV 10=0. -15 DIV 4= -3。DIV运算只取商的整数部分,参与DIV运算的两个对象不能为实型。
⑥ mod (求余),也只能用于整数运算,结果为整数。例如:10 mod 4=2 , -17 mod 4= -1 , 4 mod (-3)=1, - 4 mod 3= -1,即 a mod b=a-(a p b)*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('My name is Liping');
2、 writeln语句
格式:
Write(表达式1,表达式2,……)或writeln
(二)输出语句的功能
计算机执行到某一输出语句时,先计算出输出语句中的每个表达式的值,并将每一个表达式的值一个接一个地输出到屏幕上。
Write语句与writeln语句格式上都相似,但它们在功能上有所不同,两个语句的区别在于,write语句将其后括号中的表达式一个接一个输出后,没有换行。而writeln语句则在输出各个表达式的值后换行。
例如以下两个程序段的输出分别为:
write(1,2,3,4);write(5,6);
输出为:
123456
writeln(1,2,3,4);write(5,6);
输出为:
1234
56
四、应用例析
例1:
某仓库5月1日有粮食100吨,5月2日又调进20吨,5月3日卖出库存的3分之二,5月4日又调进库存的3倍粮食,问该仓库从5月1日到5月4日期间每天的粮食分别是多少吨?(输出每天的库存量)
分析:在这个问题中,主要要描述从5月1日到5月4日期间仓库的粮食库存量,且易知它是不断变化的。因此我们可以用一个变量A来描述仓库的粮食库存量。
程序可写如下:
Program ex1;
Var A : integer;
Begin
A:=100;Writeln('5/1:',A);
A:=A+20;Writeln('5/2:',A);
A:=A p 3; writeln('5/3:',A);
A:=A *4; writeln('5/4:',A);Readln;
End.
例2:
有三个小朋友甲乙丙。甲有50粒糖果,乙有43粒糖果,两有13粒糖果。现在他们做一个游戏。从甲开始,将自己的糖分三份,自己留一份,其余两份分别给乙与丙,多余的糖果自己吃掉,然后乙与丙也依次这样做。问最后甲、乙、丙三人各有书多少粒糖果?
分析:
这个问题中我们关心的是在游戏过程中每个小朋友的糖果个数,且他们所拥有的的糖果数是在变化的。因此可用a,b,c三个变量分别存放甲乙丙三个小朋友在某一时刻所拥有的糖果数。对于每人,分糖后,他的糖果数一定为原来的糖果数 p 3(因为分糖过程糖果的数目不一定都刚好分完,用整除恰恰可以表示多余的糖自己吃掉)。而其他两人则增加与这个小朋友现在拥有的一样的糖果。
程序可写如下:
program ex2;
var A,B,C:integer;
begin
A:=50;B:=43;C:=13; {初始时每个小朋友所拥有的糖果数}
A:=A p 3; B:=B+A;C:=C+A;{甲小朋友分糖果后,每个人拥有的糖果数变化情况}
B:=B p 3; A:=A+B;C:=C+B; {乙小朋友分糖果后,每个人拥有的糖果数变化情况}
C:=C p 3; 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版所规定的标准场宽。
标准场宽
━━━━━━━━━━━━━━━━━
数据类型 标准pascal Turbo pascal
─────────────────
integer 10 实际长度
real 22 17
布尔型 10 4或5
字符串 串长 串长
━━━━━━━━━━━━━━━━━
在Turbo Pascal系统中,对于整型字符串的输出都是按数据本身长度输出,对于布尔型数据(只有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
写出下列程序在turbo pascal下的输出结果.
program ex;
const s='abcdefg';
var
i:integer;
r:real;
c:char;b:boolean;
begin
i:=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□□□abcdefgabcdefg
TRUE□TRUETRUE
3.应用例析
例2:
已知A=253,B=43,输出A*B的运算式子。即输出如下:
253*43=10879
253
* 43
759
+1012
10879
分析:
对于该问题,我们只要控制好输出时右靠齐即可。即前四行的总宽度一样(例如为12),第五行总宽度比前面少1。第六、七行总宽度与前四行一样。
参与程序如下:
var a,b:integer;
begin
a:=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语句后,指针移到下一个数据行的开头。
各变量的值如下表所示。
━━━━━━━━━━━━━━━━━━━━━━━━━━
变量名 a b c d e f g
──────────────────────────
值 1 2 3 4 5 11 12
──────────────────────────
⑥为了避免可能出现的错误,建议在程序中按下列原则使用读语句:(A)如果没有特殊需要,在一个程序中尽量避免混合使用read语句和readln语句;(B)尽量用readln语句来输入数据, 一个数据行对应一个readln语句;(C)由于执行read或readln语句时, 系统不会提供任何提示信息,因此,编程时最好在readln语句之前加以适当提示,例如:
write('Input a,b,c:');
readln(a,b,c);
在执行时,屏幕上显示:
Input a,b,c:■
其中,"■"为光标。执行readln语句后,系统处于待待输入状态, 只有输入了所需数据后才继续往下执行。
三、顺序结构程序设计
到目前为止,我们可以用读、写语句和赋值语句编写一些简单的程序。通过阅读这些程序,可以逐步熟悉pascal程序的编写方法和应遵循的规则,为以后各章的学习打基础。
例6
试编一程序,输入一梯形的上底、下底、高, 求该梯形的面积。
分析:
整个程序分为三段:输入、计算、输出。程序中用a,b,h三个变量分别存放梯形的上、下底与高,S存放面积。 要而使用这些变量都要先说明,程序的执行部分中先输入上、下底与高,接着求面积S,最后输出结果S。
源程序如下:
program Tixing; {程序首部}
var a,b,h,s:real; {程序说明部分}
begin
write('Input a,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类似。
参考程序如下:
program fentang;
var a,b,c,d,e:integer;
begin
write('Please Enter init numbers ');readln(a,b,c,d,e);
a:=a p 3;b:=b+a;e:=e+a;{1号均分后,1、2、5号的糖果数变化情况}
b:=b p 3;c:=c+b;a:=a+b;{2号均分后,1、2、3号的糖果数变化情况}
c:=c p 3;b:=b+c;d:=d+c;{3号均分后,2、3、4号的糖果数变化情况}
d:=d p 3;c:=c+d;e:=e+d;{4号均分后,3、4、5号的糖果数变化情况}
e:=e p 3;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.
源程序如下:
program circle;
const PI=3.14159;
var r,c,s:real;
begin
write('Enter R=');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)。
例如,VAR A,B:BOOLEAN;
3、 布尔类型是顺序类型
由于这种类型只有两个常量,Pascal语言中规定ture的序号为1,false的序号为0。若某种类型的常量是有限的,那么这种类型的常量通常都有一个序号,我们称这种类型为顺序类型。如前面我们学过的整型(integer),以及后面要学到的字符型(char)都是顺序类型。
4、 布尔类型的输入与输出
a)输出
VAR A,B:BOOLEAN;
BEGIN
A:=TRUE;B:=FALSE;
WRITELN(A,B);
END.
TRUEFALSE
b)布尔类型变量不能直接用读语句输入
布尔类型变量不能通过读语句给它们提供值。事实上,我们可以通过间接方式对布尔变量进行值的输入。
例如,以下程序是错误的:
var a,b,c:Boolean;
begin
readln(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为偶数"可表示为:m mod 2=0。"n为正数"可表示为:n>0。
3.布尔运算及布尔表达式
为了表示更复杂的命题,Pascal还引入三种逻辑运算符:not、and、or。它们分别相当于数学上的"非"、"且"和"或"的意义。
这三个运算符的运算对象为布尔量,其中not为单目运算,只有一个运算对象,and与or为双目运算,有两个运算对象。它们的运算真值表如下:
| a | b | Not a | a and b | a or b | a xor b |
| false | false | true | false | false | false |
| false | true | true | false | ture | true |
| true | false | false | false | true | true |
| true | true | false | true | true | false |
于是,对于一个关系表达式,或多个关系表达式用布尔运算符连接起来的式子就称为布尔表达式。布尔表达式的值也为布尔值。
如果一个表达式里出现两个或两个以上的运算符, 则必须规定它们的运算次序。pascal规定:
①表达式中相同优先级的运算符,按从左到右顺序计算;
②表达式中不同优先级的运算符,按从高到低顺序计算;
③括号优先级最高,从内到外逐层降低;
对于一个复杂的表达式可能同时包含算术运算、关系运算和逻辑运算以及函数运算。运算的优先顺序为:括号à函数ànotà*、/、p、mod、andà+、-、or、xorà关系运算。
对于复杂的命题,我们可以用布尔表达式来表示。例如,命题:"m,n都是偶数或都是奇数"可表示为"(m mod 2=0)and(n mod 2=0) or (m mod 2=1)and(n mod 2=1)"。
三、简单的IF语句
1、格式
Ⅰ、IF <布尔表达式>THEN 语句;
Ⅱ、IF <布尔表达式>THEN 语句1 ELSE 语句2;
(注意Ⅱ型IF语句中语句1后无";"号)
2、功能 Ⅰ、执行IF语句时,先计算<布尔表达式>的值,若为TRUE则执行语句,否则不执行任何操作。
Ⅱ、执行IF语句时,先计算<布尔表达式>的值,若为TRUE则执行语句1,否则执行语句2;
3、示例
1)例4.2输入一个整数a,判断是否为偶数。(是输出"yes"否则输出"no")。
Program ex4_2;
Var a:integer;
Begin
Write('a=');readln(a);
If (a mod 2 =0)then writeln('yes')
Else writeln('no');
Readln;
End.
2)华榕超市里卖电池,每个电池8角钱,若数量超过10个,则可打75折。
Program ex4_3;
Var Num:integer;Price,Total:real;
Begin
Write('Num=');readln(Num);
Price=0.8;
If Num>10 then Price:=Price*0.75;
Total:=Num*Price;
Writeln('Total=',Total:0:2);
Readln;
End.
3)编写一与电脑猜"红"或"黑"的游戏。
分析:用1代表红,0代表黑。先由计算机先出答案,然后再由人猜,猜对输出"YOU WIN"否则输出"YOU LOST"。为了模拟猜"红"或"黑"的随意性,程序中需要用到随机函数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之间的整数(但它不确定的,或说是随机的)。同时由于函数是一个运算结果,所以函数的调用只能出现在表达式中。
Program ex4_3;
Uses crt;
Var Computer,People:integer;
Begin
Randomize;
Computer:=random(2);
Write('You guess(0-Red 1-Black):');readln(People);
If People=Computer then writeln('YOU WIN')
Else writeln('YOU LOST');
Readln;
End.
作业:.某车站行李托运收费标准是:10公斤或10公斤以下,收费2.5元,超过10公斤的行李,按每超过1公斤增加1.5元进行收费。 试编一程序,输入行李的重量,算出托运费。
第五课 if嵌套与case语句
一、IF语句的嵌套
在if语句中,如果then子句或else子句仍是一个if语句, 则称为if语句的嵌套。
例1 计算下列函数
分析:根据输入的x值,先分成x>0与x≤0两种情况,然后对于情况x≤0,再区分x是小于0,还是等于0。
源程序如下:
program ex;
var
x:real;
y:integer;
begin
wrtie('Input x:');readln(x);
if x>0 then y:=1{x>0时,y的值为1}
else {x≤0时}
if x=0 then y:=0
else y:=-1;
writeln('x=',x:6:2,'y=',y);
end.
显然,以上的程序中,在then子句中嵌套了一个Ⅱ型if语句。当然程序也可以写成如下形式:
program ex;
var
x:real;y:integer;
begin
wrtie('Input x:');readln(x);
if x>=0 then
if x>0 then y:=1
else y:=0
else y=-1;
writeln('x=',x:6:2,'y=',y);
end.
但是对于本题,下面的程序是不对的。
y:=0;
if x>=0 then
if x>0 then y:=1
else y:=-1;
明显,从此人的程序书写格式可以看出,他想让else与第一个if配对,而事实上,这是错的。因为pascal规定:else与它上面的距它最近的then配对,因此以上程序段的逻辑意义就与题义不符。
要使上程序段中esle与第一个then配对,应将程序段修改为:
y:=0; 或者 y:=0;
if x>=0 if x>=0
then if x>0 then
then y:=1 begin
else if x>0 then Y:=1;
else y:=-1; end
else Y:=-1;
二、case语句
上面我们知道可以用嵌套的if语句实现多分支的选择结构。但是如果分支越来越多时,用嵌套的if语句实现多分支就显得繁杂。当多分支选择的各个条件由同一个表达式的不同结果值决定时,可以用case语句实现。它的选择过程,很象一个多路开关,即由case语句的选择表达式的值,决定切换至哪一语句去工作。因此在分支结构程序设计中,它是一种强有力的手段。在实现多路径分支控制时,用case对某些问题的处理和设计,比用if语句写程序具有更简洁、清晰之感。
(一)、情况语句的一般形式:
case <表达式> of
<情况标号表1>:语句1;
<情况标号表2>:语句2;
:
<情况标号表n>:语句n
end;
其中case、of、end是Pascal的保留字, 表达式的值必须是顺序类型,它可以是整型、布尔型及以后学习的字符型、枚举型和子界型。情况标号表是一串用逗号隔开的与表达式类型一致的常量序列。语句可以是任何语句,包括复合语句和空语句。
(二)、case语句的执行过程
先计算表达式(称为情况表达式)的值,如果它的值等于某一个常量(称为情况常量,也称情况标号),则执行该情况常量后面的语句,在执行完语句后,跳到case语句的末尾end处。
(三)、说明
①情况表达式必须是顺序类型的;
②情况常量是情况表达式可能具有的值,因而应与情况表达式具有相同的类型;
③情况常量出现的次序可以是任意的;
④同一情况常量不能在同一个case语句中出现两次或两次以上;
⑤每个分语句前可以有一个或若干个用逗号隔开的情况常量;
⑥如果情况表达式的值不落在情况常的范围内,则认为本case语句无效,执行case语句的下一个语句。turbo pascal中增加了一个"否则"的情况,即增加一个else子句,但也是可省的。
⑦每个常量后面只能是一个语句或一个复合语句。
例2 根据x的值,求函数Y的值:
分析:利用case语句进行程序设计, 关键在于巧妙地构造情况表达式。本例中三种情况可用一个表达式区分出来:Trunc(x/100)。因为x在(0~100)之间时表达式值为0;x在[100,200)时表达式值为1 ;其余部分可用else子句表示。
源程序如下:
program ex;
var x,y:real;
begin
write('Input x:');readln(x);
case trunc(x/100) of
0:y:=x+1;
1:y:=x-1;
else y:=0;
end;{end of case}
writeln('x=',x:8:2),'y=',y:8:2);
end.
三、选择结构的程序设计
例3 输入一个年号,判断它是否是闰年。
分析:判断闰年的算法是:如果此年号能被400除尽, 或者它能被4整除而不能被100整除,则它是闰年。否则,它是平年。
源程序如下:
program ex;
var year:integer;
begin
write('Input year:');readln(year);
write(year:6);
if (year mod 400=0 ) then
writeln('is a leap year.')
else
if (year mod 4=0)and(year mod 100<>0)
then writeln('is a leap year.')
else writeln('is not a leap year.');
end.
例4 判断1995年,每个月份的天数。
分析:程序分为:输入月份,计算该月的天数,输出天数
源程序如下:
program days;
var month,days:integer;
begin
write('Input month:');readln(month);
case month of
1,3,5,7,8,10,12:days:=31;
4,6,9,11 :days:=30;
2 :days:=28;
else days:=0;
end;
if days<>0 then writeln('Days=',days);
end.
例5 期未来临了,班长小Q决定将剩余班费X元钱,用于购买若干支钢笔奖励给一些学习好、表现好的同学。已知商店里有三种钢笔,它们的单价为6元、5元和4元。小Q想买尽量多的笔(鼓励尽量多的同学),同时他又不想有剩余钱。请您编一程序,帮小Q制订出一种买笔的方案。
分析:对于以上的实际问题,要买尽量多的笔,易知都买4元的笔肯定可以买最多支笔。因此最多可买的笔为x p 4支。由于小q要把钱用完,故我们可以按以下方法将钱用完:
若买完x p 4支4元钱的笔,还剩1元,则4元钱的笔少买1支,换成一支5元笔即可;若买完x p 4支4元钱的笔,还剩2元,则4元钱的笔少买1支,换成一支6元笔即可;若买完x p 4支4元钱的笔,还剩3元,则4元钱的笔少买2支,换成一支5元笔和一支6元笔即可。
从以上对买笔方案的调整,可以看出笔的数目都是x p 4,因此该方案的确为最优方案。
源程序如下:
program pen;
var a,b,c:integer;{a,b,c分别表示在买笔方案中,6元、5元和4元钱笔的数目}
x,y:integer;{x,y分别表示剩余班费和买完最多的4元笔后剩的钱}
begin
write('x=');readln(x){输入x}
c:=x p 4;{4元笔最多买的数目}
y:=x mod 4;{求买完c支4元笔后剩余的钱数y}
case y of
0 : begin a:=0;b:=0; end;
1 : begin a:=0;b:=1;c:=c-1; end;
2 : begin a:=1;b:=0; c:=c-1;end;
3 : begin a:=1;b:=1; c:=c-2;end;
end;
writeln('a=',a,'b=',b,'c=',c);
end.
练 习
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循环语句
在实际应用中,会经常遇到许多有规律性的重复运算,这就需要掌握本章所介绍的循环结构程序设计。在Pascal语言中,循环结构程序通常由三种的循环语句来实现。它们分别为FOR循环、当循环和直到循环。通常将一组重复执行的语句称为循环体,而控制重复执行或终止执行由重复终止条件决定。因此,重复语句是由循环体及重复终止条件两部分组成。
一、for语句的一般格式
for <控制变量>:=<表达式1> to <表达式2> do <语句>;
for <控制变量>:=<表达式1> downto <表达式2> do <语句>;
其中for、to、downto和do是Pascal保留字。表达式1 与表达式2的值也称为初值和终值。
二、For语句执行过程
①先将初值赋给左边的变量(称为循环控制变量);
②判断循环控制变量的值是否已"超过"终值,如已超过,则跳到步骤⑥;
③如果末超过终值,则执行do后面的那个语句(称为循环体);
④循环变量递增(对to)或递减(对downt o)1;
⑤返回步骤②;
⑥循环结束,执行for循环下面的一个语句。
三、说明
①循环控制变量必须是顺序类型。例如,可以是整型、字符型等,但不能为实型。
②循环控制变量的值递增或递减的规律是:选用to则为递增;选用downto则递减。
③所谓循环控制变量的值"超过"终值,对递增型循环,"超过"指大于,对递减型循环,"超 过"指小于。
④循环体可以是一个基本语句,也可以是一个复合语句。
⑤循环控制变量的初值和终值一经确定,循环次数就确定了。但是在循环体内对循环变量的值进行修改,常常会使得循环提前结束或进入死环。建议不要在循环体中随意修改控制变量的值。
⑥for语句中的初值、终值都可以是顺序类型的常量、变量、表达式。
四、应用举例
例1.输出1-100之间的所有偶数。
var i:integer;
begin
for i:=1 to 100 do
if i mod 2=0 then write(i:5);
end.
例2.求N!=1*2*3*…*N ,这里N不大于10。
分析:程序要先输入N,然后从1累乘到N。
程序如下:
var
n,i : integer;{i为循环变量}
S : longint;{s作为累乘器}
begin
write('Enter n=');readln(n);{输入n}
s:=1;
for i:=2 to n do{从2到n累乘到s中}
s:=s*i;
writeln(n,'!=',s);{输出n!的值}
end.
练 习
1. 求s=1+4+7+…+298的值。
2. 编写一个评分程序,接受用户输入10个选手的得分(0-10分),然后去掉一个最高分和一个最低分,求出某选手的最后得分(平均分)。
3. 用一张一元票换1分、2分和5分的硬币,每种至少一枚, 问有哪几种换法(各几枚)?
第七课 WHILE循环与REPEAT
一、WHILE循环
对于for循环有时也称为计数循环,当循环次数未知,只能根据某一条件来决定是否进行循环时,用while 语句或repeat语句实现循环要更方便。
while语句的形式为:
while <布尔表达式> do <语句>;
其意义为:当布尔表达式的值为true时,执行do后面的语句。
while语句的执行过程为:
①判断布尔表达式的值,如果其值为真,执行步骤2,否则执行步骤4;
②执行循环体语句(do后面的语句);
③返回步骤1;
④结束循环,执行while的下一个语句。
说明:这里while和do为保留字,while语句的特点是先判断,后执行。 当布尔表达式成立时,重复执行do后面的语句(循环体)。
例1 、求恰好使s=1+1/2+1/3+…+1/n的值大于10时n的值。
分析:"恰好使s的值大于10"意思是当表达式s的前n-1项的和小于或等于10,而加上了第n项后s的值大于10。从数学角度,我们很难计算这个n的值。故从第一项开始,当s的值小于或等于10时,就继续将下一项值累加起来。当s的值超过10时,最后一项的项数即为要求的n。
程序如下:
var
s : real;
n : integer;{n表示项数}
begin
s:=0.0;n:=0;
while s<=10 do{当s的值还未超过10时}
begin
n:=n+1;{项数加1}
s:=s+1/n;{将下一项值累加到s}
end;
writlen('n=',n);{输出结果}
end.
例2、求两个正整数m和n的最大公约数。
分析:求两个正整数的最大公约数采用的辗转相除法求解。以下是辗转的算法:
分别用m,n,r表示被除数、除数、余数。
①求m/n的余数r.
②若r=0,则n为最大公约数.若r≠0,执行第③步.
③将n的值放在m中,将r的值放在n中.
④返回重新执行第①步。
程序如下:
program ex4_4;
var m,n,a,b,r:integer;
begin
write('Input m,n:');
readln(m,n);
a:=m;b:=n;r:=a mod b;
while r<>0 do
begin
a:=b;b:=r;
r:=a mod b;
end;
writeln('The greatest common pide is:',b:8);
end.
二、直到循环(REPEAT-until语句)
用while语句可以实现"当型循环",用repeat-until 语句可以实现"直到型循环"。repeat-until语句的含义是:"重复执行循环,直到指定的条件为真时为止"。
直到循环语句的一般形式:
Repeat
<语句1>;
:
<语句n>;
until <布尔表达式>;
其中Repeat、until是Pascal保留字,repeat与until之间的所有语句称为循环体。
说明:
①repeat语句的特点是:先执行循环,后判断结束条件,因而至少要执行一次循环体。
②repeat-until是一个整体,它是一个(构造型)语句,不要误认为repeat是一个语句, until是另一个语句。
③repeat语句在布尔表达式的值为真时不再执行循环体,且循环体可以是若干个语句,不需用begin和end把它们包起来, repeat 和until已经起了begin和end的作用。while循环和repeat循环是可以相互转化的。
对于例2中求两个正整数的最大公约数,程序可用repeat-until循环实现如下:
var
m,n,a,b,r : integer;
begin
write('Input m,n=');
readln(m,n);
a:=m;b:=n;
repeat
r:=a mod b;
a:=b;b:=r;
until r=0;
writeln('The greatest common pide is',a);
end.
以上我们已介绍了三种循环语句。一般说来,用for 循环比较简明,只要能用for循环,就尽量作用for循环。只在无法使用for循环时才用while循环和repeat-until循环, 而且 while 循环和repeat-until循环是可以互相替代的。for 循环在大多数场合也能用whiel和repeat-until循环来代替。一般for循环用于有确定次数循环,而while和repeat-until循环用于未确定循环次数的循环。
当一个循环的循环体中又包含循环结构程序时,我们就称之为循环嵌套。
三、循环结构程序设计
例3 求1!+2!+…+10!的值。
分析:这个问题是求10自然数的阶乘之和,可以用for 循环来实现。程序结构如下:
for n:=1 to 10 do
begin
①N!的值àt
②累加N!的值t
end
显然,通过10次的循环可求出1!,2!…,10!,并同时累加起来, 可求得S的值。而求T=N!,又可以用一个for循环来实现:
t=1;
for j:=1 to n do
t:=t*j;
因此,整个程序为:
program ex4_5;
var t,s:real;
i,j,n:integer;
begin
S:=0;
for n:=1 to 10 do
begin
t:=1;
for j:=1 to n do
t:=t*j;
S:=S+t;
end;
writeln('s=',s:0:0);
end.
以上的程序是一个二重的for循环嵌套。这是比较好想的方法,但实际上对于求n!,我们可以根据求出的(n-1)!乘上n即可得到,而无需重新从1再累乘到n。
程序可改为:
program ex4_5;
var t,s:real;
i,j,n:integer;
begin
S:=0;t:=1;
for n:=1 to 10 do
begin
t:=t*n;
S:=S+t;
end;
writeln('s=',s:0:0);
end.
显然第二个程序的效率要比第一个高得多。第一程序要进行1+2+…+10=55次循环,而第二程序进行10次循环。如题目中求的是1!+2!+…+1000!,则两个程序的效率区别更明显。
例4 一个炊事员上街采购,用500元钱买了90只鸡, 其中母鸡一只15元,公鸡一只10元,小鸡一只5元,正好把钱买完。问母鸡、公鸡、小鸡各买多少只?
分析:设母鸡I只,公鸡J只,则小鸡为90-I-J只,则15*I+ 10* J+(90-I-J)*5=500,显然一个方程求两个未知数是不能直接求解。必须组合出所有可能的i,j值,看是否满足条件。这里I的值可以是0到33,J的值可以0到50。
源程序如下:
programr ex4_6;
var i,j,k:integer;
begin
for i:=1 to 5 do
for j:=1 to 8 do
begin
k:=90-i-j;
if 15*i+10*j+5*k=500 then writeln(i:5,j:5,k:5);
end;
end.
例5、求100-200之间的所有素数。
分析:我们可对100-200之间的每一整数进行判断,判断它是否为素数,是则输出。而对于任意整数i,根据素数定义,我们从2开始,到 ,找i的第一个约数。若找到第一个约数,则i必然不是素数。否则i为素数。
源程序如下:
var
i : integer;
x : integer;
begin
for i:=100 to 200 do
begin
x:=2;
while (x<=trunc(sqrt(i)))and(i mod x<>0)do
begin
x:=x+1;
end;
if x>trunc(sqrt(i)) then write(i:8);
end;
end.
练 习
1、输入一个正整数n,将n分解成质因数幂的乘积形式。
例如:36=22*32
2、输出如下图形。
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表示总分}
for i:=1 to 50 do {循环读入每一个学生的成绩,并累加它到总分}
begin
read(a[i]);
tot:=tot+a[i];
end;
ave:=tot/50;{计算平均分}
for i:=1 to 50 do
if a[i]<ave then writeln('No.',i,' ',a[i]);{如果第i个同学成绩小于平均分,则将输出}
而要在程序中使用下标变量,则必须先说明这些下标变量的整体―数组,即数组是若干个同名(如上面的下标变量的名字都为a)下标变量的集合。
二、一维数组
当数组中每个元素只带有一个下标时,我们称这样的数组为一维数组。
1、一维数组的定义
(1)类型定义
要使用数组类型等构造类型以及第6章要学习的自定义类型(枚举类型与子界类型),应在说明部分进行类型说明。 这样定义的数据类型适用整个程序。
类型定义一般格式为:
type
<标识符1>=<类型1>;
<标识符2>=<类型2>;
:
<标识符n>=<类型n>;
其中type是Pascal保留字,表示开始一个类型定义段。在其后可以定义若干个数据类型定义。<标识符>是为定义的类型取的名字, 称它为类型标识符。
类型定义后,也就确定了该类型数据取值的范围,以及数据所能执行的运算。
(2)一维数组类型的定义
一维数组类型的一般格式:
array[下标1..下标2] of <基类型>;
说明:其中array和of是pascal保留字。下标1和下标2 是同一顺序类型,且下标2的序号大于下标1的序号。它给出了数组中每个元素(下标变量) 允许使用的下标类型,也决定了数组中元素的个数。基类型是指数组元素的类型,它可以是任何类型,如整型,实型,字符型等。同一个数组中的元素具有相同类型。因此我们可以说,数组是由固定数量的相同类型的元素组成的。
再次提请注意:类型和变量是两个不同概念,不能混淆。就数组而言,程序的执行部分使用的不是数组类型(标识符)而是数组变量(标识符)。
一般在定义数组类型标识符后定义相应的数组变量,如:
type arraytype=array[1..8]of integer;
var a1,a2:arraytype;
其中arraytype为一个类型标识符,表示一个下标值可以是1到 8,数组元素类型为整型的一维数组;而a1,a2则是这种类型的数组变量。
也可以将其合并起来:
var a1,a2:array[1..8]of integer;
即
type arraytype=array[1..8]of integer;
var a1,a2:arraytype;
相当于
var a1,a2:array[1..8]of integer;
一般我们使用第二种定义方法。
当在说明部分定义了一个数组变量之后,pascal 编译程序为所定义的数组在内存空间开辟一串连续的存储单元。
例如,设程序中有如下说明:
var a:array[1..8] of integer;
则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个元素中去。
例1的完整程序如下所示:
program ex;
var
a:array[1..10] of integer;{定义a为含10个整型数组元素的一维数组}
i,tot:integer;
ave:real;
begin
tot:=0;{tot表示总分}
for i:=1 to 10 do {循环读入每一个学生的成绩,并累加它到总分}
begin
read(a[i]);
tot:=tot+a[i];
end;
ave:=tot/10;{计算平均分}
for i:=1 to 10 do
if a[i]<ave then writeln('No.',i,' ',a[i]);{如果第i个同学成绩小于平均分,则将输出}
end.
对于一维数组的输入与输出, 都只能对其中的元素逐个的输入与输出。在下面的应用示例中将详细介绍。
三、一维数组应用示例
例2 输入10个数,要求程序按输入时的逆序把这10个数打印出来。也就是说,请你按输入相反顺序打印这10个数。
分析:我们可定义一个数组a用以存放输入的10个数, 然后将数组a内容逆序输出。
源程序如下:
program ex5_1;
type arr=array[1..10]of integer; {说明一数组类型arr}
var
a:arr;i:integer;{定义a是上面说明的arr类型,i是整型}
或上面红色语句也可以用下面红色语句代替
var
a:array[1..10] of integer;
i:integer;
begin
writeln('Enter 10 integer:');{提示要输入10个整数}
for i:=1 to 10 do read(a[i]);{从键盘上输入10个整数,这是数组元素取数的方法}
readln;{输入换行}
for i:=10 downto 1 do {逆序输出这50个数,这是输出数组元素的值}
write(a[i]:10);
end.
例3 输入任意十个正整数,统计数字5的个数。
分析:将十个数字放到数组a中,并设置一个计数变量k,k的初值为0,将每个数字与5作比较,如与5相等,则k加1。最后输出k的值。
程序如下:
program ex5_3;
var
a:array [1..10] of integer;
k,I:integer;
begin
for i:=1 to 10 do read(a[i]);{从键盘任意输入10个整数}
k:=0;
for i:=1 to 10 do
if a[i]=5 then k:=k+1;{统计5的个数,放到变量k中}
writeln(‘k’,=k);{输出k的值}
end.
例4 输入一个不超过30000的正整数,按从低位到高位输出每一位上的数字。
如:输入2645,输出5 4 6 2
分析:对2645,先以2645 mod 10取出个位数,放到a[1]中,以2645 p 10 得到剩下的数264,依次类推,再以264 mod 10 得到十位数4,放到a[2]中,以264 p 10得到剩下的数26,再以26 mod 10 得到百位数6,放到a[3]中,以26 p 10得到剩下的数2,以2 mod 10得到千位数2,以2 p 10得到剩下的数为0。程序结束。
程序如下:
program ex5_4
var
a:array[1..10] of integer;
n,i,k:integer;{n为输入的任意正整数,k为n的位数}
begin
readln(n);
k:=0;
while n>0 do{从低位向高位取出n的每一位数,放到数组a中}
begin
k:=k+1;
a[k]:=n mod 10;
n:=n p 10;
end;
for i:=1 to k do{输出数组a中的每一个元素的值}
write(a[i],’’);
end.
例5 输入十个正整数,把这十个数按由小到大的顺序排列。
将数据按一定顺序排列称为排序,排序的算法有很多,其中选择排序是一种较简单的方法。
分析:要把十个数按从小到大顺序排列,则排完后,第一个数最小,第二个数次小,……。因此,我们第一步可将第一个数与其后的各个数依次比较,若发现,比它小的,则与之交换,比较结束后,则第一个数已是最小的数(最小的泡往下冒)。同理,第二步,将第二个数与其后各个数再依次比较,又可得出次小的数。如此方法进行比较,最后一次,将第九个数与第十个数比较,以决定次大的数。于是十个数的顺序排列结束。
例如下面对5个进行排序,这个五个数分别为8 2 9 10 5。按选择排序方法,过程如下:
初始数据 :8 2 9 10 5
第一次排序:8 2 9 10 5
9 2 8 10 5
10 2 8 9 5
10 2 8 9 5
第二次排序:10 8 2 9 5
10 9 2 8 5
10 9 2 8 5
第三次排序:10 9 8 2 5
10 9 8 2 5
第四次排序:10 9 8 5 2
对于十个数,则排序要进行9次。源程序如下:
program ex5_5;
var a:array[1..10]of integer;
i,j,t:integer;
begin
writeln('Input 10 integers:');
for i:=1 to 10 do read(a[i]);{读入10个初始数据}
readln;
for i:=1 to 9 do{进行9次排序}
begin
for j:=i+1 to 10 do{将第i个数与其后所有数比较}
if a[i]<a[j] then {若有比a[i]大,则与之交换}
begin
t:=a[i];a[i]:=a[j];a[j]:=t;
end;
write(a[i]:5);
end;
end.
练习:
1.输入10个正整数,输出偶数与奇数的个数。
2.输入10个数,输出大于6的个数。
3.输入一个不超过30000的正整数,输出所有位上数字的和。
例:输入2546,输出17。即2+5+4+6=17
4.输入一串小写字母(以"."为结束标志),统计出每个字母在该字符串中出现的次数(若某字母不出现,则不要输出)。
例:
输入:aaaabbbccc.
输出:a:4
b:3
c:3
5.输入一个不大于32767的正整数N,将它转换成一个二进制数。
例如:
输入:100
输出: 1100100
6.输入一个由10个整数组成的序列,其中序列中任意连续三个整数都互不相同,求该序列中所有递增或递减子序列的个数。
例如:
输入:1 10 8 5 9 3 2 6 7 4
输出:6
对应的递增或递减子序列为:
1 10
10 8 5
5 9
9 3 2
2 6 7
7 4
第九课 多维数组
一、多维数组的定义
当一维数组元素的类型也是一维数组时,便构成了二维数组。二维数组定义的一般格式:
array[下标类型1] of array[下标类型2] of 元素类型;
但我们一般这样定义二维数组:
array[下标类型1,下标类型2] of 元素类型;
说明:其中两个下标类型与一维数组定义一样,可以看成"下界1..上界1"和"下界2..上界2",给出二维数组中每个元素( 双下标变量)可以使用下标值的范围。of后面的元素类型就是基类型。
一般地,n维数组的格式为:
array[下标类型1,下标类型2,…,下标类型n] of 元素类型;
其中,下标类型的个数即数组的维数,且说明了每个下标的类型及取值范围。
二、多维数组元素的引用
多维数组的数组元素引用与一维数组元素引用类似,区别在于多维数组元素的引用必须给出多个下标。
引用的格式为:
<数组名>[下标1,下标2,…,下标n]
说明:显然,每个下标表达式的类型应与对应的下标类型一致,且取值不超出下标类型所指定的范围。
例如,设有说明:
type matrix=array[1..5,1..4]of integer;
var a:matrix;
则表示a是二维数组,共有5*4=20个元素,它们是:
a[1,1]a[1,2]a[1,3]a[1,4]
a[2,1]a[2,2]a[2,3]a[2,4]
a[3,1]a[3,2]a[3,3]a[3,4]
a[4,1]a[4,2]a[4,3]a[4,4]
a[5,1]a[5,2]a[5,3]a[5,4]
因此可以看成一个矩阵,a[4,2]即表示第4行、第2列的元素。由于计算机的存储器是一维的,要把二维数组的元素存放到存储器中,pascal是按行(第一个下标)的次序存放,即按a[1,1]a[1,2]a[1,3]a[1,4]a[2,1]…,a[5,4]的次序存放于存储器中某一组连续的存储单元之内。
对于整个二维数组的元素引用时,大多采用二重循环来实现。如:给如上说明的二维数组a进行赋值:a[i,j]=i*j。
for i:=1 to 5 do
for j:=1 to 4 do
a[i,j]:=i*j;
对二维数组的输入与输出也同样可用二重循环来实现:
for i:=1 to 5 do
begin
for j:=1 to 4 do
read(a[i,j]);
readln;
end;
for i:=1 to 5 do
begin
for j:=1 to 4 do
write(a[i,j]:5);
writeln;
end;
三、多维数组的应用示例
例1设有一程序:
program ex5_3;
const n=3;
type matrix=array[1..n,1..n]of integer;
var a:matrix;
i,j:1..n;
begin
for i:=1 to n do
begin
for j:=1 to n do
read(a[i,j]);
readln;
end;
for i:=1 to n do
begin
for j:=1 to n do
write(a[j,i]:5);
writeln;
end;
end.
且运行程序时的输入为:
2□1□3←┘
3□3□1←┘
1□2□1←┘
则程序的输出应是:
2□3□1
1□3□2
3□1□1
例2 输入4名学生数学、物理、英语、化学、pascal五门课的考试成绩,求出每名学生的平均分,打印出表格。
分析:用二维数组a存放所给数据,第一下标表示学生的学号, 第二个下标表示该学生某科成绩,如a[i,1]、a[i,2]、a[i,3]、a[i,4]、a[i,5]分别存放第i号学生数学、物理、英语、化学、pascal 五门课的考试成绩,由于要求每个学生的总分和平均分, 所以第二下标可多开两列,分别存放每个学生5门成绩和总分、平均分。
源程序如下:
program ex5_4;
var a:array[1..4,1..7]of real;
i,j:integer;
begin
fillchar(a,sizeof(a),0);
{函数fillchar用以将a中所有元素置为0}
writeln('Enter 4 students score');
for i:=1 to 4 do
begin
for j:=1 to 5 do {读入每个人5科成绩}
begin
read(a[i,j]);
{读每科成绩时同时统计总分}
a[i,6]:=a[i,6]+a[i,j];
end;
readln;
a[i,7]:=a[i,6]/5;{求平均分}
end;
{输出成绩表}
writeln( 'No. Mat. Phy. Eng. Che. Pas. Tot. Ave.');
for i:=1 to 4 do
begin
write(i:2,' ');
for j:=1 to 7 do
write(a[i,j]:9:2);
writeln;
end;
end.
四、数组类型的应用
例3 输入一串字符,字符个数不超过100,且以"."结束。 判断它们是否构成回文。
分析:所谓回文指从左到右和从右到左读一串字符的值是一样的,如12321,ABCBA,AA等。先读入要判断的一串字符(放入数组letter中),并记住这串字符的长度,然后首尾字符比较,并不断向中间靠拢,就可以判断出是否为回文。
源程序如下:
program ex5_5;
var
letter : array[1..100]of char;
i,j : 0..100;
ch : char;
begin
{读入一个字符串以'.'号结束}
write('Input a string:');
i:=0;read(ch);
while ch<>'.' do
begin
i:=i+1;letter[i]:=ch;
read(ch)
end;
{判断它是否是回文}
j:=1;
while (j<i)and(letter[j]=letter[i])do
begin
i:=i-1;j:=j+1;
end;
if j>=i then writeln('Yes.')
else writeln('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阶方阵,则按上述算法可排成:
4 3 8
9 5 1
2 7 6
有了以上的算法,解题主要思路可用伪代码描述如下:
1 in p 2+1,yn /*排数的初始位置*/
2 a[i,j]1;
3 for k:=2 to nn do
4 计算下一个排数位置(i,j);
5 if a[i,j]<>0 then
6 ii-1;
7 jj-2;
8 a[i,j]k;
9 endfor
对于计算下一个排数位置,按上述的四种情形进行,但我们应先处理第三处情况。算法描述如下:
1 if (i=n)and(j=n) then
2 jj-1; /*下一个位置为(n,n-1)*/;
3 else
4 ii mod n +1;
5 jj mod n +1;
6 endif;
源程序如下:
program ex5_7;
var
a : array[1..99,1..99]of integer;
i,j,k,n : integer;
begin
fillchar(a,sizeof(a),0);
write('n=');readln(n);
i:=n p 2+1;j:=n;
a[i,j]:=1;
for k:=2 to n*n do
begin
if (i=n)and(j=n) then
j:=j-1
else
begin
i:=i mod n +1;
j:=j mod n +1;
end;
if a[i,j]<>0 then
begin
i:=i-1;
j:=j-2;
end;
a[i,j]:=k;
end;
for i:=1 to n do
begin
for j:=1 to n do
write(a[i,j]:5);
writeln;
end;
end.
练习:
1、 输入N个同学的语、数、英三科成绩,计算他们的总分与平均分,并统计出每个同学的名次,最后以表格的形式输出。
2、 输出杨辉三角的前N行(N<10)。
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
第十课 字符与字符串处理
一、字符、字符串类型的使用
(一)字符类型
字符类型为由一个字符组成的字符常量或字符变量 。
字符常量定义:
const
字符常量='字符'
字符变量定义:Ⅱ
Var
字符变量:char;
字符类型是一个有序类型, 字符的大小顺序按其ASCⅡ代码的大小而定。函数succ、pred、ord适用于字符类型。
例如:后继函数:succ('a')='b'
前继函数:pred('B')='A'
序号函数:ord('A')=65
例1 按字母表顺序和逆序每隔一个字母打印。即打印出:
a c e g I k m o q s u w y
z x r v t p n l j h f d b
程序如下:
program ex8_1;
var letter:char;
begin
for letter:='a' to 'z' do
if (ord(letter)-ord('a'))mod 2=0 then write(letter:3);
writeln;
for letter:='z' downto 'a' do
if (ord(letter)-ord('z'))mod 2 =0 then write(letter:3);
writeln;
end.
分析:程序中,我们利用了字符类型是顺序类型这一特性,直接将字符类型变量作为循环变量,使程序处理起来比较直观。
(二)字符串类型
字符串是由字符组成的有穷序列。
字符串类型定义:
type <字符串类型标识符>=string[n];
var
字符串变量: 字符串类型标识符;
其中:n是定义的字符串长度,必须是0~255之间的自然整数,第0号单元中存放串的实际长度,程序运行时由系统自动提供,第1~n号单元中存放串的字符。若将string[n]写成string,则默认n值为255。
例如:type
man=string[8];
line=string;
var
name:man;
screenline:line;
另一种字符类型的定义方式为把类型说明的变量定义合并在一起。
例如:VAR
name:STRING[8];
screenline:STRING;
Turbo Pascal中,一个字符串中的字符可以通过其对应的下标灵活使用。
例如:var
name:string;
begin
readln(nsme);
for i:=1 to ord(name[0])do
writeln(name[i]);
end.
语句writeln(name[i])输出name串中第i个字符。
例2 求输入英文句子单词的平均长度.
程序如下:
program ex8_2;
var
ch:string;
s,count,j:integer;
begin
write('The sentence is :');
readln(ch);
s:=0;
count:=0;
j:=0;
repeat
inc(j);
if not (ch[j] in [':',',',';','''','!','?','.',' ']) then inc(s);
if ch[j] in[' ','.','!','?'] then inc(count);
until (j=ord(ch[0])) or (ch[j] in ['.','!','?']);
if ch[j]<>'.' then writeln('It is not a sentence.')
else writeln('Average length is ',s/count:10:4);
end.
分析:程序中,变量s用于存句子中英文字母的总数,变量count用于存放句子中单词的个数,ch[j]表示ch串中的第j个位置上的字符,ord(ch[0])为ch串的串长度。程序充分利用Turbo Pascal允许直接通过字符串下标得到串中的字符这一特点,使程序比较简捷。
二、字符串的操作
(一)字符串的运算和比较
由字符串的常量、变量和运算符组成的表达式称为字符串表达式。
字符串运算符包括:
1.+:连接运算符
例如:'Turbo '+'PASCAL'的结果是'Turbo PASCAL'。
若连接的结果字符串长度超过255,则被截成255个字符。若连接后的字符串存放在定义的字符串变量中,当其长度超过定义的字符串长度时,超过部份字符串被截断。
例如:var
str1,str2,str3:string[8];
begin
str1:='Turbo ';
str2:='PASCAL';
str3:=str1+str2;
end.
则str3的值为:'Turbo PA'。
2.=、〈〉、〈、〈=、〉、〉=:关系运算符
两个字符串的比较规则为,从左到右按照ASCⅡ码值逐个比较,遇到ASCⅡ码不等时,规定ASCⅡ码值大的字符所在的字符串为大。
例如:'AB'〈'AC' 结果为真;
'12'〈'2' 结果为真;
'PASCAL '='PASCAL' 结果为假;
例3 对给定的10个国家名,按其字母的顺序输出。
程序如下:
program ex8_3;
var i,j,k:integer;
t:string[20];
cname:array[1..10] of string[20];
begin
for i:=1 to 10 do readln(cname[i]);
for i:=1 to 9 do
begin
k:=i;
for j:=i+1 to 10 do
if cname[k]>cname[j] then k:=j;
t:=cname[i];cname[i]:=cname[k];cname[k]:=t;
end;
for i:=1 to 10 do writeln(cname[i]);
end.
分析:程序中,当执行到if cname[k]>cname[j]时,自动将cname[k]串与cname[j]串中的每一个字符逐个比较,直至遇到不等而决定其大小。这种比较方式是计算机中字符串比较的一般方式。
三、字符串的函数和过程
Turbo Pascal提供了八个标准函数和标准过程,见下表,利用这些标准函数与标准过程,一些涉及到字符串的问题可以灵活解决。
| 函数和过程名 | 功 能 | 说 明 |
| 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 | 在前面几章中我们用到了整型、实型、布尔型、字符型的数据。以上数据类型是由pascal规定的标准数据类型,只要写integer,real,boolean, char, pascal 编译系统就能识别并按这些类型来处理。pascal还允许用户定义一些类型,这是其它一些语言所没有的,这就使得pascal使用灵活、功能丰富。 一、枚举类型 (三)枚举类型的性质 三、集合类型 集合是由具有某些共同特征的元素构成的一个整体。在pascal中,一个集合是由具有同一有序类型的一组数据元素所组成,这一有序类型称为该集合的基类型。 四、记录类型 begin
练习 1.一家水果店出售四种水果,每公斤的价格是:苹果1.50元,桔子1.80元,香蕉2.0,菠萝1.60元。编一个程序,使售货员只要从键盘输入货物的代码及重量,计算机便能显示货物的名称、单价、重量及总价。 4. 输入五个学生的出生日期(月/日/年)和当天的日期,然后用计算机计算出每个人到当天为止的年龄各是多少?(如某人1975年10月1日出生,今天是94年12月1日,则他的年龄应为19岁,而另一人的出生日期为76年12月30日,则他的年龄为17岁。)
第十二课过程与函数
前面我们曾经学习了程序设计中的三种基本控制结构(顺序、分支、循环)。用它们可以组成任何程序。但在应用中,还经常用到子程序结构。 二、过程 (二)全程变量、局部变量及它们的作用域 四、过程和函数的嵌套 begin 例6 编写一个给一个分数约分的程序。 练习 1. 输入5个正整数求它们的最大公约数。(提示:可用一个数组将5个数存放起来,然后求第一个数和第二个数的公约数,再求第三个数与前两个数公约数的公约数,这样求得前三个整数最大公约数……如此类推可求出5个整数的最大公约数)
第十三章 动态数据类型
前面介绍的各种简单类型的数据和构造类型的数据属于静态数据。在程序中,这些类型 一、指针的定义及操作 ②一个指针变量只能存放一个地址。如再一次执行New(p)语句,将在内存中开辟另外一个新的整型变量存储单元,并把此新单元的地址放在p中,从而丢失了原存储单元的地址。 (四)对指针变量的操作
在DOS操作中,我们所谈及的文件称之为外部文件。外部文件是存储在外部设备上, 如:外存储器上,可由计算机操作系统进行管理,如用dir、type等命令直接对文件进行操作。 一、文本文件 例5 读入一个行长不定的文本文件。排版,建立一个行长固定为60个字符的文件, 排版要求:(1)当行末不是一个完整单词时,行最后一个字符位用'-'代替, 表示与下一行行头组成完整的单词;(2)第一行行头为两个空格,其余各行行头均不含有空格。 二、有类型文件 例7 产生数1-16的平方、立方、四次方表存入有类型文件中, 并用顺序的方式访问一遍,用随机方式访问文件中的11和15两数及相应的平方、立方、四次方值。 三、综合例析 程序: 字符串函数 求长度length 复制子串copy 插入子串insert 删除子串delete 字符串转为数值val 求绝对值函数abs(x) 取整函数int(x) 四舍五入函数round(x) 取小数函数frac(x)
附录三 关于fillchar的使用和讨论 大家听说过fillchar这个标准过程吧。 很好用的。 执行fillchar(a,sizeof(a),0); 执行fillchar(a,size(a),1);
附录五 程序的调试(一) ——步骤法 任何一个天才都不敢说,他编的程序是100%正确的。几乎每一个稍微复杂一点的程序都必须经过反复的调试,修改,最终才完成。所以说,程序的调试是编程中的一项重要技术。我们现在就来掌握一下基本的程序调试。 var i:integer; begin for i:=1 to 300 do begin if i mod 2 = 0 then if i mod 3 = 0 then if i mod 5 = 0 then writeln(i); end; end. 该程序是输出300以内同时能被2,3,5整除的整数。 现在我们开始调试。 调试有多种方法,先介绍一种,权且叫步骤法,步骤法就是模拟计算机的运算,把程序每一步执行的情况都反映出来。通常,我们有F8即STEP这个功能来实现,如图: var i:integer; a,b,c:boolean; begin for i:=1 to 300 do begin a:=false; b:=false; c:=false; if i mod 2 = 0 then a:=true; if i mod 3 = 0 then b:=true; if i mod 5 = 0 then c:=true; if a and b and c then writeln(i); end; end. 如图,我们单击菜单栏中debug选项,里面有一项叫watch的选项,我们单击它。 程序的调试(二) ——断点法
在前面我们已经学习了基本的程序调试方法——步骤法。步骤法有一个缺点,就是在遇到循环次数比较多或者语句比较多的时候,用起来比较费时,今天我们来学习一种新的也是常用的调试方法——断点法。 请记住,计算机是执行到断点行之前的一行,断点行并没有执行,所以这时b:=true这一句并没有执行。
附录六 Pascal的多种退出语句用法
1、 break 是用来退出其所在的循环语句
即 : 不论在任何一个循环语句中 执行了 break 的话, 马上退出这个语句。 可见 第一次循环 时 , 执行了{1}句 后 , 执行 break ,然后马上退出了这个for语句。 {*****} 注意 : 以上两个语句 只 对 它们所在的 那层循环语句 起作用,也就是说 : 如果有多个 循环语句 相嵌套, 其中 某一层 执行了continue / break 语句, 它们并不能影响上面几层的循环语句。 2、exit 是退出当前程序块; 即 : 在任何子程序 中执行 exit , 那么 将退出 这个子程序;如果是在 主程序中执行 exit , 那么将退出整个程序。相当于 : goto 这个程序块 的 末尾 的 end 例如 : 试除法判断素数时,一旦整除,就把函数值赋为false ,然后exit;{******}注意 : 类似上面的 , exit也是只对当前 这一个 子程序产生作用,如果多重嵌套子程序 , 那么其中某个子程序执行了exit以后,将返回到 调用它的那个语句 的下一个语句。 3、halt : 没什么好说的,退出整个程序,Game Over. 例如 : 搜索时, 一旦找到一个解,就打印,然后执行halt,退出整个程序。使用exit , halt 应该注意的地方:要注意所有可能会退出 子程序或主程序 的地方 均要妥善处理好善后工作,比如 文件是否关闭 ,输出是否完整等。 最后说一句 , 使用这些语句 使得程序结构不止有一个出口,破坏了结构化程序设计的 标准控制结构 , 使程序难以调试 (但是往往便于编写),应尽量避免使用,因为它们完全可以用其它语句代替,所以,除非使用这些语句 能给 编写程序 带来 较大的方便,且可读性不受到影响,才值得一用。 转载于:https://www.cnblogs.com/Chaobs/p/3838433.html 需要做网站?需要网络推广?欢迎咨询客户经理 13272073477
|