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。
版权声明:本文标题:Pascal教程 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://roclinux.cn/p/1735661381a1682564.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论