admin 管理员组

文章数量: 1086019


2024年12月31日发(作者:log4j2阿里被处罚)

第一课时:初识Pascal语言

信息学奥林匹克竞赛是一项益智性的竞赛活动,同数学、物理、化学、生物一起被称为五大联赛,其

核心是考查选手的智力和使用计算机解题的能力。选手首先应针对竞赛中题目的要求建构数学模型,进而

构造出计算机可以接受的算法,之后要写出高级语言程序,上机调试通过。程序设计是信息学奥林匹克竞

赛的基本功,在青少年朋友参与竞赛活动的第一步必须掌握一门高级语言及其程序设计方法。

一、Pascal 语言概述

PASCAL语言也是一种算法语言,它是瑞士苏黎世联邦工业大学的N.沃思(N. Wirth)教授于1968年

提出来的,它命名是为了纪念法国数学Pascal。它的建立基于两个目的:第一,提供一种能够清晰、自然

地表述某些基本概念的语言,使其成为基本概念系统的训练工具,适合于程序设计教学,第二,使新定义

的语言能在现有的计算机上可靠的、有效的加以实现。

二、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,

下面我们就来学习Turbo Pascal 7.0系统的使用。

1. 系统的启动

在桌面上运行快捷方式或在系统目录下的启动程序,即可启动系统。屏幕上出现如图1

所示的集成环境。

2. Turbo Pascal系统集成环境简介

最顶上一行为主菜单。中间蓝色框内为编辑窗口,在它的编辑窗口内可以进行程序的编辑其使用方法

同其它文本编辑器相类似。最底下一行为提示行,显示出系统中常用命令的快捷键,如将当前编辑窗口中

文件存盘的命令快捷键为F2,获得系统帮助的快捷键为F1,等等。

2

3.菜单选择:

菜单的选取可使用鼠标,或者使用相应的快捷方式,如:选择”file”,可以使用ALT+F;

4. 新建程序窗口

按F10进行主菜单,选择FILE菜单,执行其中New命令。就可建立一个新的程序窗口(默认文件名

为或等)。

5. 程序的输入、编辑与运行

在当前程序窗口中,一行一行的输入程序。事实上,程序窗口是一个全屏幕编辑器。所以对程序的编

辑与其它编辑器的编辑方法类似,这里不再重复。

当程序输入完毕之后,一般要先按Alt+F9(或执行compile菜单中compile命令)对程序进行编译。

如果程序有语法错误,则会在程序窗口的第一行处显示第一个红色错误信息。若无语法错误,则窗口正中

央会出现一个对话框,提示编译成功。接下来,我们可以运行程序了。

程序的运行可以通过按ALT+R打开RUN菜单中的RUN命令,或直接按快捷键CTRL+F9。则可以在

用户窗口中输出运行结果。通常在程序运行结束后系统回到Pascal系统的集成环境,因此要查看运行结果,

要按ALT+F5将屏幕切换到用户屏幕。

5.程序的保存与打开

当我们想把程序窗口中的程序存入磁盘时,可以通过按F2键(或执行File菜单中的save命令)来保存

程序。第一次保存文件时屏幕上会出现一个对话框要求输入文件名(默认扩展名为.pas)。

当我们要将磁盘上的程序文件中的PASCAL程序装入窗口时,可按F3(或执行File菜单中的Open命

令)来装入程序,此时系统也会弹出一个对话框要求输入要打开的文件名,或直接在文件对话框列表中选择

所要的文件,然后回到打开文件。

五、第一个程序

输入正方形(rectangle)的长和边,求其周长。

program rectangle(input,output);

var

l,a,b:integer;

begin

read(a,b);

l:=2*a*b;

write(l);

end.

请输入上面的程序,并练习将其存盘、打开与运行上面程序。

【作业】

1、输入长方形的长和宽,求其面积。

第二课:标准数据类型(一):实型和整型

在上节课我们学习了Pascal语言的程序结构,在一程序中,程序的所有操作都由d.中的的语

句来完成,语句的执行依赖于数据的类型,如果运算和它的数据类型不一致,编译将给出错误的信息,导

致程序无法运行。这节课我们将学习Pascal标准的数据类型(实型、整型、字符型、布尔型)。

一、实型(real)

实型是最常用的数据类型,包括正数、负数和0。

1.在Pascal中,实数有两种表示方法:小数表示法和指数表示法(或称科学表示法)。

小数表示法: 以小数的形式来表示,如:1.25,3.1415926,0.0等。

3

科学表示法:用e后的数字代表10的幂,如:

1.25e0=1.25

1.23e+2=123

2.4e-3=0.0025

-1.56e1=-15.6

『注意』:在小数表示法中必须有小数点,且小数点前后必须有数字(0~9)。在科学表示法中必须有e,

且有的前后必须有数字。如果实数太大或太小,用科学表示法比较方便。

2.实数表示的范围。

在turbo Pascal中实数表示的范围为:-1.7e38~-2.9e39,0,2.9e-39~1.7e38。

3.实型量的运算

实型量的运算有:+(加)、-(减)、*(乘)、/(除),在pascal语言中表达式的计算先乘后加减的次

序进行。通过括号可以改变运算的先后顺序。在有括号时,先执行括号内的运算,再执行括号外的运算。

如以下数学表达式和Pascal表达式的不同。

数学表达式

Pascal表达式

b*b-4*a*c

(a+b)/(c+d)

(a+b)/c+d

e-a*b/(c*d)或e-a*b/c/d

4.实型量常用的标准函数

abs(绝对值)、sqr(平方)、sqrt(开方)、trunc(取整)、round(舍入),Pascal语言规定,所有函数的自变量

必须写在括号内。例如:

可表示为:abs(-5)

可表示为:x*x*x或aqr(*)*x

可表示为:sqr(a+b)

可表示为:sqrt(sqr(b)-4*a*c)

trunc是去掉小数部份,取其整数。round是将小数部份四舍五入后变为整数,其返回值均为整型。如:

trunc(1.3)=1 round(1.3)=1

trunc(1.5)=1 round(1.5)=2

turnc(-2.6)=-2 round(-2.6)=-3

二整型(integer、longint)

整型包括正整数、负整数和零。

1.整的范围:

在Pascal语方中有两种整型,一种是普通整型,另外一处是长整型。

整型(integer):

-maxint-1~maxint

4

长整型(longint): -maxlongint-1~maxlongint

在pascal系统语言中,定义了两个特殊的整型变量,maxint,maxlongint

在不同的系统中有不同的值。

2.整型量的运算符。

+(加)、-(减)、*(乘)、/(除)、DIV(整除)、MOD(取余)

DIV的结果是整数商、MOD的结果是整数后的余数。

7 DIV 3=1 7 mod 3=1

-7 DIV 3=-1 -7 MOD 3=-2

7 DIV -3=1 7 MOD -3=-2

3.整型量的标准函数。

abs(绝对值)、sqr(平方)、pred(前导)、succ(后继)、odd(奇函数)chr(取字符)等。

pred(5)=4、pred(-5)=-6

succ(5)=6、succ(-5)=-4

对于odd函数,当自变量为奇数时,返回值为(true)、当自变量为偶数时,返回值为假。如:

odd(5)=ture odd(6)=false

取字符函数(chr)是将自变量(整型)作为字符的序号,并将与此序号对应的字符作为函数的结果。如:

chr(65)='A' chr(66)=„B‟

三、常量与变量

(1)常量:

在程序运行过程中,其值不能被改变的量称为常量。3.1415926、„A‟、100等。在程序中常见的常量

有整型常量、实型常量、字符型常量、布尔常量。

常量的定义。

定义符号常量的一般格式:

CONST

<常量标识符>=<常量>

『说明』:常量说明部分以关键字const开头, 后面的标识符为常量标识符,其中"="号后的常量为整数、

实数、字符、 字符串(字符、字符串常量在后面章节中将作介绍)。而且,在常量说明部分可以将几个常

量说明成符号常量,共用一个关键字"const"。例如:

const

pi=3.1415926;

ch='A';

在以上的定义中pi作实型常量、ch作为符号常量,分别代表实数3.1415926和字符'A'。也就是说,常

量说明部分既定义了常量名及其值,又隐含定义了常量的类型。

对于符号常量,应注意下列几点:

(1)符号常量一经定义,在程序的执行部分就只能使用该常量标识符,而不能修改其值。

(2)使用符号常量比直接用数值更能体现"见名知义"的原则,也便于修改参数,故一个较好的程序中,

应尽量使用符号常量,在执行部分基本上不出现直接常量。

(2)变量

变量代表了一个存储单元,在程序运行中的值是可变的,故称为变量。 变量有三个要素是:变量

名、变量类型、变量值。

一个程序中可能要使用到若干个变量,为了区别不同的变量,必须给每个变量(存贮单元)取一个名

(称为变量名),该变量(存贮单元)存放的值称为变量的值,变量中能够存放值的类型为变量的类型。

5

1.变量名

用一个合法的标识符代表一个变量。如n,m,rot,total 等都是合法变量名。在程序中用到的变量必须在

说明部分加以说明,变量名应遵循自定义标识符的命名规则,并注意"见名知义"的原则,即用一些有意义

的单词作为变量名。

"自定义标识符"的命名规则为:自定义标识符必须以字母(包含下划线"_")开头,后面的字符可以是

字母或数字。标识符长度不超过63个字符。

2.变量的类型

常量是有类型的数据,变量在某一固定时刻用来存放一个常量,因此也应有相应的类型。如整型变量

用来存放整数,实型变量用来存放实数(也可用于存入整数)。

3.变 量说明

在程序中若要使用变量,变量的名称及类型在程序的变量说明部分加以定义,变量的值则在程序的执

行部分中才能赋给。

变量说明的一般格式:

VAR

<变量标识符>[,<变量标识符>]:<类型>;

(中括号内部分表示可省,下同)

其中VAR是pascal保留字,表示开始一个变量说明段, 每个变量标识符或由逗号隔开的多个变量标识,

必须在它的冒号后面说明成同一类型。一个程序中,可以说明许多不同类型的变量,每种类型变量之间用

分号隔开,共用一个VAR符号。

例如:

var

r,l,s:real;

其中,Integer(整型)、Real(实型)是标准标识符, 它们是"类型标识符",代表了确定的类型,如r,l,s

定义为实变量。

一旦定义了变量,就确定了它的类型,也就是说,就确定了该变量的取值范围和对该变量所能进行的

运算。

四、具体实例

例1:输入两位整数,反序输出。

输入形式:23

输出形式:32

program exp1;

var

n,a,b:integer{n代表整数、a代表十位、b代表个位}

begin

read(n); {读入整数n}

a:=n div 10;{求十位数字}

b:=n mod 10;{求个位数字}

n:=b*10+a; {反序}

write(n);

end.

例2:求二元一次方程的解(输入系数要确保二元一次方程有解,且为标准二元一次方程)。

输入形式:1 1 2

1 -1 0

输出形式:1.00 1.00(保留两位有效数字)

分析:设二元一次方程的一般表达式为:

6

程序如下:

program exp2;

var

a,b,c,d,e,f:real;

begin

read(a,b,c,d,e,f);

x:=(b*f-e*c)/(d*b-a*c);

y:=c-a*x/b;

write(x:4,y:4);

end.

【作业】

1.将下列数学表达式转换成Pascal表达式。

2.写一个程序,输入三角形的三个

边a,b,c,计算并打印的面积S。计算三解开公式为:

7

3.输入三位数,反序输出。

输入形式:

123

输入形式:321

第三课:标准数据类型(二):字符型、布尔型

一、字符型(char)

1.在pascal语言中,字符型是括在单引号中的一个字符,所有字符来ASCII字符集,共有256个字符。

如'a','A'.'0'等,而'abc'则不是字符类型。特殊地,对于单引号字符,则示成''',对于ASCII字符集中,按每个

字符在字符集中的位置,每个字符集编号为0~255,编号对应字符集序号(见ASCII表)。

2.用于字符集的标准函数。

ord (取序号) pred(前导) succ(后继)如:

ord('A')=65 ord('a')=97 ord 与chr 是互逆函数,即:

ord(chr(97))=97 chr(ord('a'))='a'

pred('b')='a' succ('a')='b'

pred与succ也是互逆函数。

pred(succ('b'))='b' succ(pred(b))='b'

二.布尔型(boolean)。

1.布尔类型的值只有两个:false(假)和true(真)。且false对应的序号为0,true对应的序号为1。

2.布尔类型的标准函数。

ord(取序号) pred(前导) succ(后继)

ord(false)=0 ord(ture)=1

pred(ture)=false pred(false)=true

『注意』false没有前导,true没有后继。

三、算术表达式与赋值语句。

(一)表达式,在这里我们只介绍算术表达式。

1.算术表达的定义

Pascal语言的算术表达式是由符合pascal语法规定的运算对象(包括常量、变量、函数)、算术运算符、

圆括号组成的有意的式子。如:pi*r*r。

2.算术运算符

常用的有以下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 div b)*b。

3.运算优先顺序

如果一个表达式里出现两个或两个以上的运算符, 则必须规定它们的运算次序。pascal规定:

①表达式中相同优先级的运算符,按从左到右顺序计算;

②表达式中不同优先级的运算符,按从高到低顺序计算;

8

③括号优先级最高,从内到外逐层降低;

在算术运算中运算符的优先顺序与数学上的四则运算一致,即"先乘除后加减"(注:"MOD"、"DIV"运算

的优先级与"*"、"/"相同)。

『注意』:

a.所有表达式必须以线性形式写出。因此分子、分母必须写在同一行上。

b.只以使用合法的标识符。

c.为了指定运算的顺序可以使用括号,括号必须是成对出现,且括号只能使用小括号“()”,而不能使

用其它括号。如"{","}",或"[","]"。

(二)赋值语句

变量既然代表一个存储单元,其值是可变的,那么其中的值是怎么提供的,又是怎么改变的呢?可以

通过赋值语句来进行。

1、 赋值语句的格式

变量名:=表达式;

其中":="称为赋值号。

2、 执行过程

计算机先计算赋值号右边表达式的值,然后将表达式的值赋给变量名代表的变量。如:x:=(2+3)

*4; x:=-x(其意义是将变量x值取反后,存入x)。

『注意』:

a.表达式的类型与左边的变量类型应相同。

b.表达式的类型为整型,变量的类型可为实型。

四.输入、输出语句

(一)输入语句(read、readln)

语句

read语句的形式为:read(<输入表>)

即:read(x1,)

read语句的输入表至少包括一个变量,且变量必须先定义,变量的数据类型必须与输入类型相同,并

且顺序相同。如果输入变量是实型。输入时也可输入整型。

演示程序

program exe;

var

x1,x2:integer;

begin

read(x1,x2);

writeln('x1=',x1);

writeln('x2=',x2);

end.

运行程序后,输入以下数据,观察结果。

①1 2 [ENTER]

②1 2 3 [ENTER]

③1 [ENTER]{程序会等待继续输入}

④1 [enter]

2 [enter]

⑤1 a [enter]{出错}

『注意』:在turbo pascal中不同类型的数据,不能用同一个read语句输入。在字符变量输入时,中间不需

用空格。

9

a.表达式的类型与左边的变量类型应相同。

b.表达式的类型为整型,变量的类型可为实型。

语句

readln语句的表现形式:readln(<变量表>)

即:readln;或 readln(x1,x2,...,xn);

readln语句后面可以没有变量,起到换行作用。readln语句执行完后,会自动地跳转到下一行。

演示程序

program exe;

var

x1,x2,x3,x4:integer;

begin

readln(x1,x2);

readln(x3,x4);

writeln('x1=',x1,'x2=',x2,'x3=',x3,'x4=',x4);

end.

运行程序后,输入以下数据,观察结果。

①1 2 [ENTER

3 4 [enter]

②1 2 3 4 [ENTER]{程序会等待继续输入}

③1 2 3 4 [ENTER]

5 6 7 8 [enter]

④1 [enter]

2 [enter]

3 4 [enter]

⑤1 2 [enter]{出错}

3 a

(二)输出语句(write,writeln)。

,writeln语句的表现形式:write(<输出表>)

write(x1,x2,...,xn),writeln;,writeln(x1,x2,...,xn)

两者的区别

①write语句的输出表至少有一个输出项,而writeln后面可以没有,表示换行。

②write语句输出后不换行,而writeln语句输出后换行。

演示程序

program exe;

var

x1,x2:integer;

begin

read(x1,x2);

write('x1=',x1);

{writeln('x1=',x1)}

write('x1+x2=',x1+x2);

end.

运行程序观察输出结果。从以上的程序我们还可以看出,write、writeln的"输出表"可以为表达式、字

符串、变量。

2.输出格式。

a.固定格式

10

在write输出语句中如果不加场宽说明,则按标准场宽输出:实型以科学表示法输出,占17位;整数

以实际长度输出,字符型占1位,布尔型输出"false","true"。分别占5位和4位。当输出值不满规定场宽时,

左边以空格代替。

如:当x=1,y=1.0,bool=true,ch'a'时,执行输出语句。

write(x,y,bool,ch);观察结果。

b.自定义格式

【单场宽】

在输出数据时,可以加场宽说明来改变输出项所占的宽度。场宽说明是在输出项后加冒号,再加整型

表达式或整数。

write(<输出表>:<整数表达式>)

观察以下输出形式:x=34;y='a';

write(x:1);write(x:3);write(y:6);

从以上输出结果可以看出,输出结果是右对齐,当字符或整数的位数小于场宽时,左边补空格,当字

符或整数的位大于场宽时,按字符或整数的实际位数输出。对于实型数,当场宽说明较小时,输出小数位

将减少,但无论场宽说明多么小,输出时将至少保留一位。

【双场宽】

对于实型数可用双场宽来控制输出形式,其中,第一个场宽表示总宽度,第二个场宽表示小数的位数。

write(<输出表>:场宽1:场宽2)

五实例

例1:输出如下字符。

*****

*

*

*****

*

*

*****

此题可以用字符的单场宽来输出。

program exe;

begin

writeln('*****');

writeln('*':3);

writeln('*':3);

writeln('*****');

writeln('*':3);

writeln('*':3);

writeln('*****');

end.

例2.某仓库5月1日有粮食100吨,5月2日又调进20吨,5月3日卖出库存的3分之二,5月4日

又调进库存的3倍粮食,问该仓库从5月1日到5月4日期间每天的粮食分别是多少吨?(输出每天的库存

量)

分析:在这个问题中,主要要描述从5月1日到5月4日期间仓库的粮食库存量,且易知它是不断变

化的。因此我们可以用一个变量A来描述仓库的粮食库存量。

程序可写如下:

Program ex1;

Var

11

x: integer;

Begin

x:=100;Writeln('5/1:',x);

x:=x+20;Writeln('5/2:',x);

x:=x div 3; writeln('5/3:',x);

x:=x *4; writeln('5/4:',x);Readln;

End.

【作业】

1. 输入两个字符,使其值交换后输出,完善程序.

Program exe (input, output);

Var

ch1, ch2: char;

—————;

begin;

read(ch1,ch2);

——————;

——————;

——————;

writeln (ch1,ch2);

end.

2.有三个小朋友甲乙丙。甲有50粒糖果,乙有43粒糖果,两有13粒糖果。现在他们做一个游戏。从甲开

始,将自己的糖分三份,自己留一份,其余两份分别给乙与丙,多余的糖果自己吃掉,然后乙与丙也依次

这样做。问最后甲、乙、丙三人各有书多少粒糖果?

输入形式:50 43 13

输出形式:51 35 16

3. 输入两个两位数,求其竖式乖法。

输入形式:12 23

输入形式:

12

*23

---------

36

+24

---------

276

第四课:关系表达式、布尔表达式及简单的IF语句

一、关系表达式。

1.什么是关系表达式。

用小括号(),>,<,>=,<=,<>,=将两个算术表达式连接的式子。如(3+7)>2,2*5>10等。

2.关系表达式的值。

关系表达式可以用于整型、实型、字符型、布尔型,结果为布尔型,一般地,关系表达式两边的量要

为同一类型,但整型和实型可以混合使用。

12

如:3<5 结果为 ture

„a‟>'b'结果为 false

false

用关系表达式表示下列命题:

m为偶数:m mod 2=0;

n为正数:n>0;

二、布尔运算及布尔表达式。

有时我们为了表达一个复杂的命题。用关系表达式不能完成,比如:

m,n都是偶数或奇数、三条边能否构成一个三角形...,此时我们必须用到布尔表达式。

1.定义

用布尔运算符把一个或多个关系表达式连接起来的式子。(x>3)and(x<5)。

2.布尔表达式的运算符。

and(与)、or(或)、not(非),这三个运算符的运算对象为布尔量,其中not为单目运算,只有一个运算对

象,and与or为双目运算,有两个运算对象。它们的运算真值表关系表如:

b1

false

false

true

true

b2

false

true

false

true

NOT b1

true

true

false

false

b2 ANb2

false

false

false

true

b1 or b2

false

true

true

true

如果一个表达式里出现多个算术运算符运算符, 则必须规定它们的运算次序。pascal规定:

①表达式中相同优先级的运算符,按从左到右顺序计算;

②表达式中不同优先级的运算符,按从高到低顺序计算;

③括号优先级最高,从内到外逐层降低;

对于一个复杂的表达式可能同时包含算术运算、关系运算和逻辑运算以及函数运算。运算的优先顺序

为:

括号 、函数 、not 、* / div mod 、and、 + - 、or、关系运算符(> >= = <> < <=)。

m,n同为奇数或偶数。

(m mod 2=0) and (n mod 2=0) or (m mod 2=1) and (n mod 2=1)

构成abc三角形三边的条件

(a+b>c)and(a+c>b)and(b+c>a)

判断整数n是否为一个三位。

(n>=100) and (n<=999)

界于3和5之间的实数。

(x>3) and (x<5)

三、简单的IF语句

1.格式

<布尔表达式>THEN 语句;

<布尔表达式>THEN 语句1 ELSE 语句2;

(注意Ⅱ型IF语句中语句1后无";"号)

2、功能

13

a.执行IF语句时,先计算<布尔表达式>的值,若为TRUE则执行语句,否则不执行任何操作。

b.执行IF语句时,先计算<布尔表达式>的值,若为TRUE则执行语句1,否则执行语句2;

3、具体实例

例1.输入一个整数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.火车托运行李,要根据行李的重量按不同的标准收费。不超过50kg,按每公斤0.35元。若超过50kg,

50kg按每公斤0.35元。其余超过部分每公斤0.5元收费,现输入托运重量,输出托运费用。

分析:此题我们设托运重量为W,手运费为P,要据题义,我们总结出数学表达式为:

从而程序如下:

program exe;

var

w,p:real;

begin

read(w);

if w<=50

then p:=w*50

else p:=50*0.35+(w-50)*0.5;

writeln('Pay=',p);

end.

例3.输入三个数,输出最大值。

分析:我们将三个数的标识符分别高为x1,x2,x3,最大值设为max,要求出最大值我们只需比较两次即

可。第一次比较两个数x1,x2,得出最大值为max,然后比较x3同max的大小。

程序如下:

program exe;

var

x1,x2,x3:integer;

begin

read(x1,x2,x3);

if x1>x2

then max:=x1

else max:=x2;

if x3 >max

then max:=x3;

writeln(max)

end.

14

【作业】

1.用布尔表达式表达下面的意思。

1)i 被j 整数。

2)n 是小于正整数K的偶数

3)实数x 不属于于下图中阴影部份。

2.魏晋南北朝的数学典籍《孙子算经》中载:“有物不知其数,三三数之剩二,五五数之剩三,七七数

之剩二,问物为几何?”试写出满足此数的布尔表达式(设此数为N)。

3.新汇丰超市里卖电池,每个电池8角钱,若数量超过10个,则可打75折。输入电池的个数,输入所

需的钱。

输入方式:15

输入方式:9

4.某车站行李托运收费标准是:10公斤或10公斤以下,收费2.5元,超过10公斤的行李,按每超过1

公斤增加1.5元进行收费。 试编一程序,输入行李的重量,算出托运费。

输入方式:12

输出方式:28

5.输入x的值,计算y的值。

第五课:if嵌套语句

一、复合语句。

我们在上节课学习IF语句中,在THEN或者ELSE后的语句可能不止一个,这时我们要用到复合语

句的概念,复合语句是一个以BEGIN开始,以END结束的语句。在BEGIN与END之间可以包含若干个

语句,第个语句都以分号隔开。一般形式为:

BEGIN

<语句1>;

<语句2>;

...;

<语句n>

END;

在IF语句中,如果THEN和ELSE后各包括几个语句,它们必须写成复合语句,一个复合语句从外

部看来,相当于一个语句。

例1:读入两个数,将大数存于x,小数存于y。

分析:对于此题,要将两个数交换,我们必须设置一个中间变量t。交换时,将x中原来的数存入t,

将y中的数存入x,再将t中的数存入y即可。

program exe;

15

var

x,y,t:real;

begin

readln(x,y);

if x

t:=x;

x:=y;

y:=t

end;

writeln('x=',x,'y=',y);

end.

例2:读入3个数,将最大数输出。

分析:在上节课中,我们做过这个题目,本节课我们换一种思路来解此题:当第一个数小于第二个数

和时,把每个数和第二个数相交换,再把第一个数同第三个数比较。

program exe;

var

a,b,c,t:integer;

begin

readln(a,b,c);

if a

t:=a;

a:=b;

b:=t;

end;

if a>c then writeln(a)

else writeln(c)

end.

二、嵌套IF语句。

在IF语句中,THEN或者ELSE后的语句本身也是一个IF语句,称作IF语句的嵌套。主要有以下两

种形式。

I型

II型

if <条件1> if <条件1>

then <语句1> then if <条件2>

else if <条件2> then <语句1>

then <语句2> else <语句2>

else <语句3>

else <语句3>

例3:输入某学生的成绩,根据成绩的好环输出评语,如果成绩在90分以上,输入出'A',如果成绩在60~

90分之间,输出'B',如果成绩在60分以下,输出C。

分析:此题我们可以利用IF的嵌套语句,根据不同的划分可以用不同的IF嵌套语句。我们首先判断

成绩是否在60分以上,若是,再判断成绩是否在90分以上,若是则输出相应的评语A,否则(60~90)输

出评语B,若在60分以下,输出评语C,此时用II型;我们也可以首先判断分数是否在90分以上,如果是,

则输出评语A,再判断分数是否在60分以上,若是,则输出评语B,否则输出评语C,此时我们I型。

I型方式:

program exe;

var

16

s:real;

begin

readln(s);

if s>=60

then if s>=90

then writeln('A')

else writeln('B')

else writeln('C');

end.

II型方式

program exe;

var

s:real;

begin

readln(n);

if s>=90

then writeln('A')

else if s>60

then writeln('B')

else writeln('C')

end.

此两种语句嵌套IF语句虽然在形式上不一样,但完成的功能是相同的。

对于一个嵌套IF语句,有时我们也可用几个简单的IF语句来代替。如上题我们也可以用以下方式来

完成。

program exe;

var

s:real;

begin

if s>=90

then writeln('A');

if (s>=60)and(s<90)

then writeln('B');

if s<60

then writeln('C');

end.

例4.输入三个数,输出最大数。

对于此题,我们以上两种不同的方法做过,此时我们用IF嵌套语句来完成。

program exe;

var

a,b,c,max:real;

begin

readln(a,b,c);

if a>b

then if a>c

then max:=a

else max:=c

17

else if b>c

then max:=b

else max:=c;

writeln('max',max);

end.

例5 计算下列函数

分析:根据输入的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;

18

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;

【作业】

1

编写程序,根据输入的x的值,计算y的值。

2 对于一批货物收取税金,价格在1万元以上的货物征税5%,在5000元以上,1万元以下征税3%,

在1000元以上,5000元以下的货物征税2%,1000元以下的货物免税,写一程序,输入货物价格,计算并

输出税金。

3.输入某学生的成绩,若成绩在85分以上,输出very Good,若成绩在60分到85分,输出Good,若

成绩在60以下,输出no Good。

4.输入三个整数,由大到小输出。

5.输入两个正整数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

其中:

6.输入三角形的三个边,判断它是何类型的三角形(等边三角形?等腰三角形?一般三角形?)。

注意:等边三角形(equilateral triangle)

等腰三解形(isoceles triangle )

一般三角形(triangle)

第六课:Case语句

上面我们知道可以用嵌套的if语句实现多分支的选择结构。但是如果分支越来越多时,用嵌套的if

19

语句实现多分支就显得繁杂。当多分支选择的各个条件由同一个表达式的不同结果值决定时,可以用case

语句实现。它的选择过程,很象一个多路开关,即由case语句的选择表达式的值,决定切换至哪一语句去

工作。因此在分支结构程序设计中,它是一种强有力的手段。在实现多路径分支控制时,用case对某些问

题的处理和设计,比用if语句写程序具有更简洁、清晰之感。首先我们来看一个例子:

例1:若已知x在1到8之间,要按如下公式计算y.的值。

若用if语句,可写成:

if x<2

then y:=3*x+5

else if x<3

then y:=sqrt(1+sqr(x))

else if x<5

then y:=sqr(x)-1

else y:=x+10

如果使用case 语句,可以写成:

case trunc(x) of

1: y:=3*x+5;

2: y:=sqrt(1+sqr(x));

3,4: y:=sqr(x)-1;

5,6,7: y:= x+10;

end;

由上可能看出,用case语句比用if语句要简单和直观。

(一)、情况语句的一般形式:

case <表达式> of

<值表1>:语句1;

<值表2>:语句2;

:

<值表n>:语句n

end;

其中case、of、end是Pascal的保留字, 表达式的值必须是顺序类型,它可以是整型、布尔型及以后

学习的字符型、枚举型和子界型。情况标号表是一串用逗号隔开的与表达式类型一致的常量序列。语句可

以是任何语句,包括复合语句和空语句。

(二)、case语句的执行过程

先计算表达式(称为情况表达式)的值,如果它的值等于某一个常量(称为情况常量,也称情况标号),

则执行该情况常量后面的语句,在执行完语句后,跳到case语句的末尾end处。

(三)、说明

①情况表达式必须是顺序类型的;

②情况常量是情况表达式可能具有的值,因而应与情况表达式具有相同的类型;

③情况常量出现的次序可以是任意的;

④同一情况常量不能在同一个case语句中出现两次或两次以上;

20

⑤每个分语句前可以有一个或若干个用逗号隔开的情况常量;

⑥如果情况表达式的值不落在情况常的范围内,则认为本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

readln(x);

case trunc(x/100) of

0:y:=x+1;

1:y:=x-1;

else y:=0;

end;{end of case}

writeln('y=',y:8:2);

end.

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

分析:每年的1、3、5、7、8、10、12月,每月有31天,4、6、9、11每月有30天;2月闰年有29天,

平年有28天。

判断闰年的方法:年号能被4整除,但不能被100整除,或者年号能被400整除。

program exe;

var

year,month,day:integer;

begin

readln(year,month);

case month of

1,3,5,,7,8,10,12:days:=31;

4,6,9,11:days:=30;

2:if(year mod 4=0) and (year mod 100<>0)

or (year mod 400=0)

then days:=29

else days:=28;

writeln('days=',days);

end.

【作业】

21

1.输入班号,输出该班学生的人数:

班号

人数

91

30

92

32

93

30

94

30

95

32

96

25

2.输入x,y的值,根据所处象限,用相应公式计算Z值。(用case语句和if语句来完成)

3. 用case语句求分段函数的y的值。

4.未来临了,班长小Q决定将剩余班费X元钱,用于购买若干支钢笔奖励给一些学习好、表现好的同

学。已知商店里有三种钢笔,它们的单价为6元、5元和4元。小Q想买尽量多的笔(鼓励尽量多的同学),

同时他又不想有剩余钱。请您编一程序,帮小Q制订出一种买笔的方案。

输入:22

输出: 1 0 4(表示6元1支,5元0支,4元支)

第七课:For循环语句(计数循环)

在许多复杂的问题中,常常需要做大量重复的计算处理,尽管计算机的速度很快,然后要把这些大量

类同的计算机处理的每一步写成语句,并输入计算机中,其工作量相当大,有时是难以完成的。循环结构

程序设计帮助我们有效地解决这一问题,利用循环结构程序设计,使得我们有可能只编写少量语句,让计

算机重复执行,从而可完成大量同类计算。在Pascal语言中,循环结构程序通常由三种的循环语句来实现。

它们分别为FOR计数循环、While当值循环和Until直到循环。通常将一组重复执行的语句称为循环体,

而控制重复执行或终止执行由重复终止条件决定。因此,重复语句是由循环体及重复终止条件两部分组成。

本节,我们来学习For语句。

一、for语句的一般格式

I:for <循环变量>:=<表达式1> to <表达式2> do <语句>;

II:for <循环变量>:=<表达式1> downto <表达式2> do <语句>;

其中for、to、downto和do是Pascal保留字。表达式1 与表达式2的值也称为初值和终值。

例:求s=1+2+3+...+100的值:

I:for i:=1 to 100 do s:=s+i;

II:ro i:=100 downto 1 do s:=s+i;

二、For语句执行过程

①先将初值赋给左边的变量(称为循环控制变量);

②判断循环控制变量的值是否已"超过"终值,如已超过,则跳到步骤⑥;

③如果末超过终值,则执行do后面的那个语句(称为循环体);

22

④循环变量递增(对to)或递减(对downto)1;

⑤返回步骤②;

⑥循环结束,执行for循环下面的一个语句。

三、说明

①循环控制变量必须是顺序类型。例如,可以是整型、字符型等,但不能为实型。

例:输出字母表中28个字母:

for i:='a' to 'z' do write(i);

②循环控制变量的值递增或递减的规律是:选用to则为递增;选用downto则递减。

③所谓循环控制变量的值"超过"终值,对递增型循环,"超过"指大于,对递减型循环,"超 过"指

小于。

④循环体可以是一个基本语句,也可以是一个复合语句。

⑤循环控制变量的初值和终值一经确定,循环次数就确定了。但是在循环体内对循环变量的值进行修

改,常常会使得循环提前结束或进入死环。建议不要在循环体中随意修改控制变量的值。

⑥for语句中的初值、终值都可以是顺序类型的常量、变量、表达式。

四、应用举例

1.输出1-100之间的偶数。

program exe;

var

i:integer;

begin

for i:=1 to 100 do

if i mod 2=0 then write(i:5);

end.

或者:

program exe;

var

i:integer;

begin

23

for i:=1 to 100 do

begin

if i mod 2=0 then write(i:5);

if i mod 10=0 then writeln;{输出控制}

end;

end.

2.求:

,这里N不大于10。

program exe;

var

n,i:integer;

s:longint;

begin

readln(n);

s:=1;

for i:=2 to n do

s:=s*i;

writeln(s);

end.

3.输入10个数,计算它的和、积、平均分,最大值,最小值。

program exe;

var

i:integer;

sum,mul,ave,x,max,min:real;

begin

read(x);

sum:=x;

max:=x;

min:=x;

num:=1;{赋初值}

for i:=2 to 10 do

begin

read(x);

if max

if min>x then min:=x;

sum:=sum+x;

mul:=mul*x;

end;

ave:=sum/10;

writeln('sum=',sum:5:2,'mul=',mul:5:2,'ave=',ave:5:2,

'max=',max:5,'min=',min:5);

end.

24

【作业】

1.在1-500中,找出能同时满足用3除余2,用除5余3,用7除2的所用数

2.编写程序求:S=1+4+7+...+298的值,并输出值。

3.编写一个评分程序,输入10个选手的得分,然后去掉一个最高分,去掉一个最低分,求出这个选手

的最后得分(平均分)。

4.输入10个数,统计其中正数、负数、零的个数。

5.利用下列公式求的值。

并输出pi的值,输出9位有效数字。

(n=10000)

第八课:WHILE循环语句(当值循环)

在上节课我们学习的FOR语句,它的特点是循环次数已知的情况,其循环次数由初、终值决定。当

循环次数不确定时,它依赖于某个布尔表达式的值,而此值会在循环语句的执行过程中改变。这种循环不

能由For语句来完成,Pascal为此提供了While语句和Repeat语句。本节我们介绍While语句。

一、While语句的一般格式

While <布尔表达式> Do

<循环语句>

其中While和Do保留字。

二、While语句的执行过程为:

①判断布尔表达式的值,如果其值为真,执行步骤2,否则执行步骤4;

②执行循环体语句(do后面的语句);

③返回步骤1;

④结束循环,执行while的下一个语句

三、应用举例

1.求S=1++100的值。

25

program exe;

var

i,s:integer;

begin

i:=1;

while i<=100 do

begin

s:=s+i;

i:=i+1;

end;

writeln('s=',s)

end.

while在循环次数确定时也适用。

2.求恰好使S=1+1/2+1/3+...+1/N的大于10时N的值,。

分析:“恰好使S的值大于10”的意思是S的前n-1项的和是小于或等于10,而加上第n项后S的值

大于10。

program exe;

var

s:real;

n:integer;

begin

while s<=10 do

begin

n:=n+1;

s:=s+1/n;

end;

writeln('n=',n);

end.

3.求两个正整数m,n的最大公约数。

解法一:常规法。

最大公约数就是能被两个数同时整除,且最大。我们可以用此作为While语句的布尔表达式。如程序

如下:

program exe;

var

m,n,i:integer;

begin

readln(m,n)

if m>n then i:=n

else i:=m;

while not((m mod i=0)and (n mod i=0)) do

i:=i-1;

writeln(i);

end.

解法二:辗转相除法

26

用m,n,r分别表示除数、被除数、余数,过程如下:

①m/n的余数为r

②若r=0,则n为最大公约数。

若r<>0,则执行第三步。

③将n的值放入m中,r的值放入n中。

④返回执行第一步。

程序如下:

program exe;

var

m,n,r:integer;

begin

readln(m,n);

r:=m;

while r<>0 do

begin

r:=m mod n;

m:=n;

n:=r;

end;

writeln(m);

end.

解法三:尼考曼切法(辗转相减法)

约定把m和n的最大公约数记为(m,n),例如求:(36,24)则可通过如下操作找出最大公约数:

(36,24)=(36-24,24)=(24,12)=(24-12,12)=(12,12)=0当m和n减为0时,最大公约数即为n;程序如下:

program exe;

var

m,n,t:iteger;

begin

readln(m,n);

while m<>0 do

begin

if m

begin

t:=m;

m:=n;

n:=t;

end;

m:=m-n;

end;

writeln(n);

end.

4.输入一串字符,以'?'结束,输出其中字母个数和数字个数。

分析:输入字符包括能从键盘中输入字母('a'...'z'),数字('0'...'1')和其它符号如(„+‟,„-‟等)我们只统

计小写字母个数和数字个数。我们用ch表示输入字符,num1,num2表示字母和数字个数。此题难点为如

何判断输入字符为数字或字母。根据输入字母的ASCII序号来判断。如字母:(ch>='a')and (ch<='z')or

27

(ch>'A')and (ch<'Z'),数字:(ch>='0')and (ch<='9')

具体程序如下:

program exe;

var

ch:char;

num1,num2:integer;

begin

read(ch);

while ch<>'?' do

begin

if (ch>='a')and (ch<='z')

then num1:=num1+1

else if (ch>='0')and (ch<='9')

then num2:=num2+1;

read(x)

end;

writeln('num1=',num1,'num2=',num2);

end.

【作业】

1.求100-999中的水仙花数(若三位数abc,,则称abc为水仙花数,例如153,

,则153为水仙花数)。此题为For语句来完成。

2.输入一串字符,以'?'结束,统计其中字母个数,数字个数,其它字母个数。

3.编写一个程序,验证“角谷猜想”,所谓解谷猜想:对于任意大于1的自然数n,若n为奇数,则将n

变为3n+1,否则n变为原来的一半,经过若干次这样的变换后,一定会使n变为1。

输入

:

3

输出:10 5 16 8 4 2 1

4. 读入一个算术表达式,以";"结束。结表达式中圆括号是否匹配进行检查,如果括号匹配,则输出

"right!",若出错,如左括号多于右括号,则输出"error1",右括号多于左括号则输出"error2",或是先出现了右括

号,则输出"error3"。

第九课:REPEAT-UNTIL循环语句(直到循环)

用while语句可以实现"当型循环",用repeat-until 语句可以实现"直到型循环"。repeat-until语句的含

义是:"重复执行循环,直到指定的条件为真时为止"。

一、Repeat-until语句的一般格式

Repeat

<语句1>;

:

<语句n>;

until <布尔表达式>;

28

其中Repeat和until保留字。

二、Repeat语句的执行过程为:

①repeat语句的特点是:先执行循环,后判断结束条件,因而至少要执行一次循环体。

②repeat-until是一个整体,它是一个(构造型)语句,不要误认为repeat是一个语句, until是另一

个语句。

③repeat语句在布尔表达式的值为真时不再执行循环体,且循环体可以是若干个语句,不需用begin

和end把它们包起来, repeat 和until已经起了begin和end的作用。while循环和repeat循环是可以相互

转化的。

Repeat-Until语句的执行示意图:

Repeat语句示意图

三、应用举例

1.求S=1++100的值。

program exe;

var

i,s:integer;

begin

i:=0;

s:=1;

repeat

s:=s+i;

i:=i+1;

until i>100

writeln('s=',s)

end.

2.求两个正整数的最大公约数。

分析:本题使用辗转相除法,具体算法如下:

用m,n,r分别表示除数、被除数、余数,过程如下:

①m/n的余数为r

②若r=0,则n为最大公约数。

若r<>0,则执行第三步。

③将n的值放入m中,r的值放入n中。

④返回执行第一步。

program exe;

var

m,n,r;integer;

begin

29

readln(m,n);

r:=m;

repeat

r:=m mod n;

m:=n;

n:=r;

until r=0;

writeln(m);

end.

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

分析:设自变量为x,和为sum,每一项为term,定义它们为实型。另外定义一常量eps用来表示误差,

其值为

一级算法为:

1.读入x

2.设sum,term的初值为x

4.计算下一项term

5.将下一项加到sum中

Until term的绝对值小于eps

6.输出和为sum

下面我们来看第4步: 我们经过观察,可以发现每一项都与变量n相对应,前一项只需后一项乘

上一个因子即可:如的下一项,只需作如下计算:

此时的n为7。要求后一项只需前一项乘因子.

二级算法如下:

第4步 计算下一项term

4-1 n:=n+1

4-2 term:=term*(-x*x)/(n-1)/n

具体程序如下:

program exe;

const

eps:=1e-7;

var

x,term,sum:real;

n:integer;

begin

read(x);

n:=1;

term:=x;

30

sum:=x;

repeat

n:=n+2;

term:=term*(-x*x)/(n-1)/n;

sum:=sum+term;

until abs(term)

writeln(term0

end.

【作业】

1.求2-1000中的守形数(若某数的平方,其低位与该数本身相同,则称该数为守形数。例如

25,25*25=625,625的低位25与原数相同,则称25为守形数)用for语句来完成。

2.输入x,按下列公式计算cos(x)的值。

3.输入x的值(

直到最后一项的绝对值小于

),按下列公式计算s。

直到最后一项的绝对值小于。

4.求出被2,3,5除时余数为1的最小的十个数。

5.写一个程序,判断一个数是否为质数。

输入一个数,是质数则输出yes,

不是质数则输出NO。

第十课:多重循环(一)

一、定义。

一个循环结构的内部(循环体)包括一个循环结构,就称为多重循环结构。实现多重循环结构可以

用前面讲的三种循环语句,任一循环语句的循环体部分都可以包含另一个循环语句,也称为循环语句的嵌

套。多重循环语句的嵌套次数可以是任意的,按照嵌套层次数,分别叫做二重循环、三重循环等。

二、应用举例

1.求S=1!+2!+3!+...+10!的值。

解法一:

分析:第一步:把每一项的值相加:

for n:=1 to 10 do

begin

1.N!的值为t;

2.累加N!的值为S;

end;

第二步:求N!的值:

for j:=1 to n do

t:=t*j;

因此整个如序如下:

31

program exe;

var

t,s:longint;

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);

end.

解法二:用上面的解法做此题时,每求一个N!的值,内循环体语句都要执行N次,我们经过观察,

可以发现:存在这个一个递推公式n!=(n-1)!*n,因引要求当前N!的值,我们只要把前一项(N-1)!值再乘N即

可,因此程序可改为:

var

t,s:longint;

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);

end.

2.一个炊事员上街采购,用500元买了90只鸡,其中母鸡一只15元,公鸡一只10元,小鸡一只5元,

问母鸡、公鸡、小鸡各多少只。

分析:母鸡设为i只,公鸡设为j只,则小鸡为90-i-j, 根据题义则有15*i+10*j+(90-i-j)*5=500,穷举所有

的i,j的可能情况,检验是否满足条件。为了减少穷举量,根据题义0

var

i,j,k:integer;

begin

for i:=1 to 33 do

for j:=1 to 50 do

begin

k:=90-i-j;

if 15*i+10*j+5*k =500

then writeln(i:5,j:5,k:5)

end;

32

end;

3.求1-100之间的素数。

分析:素数是大于1,且除了1和它本身外,不能被其它任何整数所整除的整数。判断一个数i是否为

素数,一个最简单的方法是,用2,3,...i-1去除个除i,看能否被除尽,若其中一个数被除尽,则不是素数,

否则i为素数。

当i比较大时,用这种方法,除的次数会很多,因此我们作一下改进:用2,3,...,sqrt(i)去除i,如果都

除不尽,则i为素数。(可用反证法加以证明:假设有大于sqrt(i)的数j能除尽i,则它的商k必小于sqrt(i),且

k能除尽i(其商为j)。这与原命题相矛盾,假不成立,原命题得到证明)。

for i:=2 to 100 do

begin

1.用2除到sqrt(i)去除i,看能否被除尽。

2.if 除不尽 then 输出i

end.

1步求精

flag:=true;

for j:=2 to round(sqrt(i)) do

if i mod j =0

then flag:=false;

完整程序如下:

var

i,j:integer;

flag:boolean;

begin

for i:=2 to 100 do

begin

flag:=true;

for j:=2 to round(sqrt(i)) do

if i mod j=0

then flag:=flase;

if flag then write(i:5);

end;

end.

另解:此题也可用while语句来完成。程序如下:

var

i,n:integer;

begin

for i:=2 to 100 do

begin

n:=2;

while (n<=trunc(sqrt(i))and(i mod n <>0) do

x:=x+1;

if x>trunc(sqrt(i)) then write(i:5)

end;

4.验证哥德巴赫猜想:任一充分大的偶数,可以用两个素数之和表示。例如:

4=2+2

33

6=3+3

50=13+37

分析:在这里,我们只讨论有限范围内的数,用计算机加以验证,不算严格证明。

读入偶数n,将它分成p和q 使n=p+q。p从2开始(每次加1),q=n-p.若p,q均为素数,则输出结果,

否则将p加1再试。

一级算法:

1.读入大于3的偶数。

2.p:=1

4.p:=p+1;q:=n-p;

5.p是否是素数;

6.q是否是素数;

until p,q 均为素数;

7.打印n=p+q;

二级求精

5-1 falgp:=true;

5-2 for j:=2 to round(sqrt(p)) do

if p mod j=0

then flagp:=false;

6-1 falg:=true;

for j:=2 t round(sqrt(q)) do

if q mod j=0

then falgq:=flase

完整程序如下:

var

n,p,q,j:integer;

flagp,flagq:boolean;

begin

read(n);

p:=1;

reapat

p:=p+1;

q:=n-p;

flagp:=true;

for j:=2 to round(sqrt(p)) do

if p mod j=0

then flagp:=false;

flagq:=true;

for j:=2 to round(sqrt(q)) do

if q mod j=0

then flagq=flase;

until flagp and flagq;

writeln(n,'=',p,'+',q);

end.

【作业】

34

1.写一个程序找出 (1<=x,y<=100)所有整数解。

2.输入一个整数n,把它分解成质因数乘各的形式。

如36=3*3*2*2;

3.求2-1000中的完数(因子和等于它本身的数为完数,例如28的因子是1,2,4,7,14,且1+2+4+7+14=28,

则28为完数)。

4.用一张一元票换1分,2分,5分的硬币,每种至少一枚,列出所有满足条件的换法,并输出总共有

多少种换法。

第十课:多重循环(二)

例1、输出以下图形

* * *

* * *

* * *

此题比较简单,我们可以采用两个for 语句来实现,即:

for m:=1 to 3 do

begin

for n:=1 to 3 do

write('*':2);

writeln;

end;

例2:输出以下图形

A * B * * * * *

* * * * * *

* * * * * *

35

* * * * * *

* * * * * *

C * * * * * D *

* * * * * *

* * * * * *

* * * * * *

* * * * * *

本题实际是在例1的基础上改进而来的,我们只要控制循环的值即可实现输出:

A for m:=1 to 5 do

begin

for n:=1 to m do

write('*':2);

writeln;

end;

B for m:=5 downto 1 do

begin

write(' ':10-2*m);

for n:=m downto 1 do

write('*':2);

writeln;

end

for m:=1 to 5 do

begin

write(' ':10-2*m);

for n:=6-m downto 1 do

write('*':2);

writeln;

end

C for m:=5 downto 1 do

36

begin

for n:=m downto 1 do

write('*':2);

writeln;

end;

D for m:=1 to 5 do

begin

write(' ':10-2*m);

for n:=1 to m do

write('*':2);

writeln;

end;

从上面的例题我们可以看出,这种内循环依赖于外循环的情况,有时是内循环的初值依

赖于外循环,有时内循环的终值依赖于外循环,有时初终值都依赖于外循环,要根据情况来

定。

例3:打印如下数字金字塔:

1

1 2 1

1 2 3 2 1

1 2 3 4 3 2 1

.

37

.

.

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

解析:本题主要是把金字塔一分为二,用例2的形式来解题:

for m:=1 to 10 do

begin

write(' ':40-3*m);

for n:=1 to m do

write(n:3);

for n:=m-1 downto 1 do

write(n:3);

writeln;

readln

end;

例4:打印杨辉三角形

1

1

1 3

1 4

.

1

2 1

3 1

6 4

38

.

1

1

. .

. .

1 10 45 ... ... ... ... 45 10 1

我们首先给大家介绍一下排列组合的公式:

排列:

组合:

即:

特殊情况有:,且规定0!=1;

两式相除可得,它们之间的递推公式:

而在杨辉三解形中,每个公式都可以用组合公式来计算,上面的杨辉三角形可表示为:

为了输出三角形,我们将中心线位置定在40格处,每行的第一个值应往左移3格,最大数是3位整数,

每个数之间空3格,因此输出场宽可定义为6。

完整程序如下:

program exe;

39

var

m,n,c:integer;

begin

c:=1;

write(c:40-3*m);

for n:=1 to m do

begin

c:=c*(m-n+1) div n;

write(c:6);

end;

writeln;

end

end.

【作业】

1.输出以下图形

a

a b

a b c

a b c d

.

.

a b c ... y z

2.输出下列两种格式;

E D C B A

C B A

A

1

3 5 7

9 1 3 5 7

3.编程找出四位数ABCD满足下列条件的数:

(AB+CD)(AB+CD)=ABCD

4.求一个整数各位数的乘积。

输入:323

输出:18

【选作题】:

5.找出2-1000中的亲密对(如果a的因子和等于b,b的因子和等于a,且a不等于b,则称a,b为亲密对子数)。

6.要将100元大钞票,换成等值的10元,5元,2元,1元一张的小钞票,要求每次换成40张小钞票,每

种至少一张,编程求出所有可以的换法,程序应当减少重复的次数。

第十二课:自定义函数

一、使用自定义函数的理由

40

前面我们曾经学习了程序设计中的三种基本控制结构(顺序、分支、循环)。用它们可以组成任何程

序。但在应用中,还经常用到子程序结构。

通常,在程序设计中,我们会发现一些程序段在程序的不同地方反复出现,此时可以将这些程序段作

为相对独立的整体,用一个标识符给它起一个名字,凡是程序中出现该程序段的地方,只要简单地写上其

标识符即可。这样的程序段,我们称之为子程序。

子程序的使用不仅缩短了程序,节省了内存空间及减少了程序的编译时间,而且有利于结构化程序设

计。因为一个复杂的问题总可将其分解成若干个子问题来解决,如果子问题依然很复杂,还可以将它继续

分解,直到每个子问题都是一个具有独立任务的模块。这样编制的程序结构清晰,逻辑关系明确,无论是

编写、阅读、调试还是修改,都会带来极大的好处。

二、自定义函数的格式。

在此之前,我们曾经介绍并使用了pascal提供的各种标准函数,如ABS,SUCC等等,这

些函数为我们编写程序提供了很大的方便。但这些函数只是常用的基本函数,编程时经常需

要自定义一些函数。

在pascal中,函数也遵循先说明后使用的规则,在程序中,函数的说明放在调用该函数

的程序(主程序或其它子程序)的说明部分。函数的结构主程序的结构很相似。

function <函数名> (<形式参数表>):<类型>; {函数首部}

例1:求五边形的面积,边长分别为L1~L7,如下图:

分析:求五边形的面积,只要求出三个三角形的面积相加就可以了,求三个三角形的面积方法都是一

样的,因此我们可以用自定义函数的方法:

Function ts(a,b,c:real):real;

var

p:real;

begin

p:=(a+b+c)/2;

ts:=sqrt(p(p-a)*(p-b)*(p-c))

end;

在程序中我们只要对自定义函数进行引用即可:

program exe;

var

l1,l2,l3,l4,l5,l6,l7:real;

41

s:real;

function ts(a,b,c:real):real;

var

p:real;

begin

p:=(a+b+c)/2;

ts:=sqrt(p*(p-a)*(p-b)*(p-c));

end;

begin

readln(l1,l2,l3,l4,l5,l6,l7);

s:=ts(l1,l2,l6)+ts(l6,l3,l7)+ts(l5,l6,l7);

writeln('s=',s:5:2);

end.

从上面这个例子,我们可以看出:

①函数由首部与函数体两部分组成。

②函数首部以关键字function开头。

③函数名是用户自定义的标识符。

④函数的类型也就是函数值的类型,所求得的函数值通过函数名传回调用它的程序。可见,函数的作

用一般是为了求得一个值。

⑤形式参数简称形参,形参即函数的自变量。自变量的初值来源于函数调用。在函数中,形参一般格

式如下:

变量名表1:类型标识符1;变量名表2:类型标识符2;„;变量名表n:类型标识符n

可见形参表相当于变量说明,对函数自变量进行说明,但应特别注意:此处只能使用类型标识符,而

不能直接使用类型。

⑥当缺省形参表(当然要同时省去一对括号)时,称为无参函数。

⑦函数体与程序体基本相似,由说明部分和执行部分组成。

⑧函数体中的说明部分用来对本函数使用的标号、常量、类型、变量、子程序加以说明,这些量只在

本函数内有效。

⑨函数体的执行部分由begin开头,end结束,中间有若干用分号隔开的语句,只是end后应跟分号,

不能像程序那样用句号"."。

⑩在函数体的执行部分,至少应该给函数名赋一次值,以使在函数执行结束后把函数值带回调用程序。

三、函数的调用

我们可以在任何与函数值类型兼容的表达式中调用函数,或者说,函数调用只能出现在允许表达式出

现的地方,或作为表达式的一个因子。

函数调用方式与标准函数的调用方式相同。

函数调用的一般格式:

<函数名>

<函数名>(实在参数表)

说明:①实在参数简称实参。实参的个数必须与函数说明中形参的个数一致,实参的类型与形参的类

型应当一一对应。

②调用函数时,一般的,实参必须有确定的值。

③函数调用的步骤为:计算实参的值,"赋给"对应的形参;

四:应用举例:

例2:求2~1000中的完全数。

42

分析:所谓完全数是指它的小于该数本身的因子之和等于它本身,如6=1+2+3,6即是一个完全数。

因此我们可定义一个布尔型函数perfect(x),若x是完全数,其值为TURE,否则为FALSE。整个程序算法如下:

program exe;

var

i:integer;

function perfect(x:integer):boolean;

var

k,s:integer;

begin

s:=1;

for k:=2 to x div 2 do

if x mod k =0 then s;=s+k;

perfect:=x=s;

end;

begin

for i:=2 to 1000 do

if perfect(i) then write(i:5);

end.

自定义函数只是主程序的说明部分,若主程序中没有调用函数,则系统不会执行函数子程序。当主

程序调用一次函数时,则将实在参数的值传给函数的形式参数,控制转向函数子程序去执行,子程序执行

完毕后自动返回调用处。

例3:求:S=1!+2!+...+10!的值。

分析:我们可以自定义一个函函数,来求出1!、2!、...,然后相加函数的值即可,完整程序如下:

program exe;

var

s:longint;

i:integer;

function f(n:integer):longint;

var

i:integer;

s:longint;

begin

s:=1;

for i:=1 to n do

s:=s*i;

f:=s;

end;

begin

for i:=1 to 10 do

s:=s+ f(i);

writeln(s);

end.

【作业】

1.定义一个函数digit(n,k),它回送整数n的从右边开始数第k个数字的值。例如:digit(15327,4)=5

digit(289,5)=0

2.定义一个函数check(n,d),它回送一个布尔值。如果数字d在整数n的某位中出现,则送回true(真),

43

否则送回false(假)。例如:

check(3256,2)=true check(1275,3)=false

3.输入a,b,c,计算m。已知:

将求三个数的最大数max(x,y,z)定义成函数。

4.计算s。已知:

s=10!+7!×8!,将n!定义成函数。

5.输入实数x和整数n,计算y。已知:

其中

将s(x,n)定义成函数。

6.输入5个正整数,求它们的最大公约数。

如:输入 20 16 8 60 120

输出 4

第十三课:过程

在pascal中,自定义过程与自定义函数一样,都需要先定义后调用。函数一般用于求值,而过程一般实

现某些操作 。

一、过程的一般格式

procedure <过程名>(<形式参数>);

<说明部分>

begin

语句组

end;

说明:

①过程首部以关键字procedure开头。

②过程名是用户自定义的标识符,只用来标识一个过程,不能代表任何数据,因此不能说明"过程的

类型"。

③形参表缺省(当然要同时省去一对括号)时,称为无参过程。

④形参表的一般格式形式如下:

[var] 变量名表:类型;„;[var] 变量名表:类型。

其中带var的称为变量形参,不带var的称为值形参。在函数中,形参一般都是值形参,很少用变量

形参(但可以使用)。例如,下列形参表中:

(x,y:real;n:integer;var w:real;var k:integer;b:real)

x、y、n、b为值形参,而w、k为变量形参。

调用过程时,通过值形参给过程提供原始数据,通过变量形参将值带回调用程序。因此,可以说,值

形参是过程的输入参数,变量形参是过程的输出参数。有关变参,这在后面内容具体叙述。

44

⑤过程体与程序、函数体类似。与函数体不同的是:函数体的执行部分至少有一个语句给函数名赋值,

而过程体的执行部分不能给过程名赋值,因为过程名不能代表任何数据。

⑥过程体的说明部分可以定义只在本过程有效的标号、常量、类型、变量、子程序等。

二、过程的调用

过程调用是通过一条独立的过程调用语句来实现的,它与函数调用完全不同。过程调用与调与标准过

程(如write,read等)的方式相同。调用的一般格式为:

<过程名>

<过程名>(实在参数表)

说明: ①实参的个数、类型必须与形参一一对应。

②对应于值形参的实参可以是表达式,对应于变量形参的实参只能是变量。

③过程调用的步骤为:计算实参的值;将值或变量的"地址"传送给对应的形参;执行过程体;返回调

用处。

过程与函数有下列主要区别:

①过程的首部与函数的首部不同;

②函数通常是为了求一个函数值,而过程可以得到若干个运算结果,也可用来完成一系列的数据处理,

或用来完成与计算无关的各种操作;

③调用方式不同。函数的调用出现在表达式中,而过程调用是一个独立的语句。

三、过程的应用举例

例1:

求五边形的面积,边长分别为L1~L7,如下图:

program exe;

var

l1,l2,l3,l4,l5,l6,l7,s,sabc1,sabc2,sabc3:real;

procedure abc(a,b,c:real;var sabc:real);

var

p:real;

begin

p:=(l1+l2+l3)/2;

sabc=sqrt(s(s-a)*(s-b)*(s-c));

end;

begin

readln(l1,l2,l3,l4,l5,l6,l7);

abc(l1,l2,l6,sabc1);

abc(l3,l4,l7,sabc2);

abc(l5,l6,l7,sabc3);

45

s:=sabc1+sabc2,sabc3;

writeln(s);

end.

例2:输出以下图形。

*

* *

* * *

* * * *

* * * * *

program exe;

var

i:integer;

procedure draw(n:integer);

var

j:integer;

begin

for j:=1 to n do

write('*');

writeln;

end;

begin

for i:=1 to 6 do

draw(i);

end.

例3:编写程序,求S=21+4!+6!+8!+10!。

program exe;

var

i:integer;

w,s:longint;

procedure njs(x:integer;var t:longint);

var

j:integer;

begin

t:=1;

for j:=1 to x do

t:=t*j;

end;

begin

s:=0;

for i:=2 to 10 do

if not odd(i) then begin

njs(I,w);

s:=s+w;

end;

writeln('s=',s)

end.

46

【作业】

1.求圆台表面积S和体积V。已知

2.输入a,b,c,计算m。已知:

将求三个数的最大数max(x,y,z),使用过程求解。

3 .计算s。已知:

s=10!+7!×8!,将n!定义成函数。

4 .输入实数x和整数n,计算y。已知:

其中

将s(x,n)定义成函数。

第十四课:嵌套及作用域

一、嵌套

一个函数或过程可以调用另外一个函数或过程。

例1:求组合数

分析:

,应注意被调动函数应写在调用它的函数的前面。

program c;

function fac(k:integer):real;

var

i:integer;

fa:real;

begin

fa:=1;

for i:=2 to k do

47

fa:=fa*i;

fac:=fa;

end;

function cmn(m,n:integer):real;

begin

cmn:=fac(m)/fac(n)*fac(m-n)

end;

begin

writeln(cmn(9,3));

writeln(cmn(8,3));

end;

由于函数fac只为cmn调用,可以把fac写在函数cmn内部。程序也可以写成:

program c;

function cmn(m,n:integer):real;

function fac(k:integer):real;

var

i:integer;

fa:real;

begin

fa:=1;

for i:=2 to k do

fa:=fa*i;

fac:=fa;

end;

begin

cmn:=fac(m)/fac(n)*fac(m-n)

end;

begin

writeln(cmn(9,3));

writeln(cmn(8,3));

end.

二、全局变量、局部变量以及它们的作用域。

1.局部变量及其作用域

在子程序内部说明的变量叫局部变量其作用域就在子程序内部。

2.全局变量及其作用域。

在主程序中说明的部分叫全程变量,其作用域分为两种情况。

①当全程变量与局部变量不同名时,其作用域是整个程序范围

②当全程变量与局部变量相同时,全程变量的作用域不包括局部变量的作用域。

例2:写出下列程序的运行结果。

program exe;

var

x,y:integer;

procedure a;

var x:integer;

begin

x:=2;

48

writeln('#',x,''#);

writeln('#',y,'#');

end;

begin

x:=1;

y:=2;

writeln('*',x,'*',y);

a;

writeln('***',x,'***',y);

end;

分析:程序中x是全程变量,但过程中也有,故全程变量的作用域为除a外的任何地方。

*1*2 而y的作用域包含子程序,即整个程序。

#2#

#2#

***1***2

三数值参数和变量参数。

在程序调用子程序时,调用程序将数据传递给被调用的过程或函数,而当子程序运行结束后,结果又

可以通过函数名、变参。当然也可以用全局变量等形式实现数据的传递。

(一)数值参数和变量参数

前面已经讲过,pascal子程序中形式参数有数值形参(简称值参)和变量形参(变参)两种。事实上,

还有函数形参和过程形参两种,只是应用并不太多,我们不作深入地研究。

1、值形参(变量前没有var)

①形参表中只能使用类型标识符,而不能使用类型。

②值形参和对应的实参必须一一对应,包括个数和类型。

③实参和值形参之间数据传递是单向的,只能由实参传送给形参,相当赋值运算。

④一个特殊情况是,当值形参是实型变量名时,对应的实参可以是整型表达式。

⑤值形参作为子程序的局部量,当控制返回程序后,值形参的存储单元释放。

2、变量形参(变量前有var)

①与变量形参对应的实参只能是变量名,而不能是表达式。

②与变量形参对应的实参可以根据需要决定是否事先有值。

③变量形参与对应的实参的类型必须完全相同。

④对变量形参,运行时不另外开辟存储单元,而是与对应的实参使用相同的存储单元。也就是说,调

用子程序时,是将实参的地址传送给对应的变量形参。

⑤当控制返回到调用程序后,变量形参的存储单元不释放,但变量形参本身无定义,即不得再使用。

⑥选用形式参时,到底是使用值形参还是变量形参,应慎重考虑。值形参需要另开辟存储空间,而变

量形参会带来一些副作用。一般在函数中使用值形参,而在过程中才使用变量形参,但也有例外。

例3 写出下列两个程序的运行结果。

program ex1; program ex2;

var a,b:integer; var a,b:integer;

procedure swap(x,y:integer);procedure swap(Var x,y:integer) ;

var t:integer; var t:integer;

begin begin

t:=x;x:=y;y:=t; t:=x;x:=y;y:=t;

end; end;

begin begin

49

a:=1;b:=2; a:=1;b:=2;

writeln(a:3,b:3); writeln(a:3,b:3);

swap(a,b); swap(a,b);

writeln(a:3,b:3); writeln(a:3,b:3);

end. end.

分析:这两个程序唯一的区别是ex1中将x,y作为值形参,而 ex2中将x,y作为变量形参,因此在ex2

中对x,y的修改实际上是对调用该过程时与它们对应的变量a,b的修改,故最后,a,b的值为2,1。而ex1

中调用swap过程时,只是将a,b的值传递给x,y,之后在过程中的操作与a,b无关。

答:ex1的运行结果为: ex2的运行结果为:

1 2 1 2

1 2 2 1

【作业】

1.求g(2.5,3.4),g(1.7,2.5),g(3.8,2.9)的值。

将f和g分别定义成函数,用函数嵌套调动计算。

2.写出以下程序的运行结果。

program exe;

var

a,b,c,d:integer;

procedure p(a:integer;var b:integer);

var

c:integer;

begin

a:=a+1;

b:=b+1;

c:=2;

d:=d+1;

writeln('m',a,b,c,d);

if a<3

then p(a,b);

writeln('n',a,b,c,d);

end;

begin

a:=1;

b:=1;

c:=1;

d:=1;

writeln('x',a,b,c,e);

p(a,b);

50

writeln('y',a,b,c,d)

end.

3.编写一个分数约分程序。

输入:12 8

输出:3 2

第十五课:递归

一、递归的定义

函数或过程调用它本身。

例1:递归计算N!。

分析:本题的关键是要找出递归的表达式。

程序如下:

program facn(input,output);

var

n:integer;

y:real;

function fac(n:integer):real;

begin

if n=0

then fac:=1

else fac:=fac(n-1);

end;

begin

read(n);

y:=fac(n);

writeln(y);

end;

程序即为; 当n=3时:

fac(3)=3*fac(2)=3*2*fac(1)=3*2*1

例2.求m与n的最大公约数。

分析:本题利用辗转相除法,如下:24 与 8

m n m mod n

24 16 8

16 8 0

8 0 当n=0时,m为最大公约数。

我们可以得出表达式:

程序如下:

program exe;

51

var

m,n:integer;

function gcd(m,n:integer):integer;

begin

if n=0

then gcd:=m

else gcd(n,m mod n);

end;

begin

readln(m,n);

writeln(gcd(m,n));

end.

例3:输入一串字符,以"."结束,然后反序输出。

program exe;

procedure receive;

var

ch:char;

begin

read(ch);

write(ch);

if ch<>'.'

then receive;

write(ch);

end;

begin

receive;

end.

例4.利用递归把一个十进制转化为n进制。

program exe;

procedure tentok(k,n:integer);

var

r :integer;

begin

r:=k mod n;

k:=k div n;

if k<>0 then tentok(k,n);

write(r);

end;

begin

readln(k,n);

tentok(k,n);

end.

对于上面的程序,也可以这样写:

program exe;

procedure tentok(k,n:integer);

var

52

r:integer;

begin

if k>0 then tentok(k div n ,n);

writeln(k mod n);

end;

begin

readln(k,n);

tentok(k,n);

end.

【作业】

1.已知:

计算x=3.1,n=15及x=8.1,n=10时的f的值。(将f定义成递归函数)

2.已知:

计算x=3.57,n=20时的f值。 (定义成递归过程)

3.求菲波拉契数的第10项和第20项,已知:

a0=0

a1=1

a2=a0+a1

a3=a1+a2

...

将第n项的a(n)写成递归函数计算。

4.计算勒让德多项式的值,已知

用递归计算。x,n由键盘输入。

5.顺序输入字符,以'?'结束,然后以和输入相反的次序输出读入字符,用递归过程。

6.某楼梯有n级,上楼时一次可以走一级,也可以走两级,计算共有多少种不同的走法。

当N=6时,S=13,当n=20,s=10946;

第十六课:枚举同子界

一、枚举类型

53

(一)枚举类型的定义

枚举类型是种自定义类型(标识符1,标识符2,...,标识符n)

①每个标识符都称为枚举元素或枚举常量

②定义类型时列出所有枚举元素构成这种类型的值域(取值范围)

例如:

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

color=(red,yellow,blue,white,black)

下列定义是错误的。

type color=('red','yellow','blue','white')

number=(1,3,5,7,9)

ty=(for,do,while)

(二)枚举变量

即把某变量说明成该类型。

如:incolor:color。

在定义时也可以把变量说明和类型定义合并在一起。

incolr:(red,yellow,blue,white)

(三)枚举的性质

①枚举类型属于顺序类型。

排列顺序即确定它们的序号,第一个枚举元素序号为0。如:

type days=(sum,mon,tue,wed,thu,fri,sat)则有:

ord(sum)=0,ord(mon)=1,succ(fri)=sat

②对枚举类型只能进行赋值运算和关系运算,不能进行算术运算和逻辑运算。如:type

days=(sum,mon,tue,wed,thu,fri,sat)

colors=(red,yellow,white,black,green)

定义变量如下:color:colors;weekday:days;

则有下列语句是合法的:

weekday:=mon;

if weekday=sun then write();

weekday<>sun;

而下面的语句是不合法的:

mon:=weekday;

mon:=1;

if weekday=sun or sat then write();

sum>red

weekday<>color

③赋值变量的值只能用赋值语句来获得,不能用read语句读入或用write语句输出。如,read(weekday)或

write(weekday)都是错误的。

④同一个枚举变量不能出现在两个或两个以上的枚举类型中。

如,type color1=(red,yellow,white);

color2=(blue,red,black);

(四)应用举例:

例1:输入今天是星期几的序号,给今天各明天赋枚举值(day类型)变量,并输出明天是星期几。

分析:由于枚举类型的变量不能直接输入或输出,应进行必要的转换。

program todaymorrow(input,output);

type

day=(sunday,monday,tuesday,wednesday,thursday,friday,saturday);

54

var

today,tomorrow:day;

number:integer;

begin

read(number);

case number of

0:today:=sunday;

1:today:=monday;

2:today:=tuesday;

3:today:=wednesday;

4:today:=thursday;

5:today:=friday;

6:today:=saturday;

end;

if today=saturday

then tomorrow:=sunday

else tomorrow:=succ(today);

write('tomorrow is ');

case tomorrow of

sunday: writeln('sunday');

monday: writeln('sunday');

tuesday: writeln('sunday');

wednesday: writeln('sunday');

friday: writeln('sunday');

saturday: writeln('sunday');

end

end.

二、子界类型

作用:便于检查不合法数据,一定程序上节省空间。

(一):子界类型的定义

<常量1>...<常量2>

说明:①常量1为子界下界,常量2子界上界

②上下界必为同一类型,上界必须大于下界如下:

type

age:150;

letter:0..'Z';

let1='2'..'a';以上三种方法都是错误的。

③可以直接在变量中说明子界类型。

type letter='a'..'d';

var ch1,ch2:letter;

等同于var ch1,ch2:'a'..'z'

(二)子界类型数据的运算规则

①凡可以使用基本类型的运算规则,同样适用应类型的子界类型。

②对基类型的运算规则,同样适用于该类型的子界类型

③基类型相同的不同子界类型可以进行混合运算如:

type a=1..100;

55

b=1..1000;

c=1..500;

var

x:a;y:=b;t:c;z:integer;

则下列语句也是合法的:

z=sqrt(x)+y+c

t:=x+y+c;

若t在1..500之间合法,否则错误。

(三)应用举例

例2:利用子界类型作为情况标注,编写一个程序对数字、大小字母和特殊字符进行判断。

program exe;

var

ch:char;

begin

read(ch);

case ch of

'0'..'9':writeln('digits!');

'A'..'Z':writeln('upper-caseletter!');

'a'..'z':writeln('lower-caseletter!')

else writeln('special-character');

end;

end;

【作业】

1 、 已知:Type da=(sun,mon,tue,wed,thu,fri,sat);

var date:da;

求出以下各式的值:

ord(sum)------ ord(sat)——— Pred(tue)———— Succ(wed)——

Pred(pred(thu))—— Succ(pred(mon))———— Succ(sat)———— ord(succ(pred(sun)))——————

2、 下列定义哪些是有效的,哪些是无效的。

Type a=’a’..’h’ Type b= 10..10 Type e =10..5

Type d=0..sqr(10) type e=1.0..10.0 Type f=’1’..’5’

Type g=1..’5’ Type h=a..b

3 .输入今天是星期几的序号,给今天和昨天赋成枚举值,并输出昨天是星期几的枚举值。

4 .输入年、月、日,输出它是该年的第几天。

5 .一家水果店出售四种水果,每公斤价格为:苹果1.5元,桔子1.8元,香蕉2.0元,菠萝1.6元,编写一

个程序,使售货员只要从键盘输入货物代码及重量,计算机便能显示名称、单价、重量及总价。

6 .设有四种水果:苹果、桔子、香蕉、与菠萝,任取其中三种水果,不重复,编写程序列出所有的组合方

法。

7 .在红、黄、兰、白、紫五种颜色的旗帜中,每次取出三面不同颜色的旗帜,以表示不同信号,问可表示

多少种不同信号。

第十七课:集合

一、集合的定义

集合是由某些具有共同特征的元素构成的一个整体。

二、集合类型定义和变量说明。

56

①类型定义:

type <集合类型标识符>=set of <基类型>

说明:基类型可以是任意顺序类型,而不能是实型或其它构造类型,序号不能超过255,如:

type

number=set of 0..9;

ch=set of char;

letter=set of „A‟..'Z';

②变量定义与定义其它数据类型一样:

var <变量标识符>:<集合类型>;

var ch1:ch;

也可将类型说明和变量说明组合在一起。

type number=set of 0..9;var s:number;与

var s:set of 0..9等价。

三、集合的值。

集合是用[ ]括起来,中间用逗号隔开的若干个元素。

[]:表示空集。

[1,2,3],['a','e','c','o','u']都是集合。

说明:

①集合的值放在括号内,中间用逗号隔开。

②集合中可以没有任何元素,称为空集。

③集合中元素若是连续的,可用子界表示。

[1,2,3,4,5,7,8,9,10,15]=[1..5,7..10,15]

④集合的值与方括号内元素出现顺序无关。

[1,5,8]=[1,8,5]

⑤集合中同一元素的重复出现对集合的值没有影响。

[1,8,5,1,8]=[1,5,8]

⑥每个元素可用基类元素允许的表达式。

[1,1+2,4]

四、集合的运算

1.赋值运算。

只能用赋值语句给集合赋值,不能用读也不能用写。

2.集合的并、交、差运算。

+:两个集合元素的汇集。

*:两个集合元素中所共有的元素汇集

-:定义在集合A中而不在集合B中的元素。

3.集合的关第运算。

集合可进行相等或不相等,包含与被包含的关系,还可测试一个元素是否在集合中。所用到的关系运

算符为:

=,<>,>,>=,<=,in(属于)

例:设有如下说明:

type weekday=(sun,mon,tue,thu,fri,sat);

week=set of weekday;

subnum=set of 1..50;

写出下列表达式的值:

(1)[sun,sat]+[sun,tue,fri] [sun,sat,tue,fri];

(2)[sun,fri]*[sun..sat]=[]

57

(3)[sun,sat]*[sun..sat]=[sun,sat]

(4)[sun]-[mon,tue]=[]

(5)[mon]-[mon,tue]=[]

(6)[sun..sat]-[mon,sun,sat]=[thu..fri]

(7)[1,2,3,5]=[1,5,3,2] true

(8)[1,2,3,4]<>[1..4] false

(9)[1,2,3,5]>=[1..3] true

(10)[1..5]<=[1..4] false

(11)[1,2,3]<=[1..3] true

(12)2 in [1..10] true

例2:输入系列字符,对其中的数学字符、字母字符和其它字符进行计数,输入以“?”结束。

分析:分别把字母、数字分别组成一个集合,然后用in进行判断。

program exe;

var

id,il,io:integer;

ch:char;

letter:set of char;

digit:set fo '0'..'9';

begin

letter:=['a'..'z','A'..'Z']

digit:=['0'..'9'];

id:=0;il:=0;io:=0;

repeat

read(ch);

if ch in letter

then il:=il+1

else if ch in digit

then id:=id+1

else io:=io+1;

until ch='?';

writeln(id:5;il:5;io:5);

end.

例3:输入一串字符,以问号结束,组成元音字母集合,辅音字母集合,然后输入两集合元素及其个数。

分析:定义两个集合变量s1,s2,分别表示元音和辅音字母集合,它们的基础类型是字母的子界'a'..'z',

再定义两个整型变量n1,n2,用来记录两个集合的元素个数,定义字符变量ch,存入读入的字符。

先通过集合的合并,然后再统计集合中的个数。

program exe;

var

s1,s2:set of 'a'..'z';

n1,n2:integer;

ch:char;

begin

s1:=[];

s2:=[];

n1:=0;

n2:=0;

58

read(ch);

while ch<>'?' do

begin

if ch in ['a'..'z']

then if ch in['a','e','i','o','u']

then s1:=s1+[ch]

else s2:=s2+[ch];

read(ch)

end;

writeln;

writeln('n1=',n1);

for ch='a'to 'a' do

if ch in s1

then begin

write(ch);

n1:=n1+1;

end;

writeln;

if ch ='a' to 'z' do

if ch in s2

then begin

write(ch);

n2:=n2+1

end;

writeln;

writeln('n2=',n2);

end.

例4:用筛选法求素数。

分析:由希腊著名数学家埃拉托色尼提出:

①将所求数放入筛中

②找出筛中最小的数(要求此数必为素数),放入集合primes中。

③将最小数及其所有倍数从筛中去掉

④重复②~④直到筛中为空。

如:首先将整数2,3,4,5,6,7,8,等放于某集合(称为筛)中。然后从该集合中选出最小的元素,此

时为2,将它作为素数输出,再从集合筛中去掉此数及其所有倍数(2,4,6,8,10,...)。再找当前集合中最小数

(此时为3),将它作为素数输出。从集合中去掉该数及其所有倍数(3,6,9,...)如此类推,直到集合为空。

program exe;

const

n=100;

var

sieve:set ;

next,nul:integer;

begin

sieve:=[2..n];

next=2;

repeat

59

while not (next in sieve) do

next:=next+1;

writeln(next);

nul:=next;

while nul<=n do

begin

sieve:=sieve-[nul];

nul:=nul+next

end

until sieve=[]

end.

【作业】

1.设有集合:A=[1,3,5,7,9] B:=[2,4,6,8,10] C:=[1,2,3,4,5] D:=[5] E:=[]

(A+B)-C=——— (A*C)=D+———— (A+E)*(B+D) =————

‘A‘ IN ((A-B)-C)-D) ———— C<(A+B) ————

2.将集合a赋值成[1,2,3,4,5,7,9],集合b赋值成[4,5,6,7,8,10],计算c=a+b,d=a-b,e=a*b,以及a>=b的值,输出

a,b,c,d,e,及a.=b的值。

3.读入一串字符,以'?'结束,分别组成字母和数字两个集合,然后分别输出两个集合中元素及其元素个数。

4.用筛选法求100-200之间的素数。

5.将十进制整数K转换成二进制,以集合类型变量buf表示一个16位二进制数,如

(18)10=(10010)2,则buf中记为[2,5]表示倒数2、5位是1,其余为0。

第十八课:一维数组

一、为会么要使用数组

例:输入50个学生的某科成绩,打印出低于平均分数的同学的号数及成绩。

分析:在此题中我们可以通过累加求总分,从而求得平均分,需要把50个学生的成绩保留下来,然

后逐个同平均分比较,如果这样则需要50个变量,显然这种方法不可取。如果使用数组,只需一个数组

变量即可完成。

program exe;

var

ave,sum:real;

a:array[1..50] of integer;

begin

sum:=0;

for i;=1 to 50 do

begin

read(a[i]);

sum:=sum+a[i];

end;

ave:=sum/50;

for i:=1 to 50

if a[i]

end.

二、一维数组

60

当数组中每个元素只带一个下标时,我们称之为一组数组。

1.一级数组的类型定义

一般格式:array[下标1...下标2] of <基类型>

①array,of都是保留字

②下标1和下标2是属于同一类型,且下标2大于下标1的序号

③基类型是指元素的类型,它可以是任何类型,同一数组中元素具有相同类型。如:

type arr=array[1..8] of integer;

2.一级数组的变量定义:

一级数组的变量定义同其它数据类型的变量定义一样,如:

var

a1,a2:arraytype;

当然,我们也可以把类型定义和变量定义放在一起,即上面的定义等价于:

var a1,a2:array[1..8] of integer;

三、一级数组的引用。

当定义了一个数组,则数组中的各个元素就共用一个数组名( 即该数组变量名),它们之间是通过下标

不同以示区别的。 对数组的操作归根到底就是对数组元素的操作。一维数组元素的引用格式为:

数组名[下标表达式]

说明:

①下标表达式值的类型, 必须与数组类型定义中下标类型完全一致,并且不允许超越所定义的下标下

界和上界。

②数组是一个整体,数组名是一个整体的标识,要对数组进行操作,必须对其元素操作。数组元素可

以象同类型的普通变量那样作用。如:a[3]:=34;是对数组a中第三个下标变量赋以34的值。read(a[4]);是

从键盘读入一个数到数组a第4个元素中去。

特殊地,如果两个数组类型一致,它们之间可以整个数组元素进行传送。如:

var a,b,c:array[1..100] of integer;

begin

c:=a;a:=b;b:=c;

end.

在上程序中,a,b,c三个数组类型完全一致, 它们之间可以实现整数组传送,例子中,先将a数组所

有元素的值依次传送给数组c,同样b数组传给a,数组c又传送给b,上程序段实际上实现了a,b 两个数

组所有元素的交换。

对于一维数组的输入与输出, 都只能对其中的元素逐个的输入与输出。在下面的应用示例中将详细介

绍。

四、应用举例:

例1:输入50个数,要求程序按输入时的逆序把这50个数打印出来。也就是说,请你按输入相反顺序打印这

50个数。

分析:我们可定义一个数组a用以存放输入的50个数, 然后将数组a内容逆序输出。

源程序如下:

program ex5_1;

type arr=array[1..50]of integer; {说明一数组类型arr}

var a:arr;i:integer;

begin

writeln('Enter 50 integer:');

for i:=1 to 50 do read(a[i]);{从键盘上输入50个整数}

61

readln;

for i:=50 downto 1 do {逆序输出这50个数}

write(a[i]:10);

end.

例2:输入学生的学号、成绩、计算平均成绩。然后计算每个学生的成绩与平均成绩的差,并由引给出每个

学生成绩的字母等到级。如果成绩高于平均成绩10分为A,与平均成绩相差10为B,其余为C。最后输出每

个学生的学号,成绩和字母等级。

分析:设两个数组,一个保留学生的学号,为一个整型数组;一个用业保留学生的成绩,为实型数组。

program exe;

const

n=10;

var

num:] of integer;

score:] of real;

i:integer;

ave:real;

grade:char;

begin

for i:=1 to n do

ave:=0;

for i:=1 to n do

ave:=ave+score[i];

ave:=ave/n;

for i:=1 to n do

begin

if score[i]>=ave+10

then grade:='A'

else if score>=ave-10

then grade:='B'

else grade:='C';

writeln(num[i],score[i]:6:1,grade:3);

end

end.

例3:输入一串字符,以'?'结束,统计其中每个字母出现的个数。

分析: 定义一个由26个元素组成的数组,下标类型是字符的子界,元素类型为整型,如:

var num:arra·y['a'..'z'] of integer;

用num['a']记录a出现的次数,用num['b']记录b出现的次数,...;

当读入字符不为"?"时,应判断它是否为字母,若是则应将相应字母计数加1,此是无需判断是哪个字

母,只需将读入的字母作为下标,就可以找出相应的数组元素,将它加1即可。若读入的字符是"?"则结束

循环,最后输出统计结果。

program exe;

var

num:array['a'..'z']of integer;

ch:char;

begin

for ch:='a' to 'z' do

62

num[ch]:=0;sv

read(ch);

while ch<>'?'do

begin

if (ch>='a') and (ch<='z')

then num[ch]:=num[ch]+1;

read(ch);

end;

for ch:='a' to 'z' do

writeln(ch,num[ch]);

end.

【作业】

1.输入一串字符,以"?"结束,分别统计其中每个数字0,1,..9出现的次数。

2.输入一个不大于32767的整数N,将其转化为二进制数。(使用数组)

3. 读入10个数,打印其中最大值和最小值及其序号。

第十九课:一维数组(二)

一、排序

例1:输入10个数,然后由大到小排列输出。

(一)选择排序法

基本思想:首先从要排序的数中选择最大的数,将它放在第一位,然后从剩余的数中选择最大的数

放在第二位,如此继续,直到最后剩下两个数中选择最大的数放在倒数第二位置,剩下的一个数放在最后

一个位置,完成排序。

例如下面对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

对于5个数,要进行四次外循环,而内循环的次数分别为4,3,2,1。因此在最坏的情况下,要进行比较

的次数为:1+2+3+...+n-1=n(n-1)/2次。

源程序如下:

program exe;

const

n=10;

var a:array[1..10]of integer;

i,j,t:integer;

begin

63

writeln('Input 10 integers:');

for i:=1 to 10 do read(a[i]);{读入10个初始数据}

readln;

for i:=1 to n-1 do{进行9次排序}

begin

for j:=i+1 to n do{将第i个数与其后所有数比较}

if a[i]

begin

t:=a[i];a[i]:=a[j];a[j]:=t;

end;

end;

for i:=1 to n do

write(a[i]);

end.

由于每次交换两个元素需要执行3个语句,过多的交换必定花费许多时间。改进方案是在内循环的比

较中找出最大元素的下标,在内循环结束时才考试虑时否交换。如序如下:

program exe;

const

n=10;

var a:array[1..10]of integer;

i,j,t,k:integer;

begin

writeln('Input 10 integers:');

for i:=1 to 10 do read(a[i]);{读入10个初始数据}

readln;

for i:=1 to n-1 do{进行9次排序}

begin

for j:=i+1 to n do

if a[i]

then k:=i;

if i<>k then begin

t:=a[i];a[i]:=a[j];a[j]:=t;

end;

end;

for i:=1 to n do

write(a[i]:5);

end.

二、冒泡排序。

思想:依次比较相邻相个数,将大数放在前面,小数放在后面。即首先比较两个数第1个和第二个数,

将大数放在前面,小数放在后面,如此继续,直到比较最后两个数,将大数放在前,小数放在后,此时第

一趟比较结束,在最后面的数必是所有数中最小数,重复以上过程,仍从第一对数开始比较,将大数放在

前,小数放在后,直到最小数前的一对相邻数,将大数放在前,小数放在后,第二趟比较结束,在倒数第

二数中得到一个新的最小数。如此类推,从而最终完成排序。

例如下面对5个进行排序,这个五个数分别为8 2 9 10 5。按选择排序方法,过程如下:

初始数据 :8 2 9 10 5

第一次排序:8 2 9 10 5

64

8 9 2 10 5

8 9 10 2 5

8 9 10 5 2

第二次排序:9 8 10 5 2

9 10 8 5 2

9 10 8 5 2

第三次排序:10 9 8 5 2

10 9 8 5 2

第四次排序:10 9 8 5 2

以上5个数要进行4趟比较,每趟比较的次数别为4,3,2,1。依此类推如果是n个数据,则需要比较的

次数为(n-1)+(n-2)+...+1=(n-1)*n/2次。

源程序如下:

program exe;

const

n=10;

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 n-1 do{进行9次排序}

for j:=1 to n-i do

if a[j]

then begin

t:=a[j];

a[j]:=a[j+1];

a[j+1]:=t;

end;

for i:=1 to n do

write(a[i]);

end.

冒泡法的改进:

如果读入数据或在排序过程中已经有部分或是全部数据已经排好,那么我们就不必对它们对进比较交

换了。为了标志在比较中是否进行了数据交换。可设置一个布尔变量flag,初始将flag设置为false,如果

在比较中发生的数据交换,则将flag置为false,在一趟比较结束后,再判断flag,如果它仍为true(表明

在该趟比较中未发生一次数据交换)则排序结束,否则进行下趟比较。

源程序如下:

program exe;

const

n=10;

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个初始数据}

65

readln;

i:=1;

repeat

flag:=true;

for j:=1 to 20-i do

if a[j]

then begin

t:=a[j];

a[j]:=a[j+1];

a[j+1]:=t;

end;

i:=i+1

until flag;

for i:=1 to n do

write(a[i]);

end.

二、数据元素的找查。

查找,也称为检索或是搜索,根据某一特定的待检数据,按照某种方法确定它在数列中的位置。

查找结果有两种:

找到:打印出相关信息。

找不到:给出提示信息。

(一)顺序查找

方法:从头开始,根据给定的值,依次与表中关键字进行比较,如果有相同,则找到;如果有不同则

找不到。

例2:在一列数组中找出某个数,并输出相关信息。

program exe;

const

n=10;

var

key,i:integer;

a:] of integer;

begin

for i:=1 to n do

read(a[i]);

read(key)

for i:=1 to n do

if key=a[i]

then writeln('OK!')

else writeln('No Fount!')

end.

(二)二分法

要求:表中的关键字必须是有序的, 为一连续的递增或递减的数列:A1,A2,...,An。

方法:a若x>An或x

b若x=A1或x=An则表明已找到,并输出。

c若前两项没有找到,则进行下面的操作。

1.求中点:M=(A1+An) div 2;

66

=x则中点值等于要找的值。

>x,则将An:=Am并执行C。

源程序如下:

program exe;

const

n=10;

var

a:] of integer;

p,t:integer;

f:boolean;

begin

for i:=1 to n do

read(a[i]);

p:=1;

t:=n;

f:=false;

repeat

m:=(p+t) div 2;

if x=a[m]

then begin

writeln('Found!');

f:=true;

end

else if x

else if x>a[m] then p:=m+1;

until (t

if not f then ('No Found!');

end.

(三)数组元素的移劝与移动与插入。

例3:将一个数插入到长度为k有序数列中,要求数列仍然有序。

分析:1.找到要插入的位置j。

2.然后移动k到j的所有数据到k+1至j+1上。

3.插入数据到空出来的J个位置上。

源程序如下:

program exe;

const

k=10;

var

a:array[1..k+1]of integer;

i,j,x:integer;

begin

for i:=1 to k do

read(a[i]);

read(x);

j:=1;

67

while (x>=a[j])and (j<=k);

j:=j+1;

for i:=k downto j do

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

a[j]:=x;

for i:=1 to k+1

write(a[i]:5);

end.

【作业】

1.输入a1,a2,a3,...a10

(1)它他们从小到大排序(选择法)

(2)它他们从大到小排序(冒泡法)

2.输入a1,a2,a3,...,a10,将他们从小到大排序输出后,并给出每个元素所对应的原来次序。

例:输入:27,3,25,27,14,39

输出:3 2

14 5

25 3

27 1

27 4

39 6

3.输入一串字符,以'?'结束,编者中字母出现的次数,并按字母出现的多少输出(先输出字母出现多的,次

数相同的按字母表顺序输出,不出现的字母不输出)。

例:输入5b3a+4-hdeh5dh?

输出

h 3

d 2

a 1

b 1

c 1

4.将一个数插入到有10个数的有序数列中,要求仍然有序。

第二十课:二维数组

一、为什么要引入二维数组

在上一节中我们用一级数组表示一个班的同学的某一科成绩并进行处理,如果我们要对一个班各科成

绩进行处理,如果使用一级数组就要定义几个一级数组,操作起来十分不便。

学号 姓名 语文 物理 化学 总分

001 90 92 94

王立

002 95 86 73

李锐

003 88 98 78

夏良

对此,我们可以使用二级数,用两个下标变量来表示以上关系:

a:array[1..3,1..6] of integer;即定义了如下变量。

a[1,1] a[1,2] a[1,3] a[1,4] a[1,5] a[1,6]

a[2,1] a[2,2] a[2,3] a[2,4] a[2,5] a[2,6]

68

a[3,1] a[3,2] a[3,3] a[3,4] a[3,5] a[3,6]

二、二级数组的定义。

(1)类型定义

当一维数组元素的类型也是一维数组时,便构成了二维数组。二维数组定义的一般格式:

array[下标类型1] of array[下标类型2] of 元素类型;

但我们一般这样定义二维数组:

array[下标类型1,下标类型2] of 元素类型;

说明:其中两个下标类型与一维数组定义一样,可以看成"下界1..上界1"和"下界2..上界2",给出二

维数组中每个元素( 双下标变量)可以使用下标值的范围。of后面的元素类型就是基类型。

如:type ar=array[1..3,1..6] of integer;

一般地,n维数组的格式为:

array[下标类型1,下标类型2,„,下标类型n] of 元素类型;

其中,下标类型的个数即数组的维数,且说明了每个下标的类型及取值范围。

(2)变量定义

变量定义同其它类型的变量定义一样,如:

var a:ar;

也可以把变量定义与类型定义合二为一,如:

a:array[1..3,1..6] of integer;

(三)二级数组的引用

多维数组的数组元素引用与一维数组元素引用类似,区别在于多维数组元素的引用必须给出多个下

标。

引用的格式为:

<数组名>[下标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

69

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 输入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.

70

(五)、字符数组

当数组元素的类型为字符型时,该数组即为字符数组。

如:type

chartype=array[1..14] of char;

var

ch:chartype;

也可以合二为一:

ch:array[1..14] of char;

在赋值时,只能以数组方式单独赋值,不能整体赋值。

ch='This is open' 则是错误的。

ch[1]='T' ch[2]='h'...

for i:=1 to 14 do read(ch[i]) 则是正确的。

例2: 输入一串字符,字符个数不超过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

begin

i:=i-1;j:=j+1;

end;

if j>=i then writeln('Yes.')

else writeln('No.');

end.

【作业】

1.播入排序(在输入过程中完成排序)。以任意次序读入10个数,将第1个数放入数组a第1个元素中。

以后读入的数应与已存入数组a中的数进行比较,确定它在从小到大的所应处的位置。将该位置及其后面

的元素向后推移一个位置,将新读入的数据放入空出的位置中。这样在数组a中的数总是从小到大排序的,

10个数据处理完毕后输出a。(一维数组解)

2.输入n(n=5)个同学的语、数、英三科成绩,计算它们的总分与平均分,并统计出每位同学的名次,最后

71

以表格的形式式输出所有同学的名次、语、数、英、总分、平均分。(二维数组)

选作题

3.将A、B两个有序数组(同为递增或同为递减)进行归并操作,然后输出。

如:输入:2 3 5 8 9

5 6 9 10 11

输出:2 3 5 6 8 9 10 11

4.约瑟夫问题,m个人围成一圈,从第1个人开始报数,数到n的人出圈。再由下一个人开始报数,数到

n的人出圈,.....输出依次出圈人的编号。m值预选定,n的值由键盘输入。

例:m=8,n=5

依次出圈的是5,2,

5.输出杨辉三角形的前n行。(用一维数组完成)

第二十一课:矩阵数级和字符串数组

一、矩阵

定义:矩阵是按行列形式排列的数据组合。如下:

1 2 1 3 2 1

A= 2 3 1 B= 1 1 3

3

2 1

3

0 2

可用二维数组表示成如下形式式。

a11 a12 a13 b11 b12 b13

A= a21 a22 a23 B= b21 b22 b23

a31

a32 a33

b31

b32 b33

矩阵相加:新矩阵的每个元素是其对应的两矩阵元素之和。

cij=aij+bij

a11+b11 a12+b12 a13+b13 4 4 2

C= a21+b21 a22+b22 a23+b23 = 3 4 4

a31+b31

a32+b32 a33+b33

6

2 3

矩阵相乖:新矩阵Dij的每一个元素是第一个矩阵的第i行和第二个矩阵的第j列相乖相加而得。

dij=

a11*b11+a12*b21+a13*b31 ... a11*b13+a12*b23+a13*b33

D= a21*b11+a22*b21+a23*b31 ... a21*b13+a22*b23+a23*b33

a31*b11+a32*b21+a33*b31 ... a31*b13+a32*b23+a33*b33

72

=

8 4 9

12 7 13

14 8 11

转置矩阵:新矩阵的第一行元素等到于旧矩阵的第一列元素,新矩阵的第二行元素等于旧矩阵的第二列元

素...。

a(

T)ij

=aji

a11 a21 a31

A

T

= b12 b22 b32

b13

b23 b33

在Pascal语言中实现矩阵的相加、相乘和转置。

例1:在Pascal语言中实现矩阵的相加、相乘和转置。

program exe;

const

m=3;n=3;

type

matrix=,1..n] of integer;

var

i,j,k:integer;

a,b,c,d,at:matrix;

procedure readmatrix(var x:matrix);

begin

for i:=1 to m do

for j:=1 to n do

read(x[i,j])

end;

procedure writematrix(var x:matrix);

begin

for i:=1 to m do

begin

for j:=1 to n do

write(x[i,j]:5);

writeln

end

end;

begin

readmatrix(a);

readmatrix(b);

for i:=1 to m do

73

1 2 3

= 2 3 2

1

1 1

for j:=1 to n do

c[i,j]:=a[i,j]+b[i,j];

for i:=1 to m do

for j:=1 to 3 do

for k:=1 to n do

d[i,j]:=d[i,j]+a[i,k]*b[k,j];

for i:=1 to m do

for j:=1 to n do

at[i,j]:=a[j,i];

writeln('C=A+B');

writematrix(c);

writeln('D=A*B');

writematrix(d);

writeln('AT');

writematrix(at);

end.

二、字符串

1、字符串常量:用单括号括起来的一串字符。

如:const

str1='Basic'

2、字符串变量

var

s:string[n] n在1到255之间,其最大长度为n个字符。

也可以表示成

var

s:string;则字符串的长度可长可短,但最大长度不超过255。

注:字符串类型的变量,一旦赋了值,它也具有像数组一样的功能,可以将字符串的字符按位取出或

打印。

字符串的标准函数和过程:

(1)concat函数

句法:concat(st1,st2,..stn)连接字符串,若字符串长度大于255则出错,此函数相当于st1+st2+...+stn。

(2)copy函数

句法:copy (st,pos,num),该函数返回原串(st)中的一个子串(从pos开始的num个字符),若pos超过串

长,返回一个空串,pos超过1~255则出错。

(3)length函数

句法:length(st),求一个字符串st的长度。

(4)pos函数。

句法:pos(obj,st)求一个子串obj在原串(st)中的起始位置,若没有,返回值为0。

(5)delete过程。

句法:delete(st,pos,num),从原串中册除一个从pos开如的num个字符的子串。

若pos大于st的长度,则不作删除。

若pos超出1..255范围,则出错。

若pos+num>st长度,则仅删除串内长度。

(6)insert过程

句法:insert(obj,st,pos),向原串st插入一个指定的子串(obj)至原串的pos位置上。

74

(7)str过程

句法:str(var,st),把一个整型或实型数值(var)转换成字符串型, 结果存入st中。

(8)val过程

句法:val(st,var,c),将一个字符串(st)转换成与var同类型的数值,并将值赋值勤给var,结果字符串无

效,其中非法字符的下标放在c中,否则c为0。

如:val(‘123df’,var,c),则c=4

大家在使用这些函数过程中请注意参考pascal系统的帮助系统。

例2:输入10个学生的姓名,并按英文字母的顺序排序。

分析:1)输入10个学生的姓名,存入一字符串数组中。

2)排序。

3)输出排序后的名单。

program exe;

cnost

n=10;

name:] of string[8];

i,j:integer;

ch:string[8];

begin

for i:=1 to n do

readln(name[i]);

for i:=1 to n-1 do

for j:=1 to n-i do

if name[i]>name[j]

then begin

ch:=name[i];

name[i]:=name[j];

name[j]:=ch;

end;

for i:=1 to n do

write(name[i]:10);

end.

【作业】

1.编程从键盘输入两个字符串(<=100),利用库函数和过程完成以下操作 (1)连接两个字符串,要求

将第二个字符串连接在第一个字符串之后。

(2)判断第二个字符串是否是第一个字符串的子串,若是输出子串在原串的位置起始位置,并将该子串

从原串的删除,若不是,将该子串插入到原串的中间位置。

2.输入矩阵a(2行3列)和矩阵b(3行4列),然后计算矩阵c=a*b,并输出c。

3.输入矩阵(5行5列),将a的第二行与第5行对调后,形成新的矩阵并输出

4.输入6列6行的矩阵a,然后:

(1)将对角线之外的上三角形的每个元素加1,下三角形的每个元素减1,开成新矩阵a输出。

(2)找出新矩阵a中绝对值最大的元素及其行、列并输出。

第二十二课:记录

一、 记录类型

75

为什么要引入记录类型?

在程序中对于组织和处理大批量的数据来说,数组是一种十分方便而又灵活的工具,但是数组在使用

中有一个基本限制,这就是:一个数组中的所等有元素都必须具有相同的类型。如一个学生的语文、数学、

英语、总分、平均分等,我们可以用一个二级数组来表示。如:

var a:array[1..5,1..5] of real;

但如果再加上学生的性别、民族、住址等后由于类型不同,因此就不能再用数组。

一个学生情况记录结构可以包含以下内容:

学号 字符串类型

姓名 字符串类型

年龄 整型

性别 字符型

成绩 实型数组

Pascal给我们提供了一种叫做记录的结构类型。在一个记录中,可以包含不同类型的并且互相相关的

一些数据。

与前面所学的数组、集合类型不同,记录是表达一种类型的数据组合。

正因为记录中允许不同的数据类型同时存在,因而它代表了最基本的信息实体。

(二)记录类型的定义

在pascal中,记录由一组称为"域"的分量组成,每个域可以具有不同的类型。

记录类型定义的一般形式:

record

<域名1>:<类型1>;

<域名2>:<类型2>;

: :

: :

<域名n>:<类型n>;

end;

说明:①域名也称域变量标识符, 应符合标识符的语法规则。在同一个记录中类型中,各个域不能

取相同的名,但在不同的记录类型中,两个类型中的域名要以相同。

②记录类型的定义和记录变量可以合并为一个定义,如:

type date=record

year:1900..1999;

month:1..12;

day:1..31

end;

var x:date;

可以合并成:

var x: record

year:1900..1999;

month:1..12;

day:1..31

end;

③对记录的操作,除了可以进行整体赋值, 只能对记录的分量──域变量进行。

④域变量的表示方法如下:

记录变量名.域名

如前面定义的记录X,其3个分量分别为: , ,。

⑤域变量的使用和一般的变量一样, 即域变量是属于什么数据类型,便可以进行那种数据类型所允许

76

的操作。

(二)记录的嵌套

当一个记录类型的某一个域类型也是记录类型的时候,我们说发生了记录的嵌套,看下面的例子:

例6 某人事登记表可用一个记录表示, 其中各项数据具有不同的类型,分别命名一个标识符。而其中

的"出生年月日"又包括三项数据,还可以用一个嵌套在内层的记录表示。

具体定义如下:

type sexs=(male,female);

date=record

year:1900..1999;

month:1..12;

day:1..31;

end;

personal=record

name:string[15];

sex:sexs;

birthdate:date;

home:string[40];

end;

(三)开域语句

在程序中对记录进行处理时,经常要引用同一记录中不同的域,每次都按6.4.1节所述的格式引用,

非常乏味。为此Pascal提供了一个with语句,可以提供引用域的简单形式。

开域语句一般形式:

with <记录变量名表> do

<语句>

功能: 在do后的语句中使用with后的记录的域时, 只要直接写出域名即可,即可以省略图10.2.2中的

记录变量名和"."。

说明: ①一般在with后只使用一个记录变量名。如:

write('Input year:');

readln();

write('Input month:');

readln();

write('Input day:');

readln();

可以改写成:

with x do

begin

write('Input year:');readln(year);

write('Input month:');readln(month);

write('Input day:');readln(day);

end;

②设x,y是相同类型的记录变量,下列语句是非法的:

with x,;

③with后接若干个记录名时,应是嵌套的关系。如有记录说明:

var x:record

i:integer;

y:record

77

j:0..5;

k:real;

end;

m:real

end;

可以使用:

with x do

begin

read(i);

with y do

read(j,k);

readln(m);

end;

或简写为:

with x,y do

readln(i,j,k,m);

);

例1:输入全班学生的姓名和成绩,计算平均成绩,并按成绩给每个学生一个字母等级(高于平均分10

以上的为A等,与平均分相差10分为B等,其余全为C等)最后输出每个学生的姓名、成绩、字母等级。

分析:当一个数组的分量是记录类型时,叫记录数组。

为了解决这个问题,可以定义一个学生记录类型student,它由姓名name,成绩score和等级grade三

个域组成。然后再定义一个记录数组类型studenta,它的分量是student。最后用记录数组类型studenta说

明记录数组变量students。整个程序如下:

program exe;

const

n=30;

type

student=record {定义一个学生的记录类型}

name:string[6];

score:real;

grade:char;

end;

studenta=] of student;{定义记录数组类型}

var

students:studenta;{数组类型变量}

ave:real;

i:integer;

begin

for i:=1 to n do

with students[i] do

read(score,name);

ave:=0;

for i:=1 to n do

ave:=ave+sutdents[i].score;

ave:=ave/n;

writeln('name':10,'score':15,'grade':10);

78

for i:=1 to n do

with students[i] do

begin

if score>=ave+10

then grade='A'

else if score>=ave-10

then grade='B'

else grade='C';

writeln(name:15,score:10:1,grade:8);

end;

end.

注意:除了对记录类型进行整体赋值外,不能对记录进行整体读、写、赋值、比较运算,而只能对记

录的第一个域(分量)进行读、写、赋值、比较运算。

例2:输入40个学生的记录(每个学生包括学号、姓名、性别、年龄、成绩),组成记录数组,然后按成绩

的由高到低的次序排序,输出排序后的全部学生记录。源程序如下:

program exe;

const

n=40;

type

student=record

num:integer;

name:string[6];

sex:(male,female);

age:5..100;

score:real;

end;

studenta=] of student;

var

students:studenta;

temp:student;

i,j:integer;

se:char;

begin

writeln('input se num,age,score,name');

for i:=1 to n do

with students[i] do

begin

readln(se,num,age,score,name);

if se='m'

then sex:=male

else sex:=female;

end;

for i:=1 to n-1 do

for j:=1 to n-i do

if students[i].score

then begin

79

temp:=students[i];

studnets[i]:=students[j];

students[j]:=temp;

end;

writeln('num':8,'name':10,'sex':14,'age':10,'score':8);

for i:=1 to n do

with students[i] do

begin

write(num:8,name:18);

if sex=male

thne write('male':8)

else write('female':8);

writeln(age:8,score:8:1);

end;

end.

【作业】

1.输入10个学生的记录(每个学生包括学号、姓名、性别、年龄、成绩),组成记录数组,统计男生、

女生人数,平均年龄,并将低于平均成绩的学生记录输出。

2.输入20个数a1,a2,a3,...,a20,将它们从大到小排序输出。并给出每个输出值对应的原来输入次序(用

记录作)

第二十三课:文件

在DOS操作中,我们所谈及的文件称之为外部文件。外部文件是存储在外部设备上, 如:外存储器

上,可由计算机操作系统进行管理,如用dir、type等命令直接对文件进行操作。

Pascal所谈及的文件,称之为内部文件。内部文件的特点是文件的实体(实际文件)也是存储在外存

储器上,成为外部文件的一分子,但在使用时必须在程序内部以一定的语句与实际文件联系起来,建立一

一对应的关系,用内部文件的逻辑名对实际文件进行操作。内部文件的逻辑名必须符合PASCAL语言

标识符的取名规则。

Pascal中的文件主要用于存放大量的数据。如:成绩管理,原始数据很多,使用文件先将其存入磁盘,

通过程序读出文件中的数据再进行处理,比不使用文件要来得方便、有效。

Pascal中的一个文件定义为同一类型的元素组成的线性序列。文件中的各个元素按一定顺序排列,可

以从头至尾访问每一个元素,从定义上看,文件与数组相似,但它们之间有着明显不同的特征,主要表现

在:

(1)文件的每一个元素顺序存贮于外部文件设备上(如磁盘上)。因此文件可以在程序进行前由Pascal

程序或用文字编辑软件,如edit、ws、Turbo Pascal的edit命令等产生,或在运行过程中由程序产生,且运

行完后,依然存贮在外部设备上。

(2)在系统内部,通过文件指针来管理对文件的访问。文件指针是一个保存程序在文件中位置踪迹

的计算器,在一固定时刻,程序仅能对文件中的一个元素进行读或写的操作,在向文件写入一个元素或从

文件读取一个元素后,相应的文件指针就前进到下一元素位置。而数组是按下标访问。

(3)在文件类型定义中无需规定文件的长度即元素的个数,就是说元素的数据可动态改变,一个文

件可以非常之大,包含许许多多元素,也可以没有任何元素,即为一个空文件。而数组的元素个数则是确

定的。

使用文件大致有以下几个步骤;

80

(1)说明文件类型,定义文件标识符;

(2)建立内部文件与外部文件的联系;

(3)打开文件;

(4)对文件进行操作;

(5)关闭文件。

Turbo Pascal将文件分为三类:文本文件(顺序)、有类型文件(顺序或随机)和无类型文件(顺序或

随机)。下面将介绍这些文件及其操作。

一、文本文件

文本文件又称为正文文件或行文文件,可供人们直接阅读,是人机通信的基本数据形式之一。文本文

件可用文字编辑程序(如DOS的edit或Turbo Pascal的编辑命令edit)直接建立、阅读和修改, 也可以

由PASCAL程序在运行过程中建立。

1、文本文件的定义:

文本文件的类型为TEXT,它是由ASCII字符组成的,是Pascal提供的标准文件之一。标准文件 TEXT

已由Pascal说明如下:

TYPE TEXT=FILE OF CHAR;

因此,TEXT同标准类型INTEGER、READ等一样可以直接用于变量说明之中,无需再由用户说明。

例如:

VAR F1,F2:TEXT;

这里定义了两个文本文件变量F1和F2。

2、文本文件的建立

文本文件的建立有两种方法:

(1)直接用Turbo Pascal的Edit建立原始数据文件。

例1 将下表中的数据存入名为的文件中。

3 4

29 30 50 60

80 90 70 75

60 50 70 45

操作步骤:

①进入Turbo Pascal的编辑状态;

②输入数据;

③存盘,文件名取。

此时,已将数据存入文本文件中。文本文件也可用DOS中的Edit等软件建立。

(2)用程序的方式建立中间数据或结果数据文件。

用程序的方式建立文件操作步骤为:

①定义文本文件变量;

②把一外部文件名赋于文本文件变量,使该文本文件与一相应外部文件相关联;

命令格式:ASSIGN(f,name)

f为定义的文本文件变量

name为实际文件文件名

如:ASSIGN(F1,``)

或:ASSIGN(F1,``)

这样在程序中对文本文件变量F1的操作,也就是对外部实际文件``或``的操

作。上例中文件``是存贮在当前目录中,而文件``则是存贮在PAS子目录中。

③打开文本文件,准备写;

命令格式1:REWRITE(f)

功能:创建并打开新文件准备写,若已有同名文件则删除再创建

81

命令格式2:APPEND(f)

功能:打开已存在的文件并追加

④对文件进行写操作;

命令格式:WRITE(f,<项目名>)

或:WRITELN(f,<项目名>)

功能:将项目内容写入文件f中

⑤文件操作完毕后,关闭文件。

命令格式:CLOSE(f)

例2 从键盘上读入表12.1的数据,用程序写入名为的文件中。

3、读取文本文件

文本文件内容读出操作步骤:

①定义文本文件变量;

②用ASSIGN(f,name)命令,将内部文件f与实际文件name联系起来;

③打开文本文件,准备读;

命令格式:READ(f,<变量名表>) READLN(f,<变量名表>)

功能:读文件f中指针指向的数据于变量中

文本文件提供了另外两个命令,在文本的操作中很有用处,它们是:

EOLN(f):回送行结束符

EOF(f):回送文件结束符

⑤文件操作完毕,用CLOSE(f)命令关闭文件。

例3 读出例12.1建立的文本文件,并输出。

82

由于文本文件是以ASCII码的方式存储,故查看文本文件的内容是极为方便,在DOS状态可使用 DOS

中TYPE等命令进行查看,在Turbo Pascal中可以象取程序一样取出文件进行查看。

4、文本文件的特点

(1)行结构

文本文件由若干行组成,行与行之间用行结束标记隔开,文件末尾有一个文件结束标记。由于各行长

度可能不同,所以无法计算出给定行在文本文件中的确定位置,从而只能顺序地处理文本文件,而且不能

对一文本文件同时进行输入和输出。

(2)自动转换功能

文本文件的每一个元素均为字符型,但在将文件元素读入到一个变量(整型,实型或字符串型)中时,

Pascal会自动将其转换为与变量相同的数据类型。与此相反在将一个变量写入文本文件时,也会自动转移

为字符型。

例4 某学习小组有10人,参加某次测验,考核6门功课, 统计每人的总分及各门的平均分,将原

始数据及结果数据放入文本文件中。

分析

(1)利用Turbo Pascal的EDIT建立原始数据文件存贮在磁盘中,其内容如下:

10 6

1 78 89 67 90 98 67

2 90 93 86 84 86 93

3 93 85 78 89 78 98

4 67 89 76 67 98 74

5 83 75 92 78 89 74

6 76 57 89 84 73 71

7 81 93 74 76 78 86

8 68 83 91 83 78 89

9 63 71 83 94 78 95

10 78 99 90 80 86 70

83

(2)程序读入原始数据文件,求每人的总分及各门的平均分;

(3)建立结果数据文件,文件名为.

程序:

84

例5 读入一个行长不定的文本文件。排版,建立一个行长固定为60个字符的文件, 排版要求:(1)

当行末不是一个完整单词时,行最后一个字符位用'-'代替, 表示与下一行行头组成完整的单词;(2)第一

行行头为两个空格,其余各行行头均不含有空格。

分析

(1)建立原始数据文件。

(2)程序边读入原始数据文件内容,边排版。

(3)每排完一行行长为60字符,并符合题中排版条件,写入目标文件中。

设原始数据文件内容如下:

Pavel was arrested.

That dat Mother did not light the stove.

Evening came and a cold wind was blowing.

There was a knock at the window.

Then another.

Mother was used to such knocks,but this time she gave a little start of joy.

Throwing a shawl over her shoulders,she opened the door.

程序:

85

对文本文件运行程序得到排版结果文件内容如下:

Pavel was dat Mother did not light the stov-

evening came and a cold wind was was a knock

86

at the was used to such knocks,b-

ut this time she gave a little start of ng a shawl

over her shoulders,she opened the door.

【作业】

1. 在一个只含有字母和空格的文本文件中,统计单词的个数。

文体文件如下:

afjds fdas df fie jfkdsa iej fds

fasjfd fjddk fdsa

2.在一个文本文件中存放着一行整数数据(个数N小于是100),将该数据读入到x数组中,按由大到小

的顺序排序,然后将排序后的数组存入到应该文件的第二行中。

3.写一个程序,统计文本中小写字母出现的个数。

4.有两个有序(由大到小)的整数文件(两个整数文件的数据互不相同),将两个文件合并成一个序的

文件。

计算机中数的表示及其运算

一、常见的数制及其特点

关于记数制,我们并不陌生,在日常生活中我们已经接触到很多计数制,比如十进制、六十进制(时

间)、十二进制(月份)等。在十进制中,可取的数字符号有:0,1,2,3,4,5,6,7,8,9,共10个。“逢十进

一”,这里记数制的基数正好等到于该数制中数字的个数。

对于任意一个十进制数,都可以表示成按权展开的多项式。如:

这里10称为基数,它是相邻数位的权之比。各位数的权是相邻基数10的整数次幂。从以上我们可以

归纳出进位计数制的特点。

①逢N进一,N是所需要符号的数目

②权:不同位置的单位数制的值。

二、常见的进位计数制

十进制:逢十进一,0,1,2,3,4,5,6,7,8,9 如984

二进制:逢二进一,0,1 如101011

八进制:逢八进一,0,1,2,3,4,5,6,7 如765

十六进制:逢十六进一,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F 如AF13

下面是几种见数的符号对照表。

十进制 二进制 八进制 十六进制

十进制 二进制 八进制 十六进制

0

1

2

3

4

5

6

0

1

10

11

100

101

110

0

1

2

3

4

5

6

0

1

2

3

4

5

6

9 1001

1010

1011

1100

1101

1110

1111

11

12

13

14

15

16

17

9

A

B

C

D

E

F

10

11

12

13

14

15

87

7

8

111

1000

7

10

7

8

16

17

10000

10001

20

21

10

11

三、把P进制转换为10进制。

把P进制转换为10进制的方法非常简单,只要按该进制数的权位展开求和。

在表示各种不同数制是也可表示为:1001.01B,17.26Q,3AD.D8H

四、把十进制转换为P进制

方法:整数部分:除P反序取余。

小数部分:乘P正序取整。

例:把(37.6875)10转换为二进制和八进制及十六进制

转换为二进制:

(37)10=(100101)2

转换为八进制:

(0.6875)10=(0.1011)2

(37.6875)10=(100101.1011)2

88

(37)10=(45)8

转换为十六进制:

(0.6875)10=(0.546)8

(37.6875)10=(45.546)8

(37)10=(24)16

(37.6875)10=(24.B)16

四、二进制、八进制、十六进制间的相互转换

(一)二进制和八进制的相互转换

由于存在

(0.6875)10=(0.B)16

,故一位八进制数相当于三位二进制数。即一位变三位、三位变一位。

如:(56.103)8=(101110.001000011)2

5 6 1 0 3

101 110 001 000 011

(1011.0011)2=(001,011.001,100)2=(13.14)8

(二)二进制和十六进制的相互转换

由于存在,故一位十六进制数相当于4位二进制数,即可一位变四位、四位变一位。

如:(3AD.B8)16=(1110101101.10111)2

3 A D B 8

0011 1010 1101 1011 1000

(1111100111.111111)2=(0011,1110,0111.1111,1100)2=()16

五、原码、反码和补码

1.原码:

整数X的原码是指:其符号位的0或1表示x的正或负,其余部分就是X绝对值的二进制表示。通常

用[X]原表示X的原码。

如:假设机器位数是8位,其中最高位是符号位,其余是数值部分。

89

[+17]原=00010001 [-17]原=1010001

值得注意的是:由于[+0]原=00000000 ,而[-0]原=10000000,所以数0的原码不是唯一的。有“正

零”和“负零”之分

2.反码

在反码的表示中,正数的反码表示方式与原码相同;负数的反码是把原码除符号位外的各位数取反(即

0变1,1变0)。通常用"[X]反"来表示。

如[+45]反=[+45]原=00101101

[-32]原=10100000 而[-32]反=11011111。

3.补码

整数的补码可表示为:正整数的补码与其原码相同;负数的补码是在其反码的基础上最低有效位上加

1。通常用"[X]补"表示X的补码。

如:[+14]补=[+14]原=00001110

[-36]原=10100100,而[-36]反=11011011,所以[-36]补=110111100

数0的补码表示是唯一的,即[0]补=[-0]补=00000000

例1:已知:X=6,Y=2 求X-Y

[X]补=00000110 [-Y]补=11111110

00000110

+)11111110

10000100

所以[X-Y]补=00000100 即X-Y=4

从上可以看出,加法和减法统一成了加法。

在一个8位机器数中,其表示数的范围为[M]补=01111111,即M=+127,而

[N]补=10000000,即N=-128,所以其表示范围为-128~+127之间,同样的道理,16位机器数中(补码)

其表示的范围为-32768~+32767之间。六:ASCII码

计算机内部用二进制数,从外部输入给计算机的所有信息必须用二进制数表示,并且对于各种命令、

字符都有需要转化为二进制数,这就涉及到信息符号转化为二进制数的编码问题,国际上统一采用美国的

标准信息编码ASCII,它用8位二进制数表示,最高位为0;中国的汉字编码则用两个字节表示,为了区

别一般编码,最高位设置为1,汉字编码有94个区,每个区有94位,一个区号和一个位号就可以唯一确定

一个汉字,称为区位码。

初赛中的试题

◆96初中基础第3题:请用等号或不等号表示下列不同进位制数值大小。例如:(3)10<(4)10=(100)2<(A)16,

其中圆括号右下角的下标,表示圆括号内数的进位制。

(98.375)10 = (142.3)8 > (58.6)16 > (1011000.0101)2

90

◆97初中第七题:已知ASCII码表中的大写字母有6个其它字符,接着便是小字字母。现已知A字母ASCII

码为(14)16{16表示16进制14},试写出如下字母用十进制表示的ASCII码:

G -->(72 )10 b -->(98)10 t --> (117)10

◆97初中第六题:一个汉字的机内码通常用2个字节表示:第一个字是区位码的区号加(160)10,第二个字

节是区位码的位码加(160)10。

已知:汉字"却"的区位码是4020,试写出内码两个字节的二进制代码:

1

1

1

0

0

1

0

1

1

0

0

1

0

0

0

0

答即为:160+40=200 160+20=180

◆98初中基础第六题:下面4个不同进制的数,最小的一个是(C )

A)(11011001)2 B)(75)10 C)(37)8 D)(A7)16

◆98初中第七题:小张用十六进制、八进制和十进制写下了如下的一个等到式:52-19=33式中三个数是

各不相同的进位制数,试问52、19、33,分别为(B)

A)八进制、十进制、十六进制 B)十进制、十六进制、八进制

B)八进制、十六进制、十进制 D)十进制、八进制、十六进制

◆如果用一个字节表示整数,最高位用作符号位,其它位表示数值。例如:

0

表示+1

1

0

0

0

0

0

0

0

0

0

0

0

0

1

1

表示-1

1)试问这样表示法的整数A的范围是( A)

A)-127<=A<=127 B)-128<=A<=128 C)-128<=A<128 D)-128

2)在这样的表示法中,以下(D)说法是正确的。

A)范围内每一个数都只有唯一的格式 B)范围内每一个数都有两种格式

C)范围内一半的数有两种格式 D)范围内只有一个有两种格式

点评:有正零和负零

◆99年初中第十三题:已知小写字母"m"的十六进制ASCII码值是6D,则小写字母"c"的十六进制数的ASCII

码值是( D)

A)98 B)62 C)99 D)63

91

◆99初中第14题:计算机中的数有浮点与定点数两种,其中用浮点数表示的数,通常由( C)这两部份组

A)指数与基数 B)尾数与小数 C)阶码和尾数 D)整数与小数

点评:浮点数的表示同数学中的科学计数法有相似之处,由小数及10的N次幂表示,计算机中的浮点数

则将小数部分表示为尾数,将10的N次幂的N作为阶码。

◆99初中第17题:十进制算术表达式:3*512+7*64+4*8+5的运算结果,用二进制表示为(B)

A)1 B) C) D)1

◆99初中基础18题:组成"教授"(JIAO SHOU),"副教授"(FU JIAO SHOU),"讲师"(JIANG SHI)这三个词的汉

字,在GB2312-80字符集中都是一级汉字,对这三个词的排序结果是( D)

A)教授、副教授、讲师 B)副教授、教授、讲师

C)讲师、副教授、教授 D)副教授、讲师、教授

◆2000年初中第一题:下列列符号数中最小的是(C)

A)(11011001)2 B)(75)10 C)(37)8 D)(2A)16

◆2000年初中题第题:GB2312-80规定了一级汉字3755个,二级汉字3008个,其中二级汉字字库中汉字

是以(B)为序排列的。

A)以笔划多少 B)以部首 C)以ASCII码 D)以机内码

点评:GB2312-80即为1981颁布的《信息交换用汉字编码字符集》共有6763个汉字,其中一级汉字3775

个按照拼音排序、二级汉字3008个,按照部首排序,另有682个图符号。

◆2001年初中第一题:在计算机内部,一切信息存取、处理和传递的形式是(C )

A)ASCII码 B)BCD码 C)二进制 D)十六进制

◆2001年初中第七题:与二进制数101.01011等值的十六进制数为(D )

A)A.B B)5.51 C)A.51 D)5.58

◆2002年普及组选择题:(0.5)10=(C ) 16.

A) 0.1 B) 0.75 C) 0.8 D) 0.25

◆2002年高中选择第三题:十进制数11/128可用二进制数码序列表示为:(D ) 。

A)1011/1000000 B)1011/100000000 C) 0.001011 D) 0.0001011

◆2002年高中选择第四题:算式(2047)10-(3FF)16+(2000)8的结果是( A) 。

A)(2048)10 B)(2049)10 C) (3746)8 D) (1AF7)16

◆2002年高中选择第五题:已知x=(0.1011010)2,则[x/2]补=(C ) 2 。

A) 0.1011101. B) 11110110 C) 0.0101101 D) 0.100110平:

点评:在二进制中除2相当于小数点移位

92

◆2003年初中选择题:十进制数2003等值于二进制数( A)。

A) B)10000011 C)110000111 D)010000011l E)1111010011

◆2003年初中选择:运算式(2008)10-(3723)8的结果是(B )。

A) (-1715)10 B) (5)10 C) (-5)16 D) (111)2 E) (3263)8

◆2003年高中选择题(多选题)运算试(2008)10-(3723)8 的结果是(BCD)

A)(-1715)10 B) (5)10 C) (5)16 D) (101)2 E) (3263)8

点评:本题是多选题

【作业】

1.写出0~16的二进制、八进制、十六进制。

2.把下列数转换为10进制数

(101101.101)2 (ABCD)16 (32)8

3.把十进制数转换为二进制数,保留4位小数。

(75.52) (101.01)

4.把二进制转换为8进制和16进制。

(101101.101)2 (110100)

5.把十六进制转换为八进制和二进制

(ABCD.1234)16 ()16

6.编写一个程序,把十进制转换为P进制(P<10),P用键盘输入。(可用数组)

7.将十进制整数K转换成二进制,以集合类型变量buf表示一个16位二进制数,如

(18)10=(10010)2,则buf中记为[2,5]表示倒数2、5位是1,其余为0。(可用集合)

93


本文标签: 程序 变量 类型 语句 文件