中学信息学奥林匹克竞赛培训教程
Pascal 语言和程序设计基础
(第一部分)
第一部分 Pascal 语言和程序设计基础
预备知识
基本程序结构和几个概念::
标识符 保留字 常量 变量 运算符 表达式 标准数据类型
Pacal 语言程序结构
Program prog_name;
var 变量申明;
begin
程序体;
end.
例如:
program pname;
const n=4;
type arr=array [1..4] of integer;
var i:integer; a:arr;
begin
for i:=1 to n do read(a[i]);
readln;
for i:=n downto 1 do write(a[i]:4);
writeln;
end.
以上是一个 PASCAL 程序。从键盘读入 4 个数据,逆序输出。
一般来说,一个 PASCAL 程序包括以下几个部分:
程序头:program pname; 其中,program 是保留字,表示程序从这个地方开始,pname 是标识符,
是程序的名字,可由程序员自定。保留字是 PASCAL 选定的,具有固定意义和用法的专用单词或
缩写,这些单词不允许作其它使用。如上,“program”就有“程序从这里开始”这样一种特别的意义,
而“const”就有“常量说明从这里开始”的意义。我们不能再用“program”、“const”来作为其它变量、
常量等的名字。标识符是以字母开头的字母数字串,其长度最大为 8 个字符。用来表示常量、变量、
类型、文件、过程、函数和程序的名字。如“pname”、“i”、“j”、“a1”就是合法的标识符;但“1a”、
“#a”是非法的标识符。有一点要注意的是,在 PASCAL 中,字母除了作为字符值或字符串值之外,
其大小写是无关的。如标识符“A1”和“a1”在 PASCLA 看来是同一标识符。在 PASCAL 中除了保留
字和自定义的标识符外,还有一类有特殊含义的标识符,这类标识符称为标准标识符。它们是用来
标记程序中经常引用的处理对象,如常量、函数。(PASCAL 定义的保留字和标准标识符附后)
标识符在命名的时候要注意:
1、名字要易记易读,有意义。如 8 皇后问题程序名可以是“queen”也可以是“huanghou”等;
2、不能用保留字、标准标识符作为自定义的标识符。
说明部分:
const n=4;
type ar=array [1..4] of integer;
var i:integer; a:ar;
其中,const 部分是常量说明,说明一些在以下部分用到的,在整个程序执行过程不改变值的
量。这些量 PASCAL 称为常量。在程序中用到这个值的地方均用常量名来代替。如上题中定义
“n=4”指本程序处理 4 个数值,在下面的程序体中就用“n”来代替具体的值(如 for i:=1 to n)。如果
要改变处理数据个数,则只在常量说明部分修改“n=4”这一句就行了,而不用在程序中每一个用到
的地方都加以修改。这样不但在编写程序的时候很方便,也增加了程序的可读性,修改时更方便。
常量说明在保留字“const”下开始。可以有多个语句。常量说明语句的格式是:“常量名=值;”。
如“n=4;”。n 是常量名,4 是该常量的值,“;”是语句分隔符。
type 部分是类型说明,说明一些在以下部分用到的数据类型。如数组、记录、指针等。
类型说明在保留字“type”下开始。可以有多个语句。类型说明语句的格式是:“类型名=类型说
明;”。如“ar=array [1..4] of integer;”。ar 是类型名,array [1..4] of integer 是类型说明,“;”是语句
分隔符。
var 部分是变量说明。变量是指在程序执行过程中可以通过赋值语句或读语句来改变值的量。
所有在程序中使用的变量都应该先在变量说明部分说明。PASCAL 中引用的每个变量都有“名字”和
“类型”属性。变量说明“说明”的主要工作是告诉 PASCA 下面程序中要用到这个名字的量,同时这
个量的类型是什么。
变量说明在保留字“var”下开始。可以有多个语句。变量说明语句的格式是:“变量名:变量类
型;”。其中,如果有多个变量同一类型,则变量名与变量名之间用逗号分隔,变量名与变量类型
之间用冒号分隔。如“i:integer;”(i 是变量名,integer 是类型名)、“i、j:integer;”(i、j 是变量
名,integer 是类型名)……
变量说明要注意:1、有效变量名称不能大于 8 个字符;2、变量名称必须以字母开头;3、在
同一个有效范围内变量名称必须唯一。
各个说明部分均以该部分的保留字开始。如“const”开始常量说明;“type”开始类型说明;“var”
开始变量说明。一个程序包含多少种类型的说明,看需要而定,不是每一个程序都必须同时包含这
三种说明。如果程序不须要用到常量,则常量说明部分可以省略;如果不须要用到类型说明,则类
型说明可省……
PASCAL 还有一条规则:先说明后引用。即所有在程序体中用到的“名字”必须都在说明部分说明
过才能引用,否则就会出错,通不过编译,也执行不了。如上,类型“ar”先在类型说明中定义,然
后在变量说明中引用;变量 i 在变量说明中定义,在程序中引用。
程序体:
begin
for i:=1 to n do
read(a[i]);
readln;
for i:=n downto 1 do
write(a[i]:4);
writeln;
end.
程序体是以 begin end.括起来的语句系列。“end”后面是一个小圆点,标识着程序结束,整个程
序只有一个是一个程序的主要部分。编程要完成的工作大部分都在这里完成。程序体中每一语句均
以“;”作为结束符。在书写程序时,以“分层缩进”的风格来写,以便提高程序的可读性。所谓的“分
层缩进”是指在逻辑上同一级的语句其起始点对齐,下一级的语句向右缩进。
运算符 表达式
PASCAL 中的运算符有算术运算符和关系运算符。和我们在数学课中学的基本一样但在写法上有些
不同,在写程序时要特别注意写法的不同:
+ 加号;- 减号;* 乘号( 数学中写为 × );/ 除号( 数学中写为 ÷);MOD 取余 如:8 MOD
2=0,7 MOD 2=1,2 MOD 3=2;DIV 取整 如:8 DIV 2=4,7 DIV 2=3,2 DIV 3=0。在 PASCAL 只
有上面 6 种数学运算。其它的就只能利用这 6 种运算的组合通过语句来实现。如 a^2(a 的平方)
可以化成 a*a。
> 大于;< 小于;<> 不等于(数学中写为 ≠);<= 小于等于(数学中写为≤);>= 大于等于(数
学中写为 ≥),
变量、常量通过运算符连接起来的式子我们称为表达式。一个单独的变量或常量也是表达式。
如 a、a+3、a*3+b 都是表达式。写表达式时要注意 PASCAL 表达式跟我们已经熟悉的数学表达式
在格式上的区别:
数学表达式 PASCAL 表达式 注意
2a 2*a *号不能省略
a÷b a/b 除号的写法
a≠b a<>b 不等号的写法
a≤b a<=b 小于等于号的写法
标准数据类型:整型 实型 字符型 布尔型
数据类型可以理解为一个取值范围和定义在这取值范围上的运算规则。想一想我们对于数的理
解:小学学自然数,范围是从 0 开始,那时候不知道有小数,也不知道有负数,允许的运算是+、
-、×、÷,而且对于减法规定被减数要大于减数。到了中学,数的范围扩大了,整数包括正数和负
数,减法运算也不再有额外的规定的了。同理,在 PASCAL 中“数据类型”也是一个取值范围和在
它上面定义的运算规则。PASCAL 中定义好的标准数据类型一共有 4 个:整型、实型、字符型、布
尔型,分别用保留字 integer、real、char、boolean 来标记它们。其取值范围和运算如下:
整型(integer):范围 -32768——32767;运算 + - * / mod div
实型(real):范围 运算 + - * /
字符型(char):范围 可显示的 ASCII 字符
布尔型(boolean):范围 true false 运算 and or not
在 PASCAL 中可使用的基本符号有:
(1)大写字母 A—Z ;小写字母 a—z ;数字 0—9
(2)其它字符 + — * / = > < >= <= <> :=
( ) [ ] . , :‘ $ ^ (* *) { }
其中,有些符号是以双字符作为一个整体,拆开后就失去原有的意义。如“<>”是一个表示“不
等于”的关系运算符,如拆开后就变成了两个关系运算符,分别表示“小于”、“大于”。
PASCAL 使用的保留字有:
AND、ARRAY、BEGIN、CASE、CONST、DIV、DO、DOWNTO、ELSE、END、FILE、
FOR 、 FUNCTION 、 GOTO 、 IF 、 IN 、 LABEL 、 MOD 、 NIL 、 NOT 、 OF 、 PACKED 、
PROCEDURE、PROGRAM、RECORD、REPEAT、SET、THEN、TO、TYPE、UNTIL、VAR、
WHILE、WITH、FORWARD
常用的标准标识符有:
标准常量:FALSE TRUE MAXINT MAXLONGINT
标准类型:INTEGER BOOLEAN REAL CHAR TEXT
标准文件:INPUT OUTPUT
标准函数:ABS ACTAN CHR COS EOF ELON EXP LN ODD
ORD PRED ROUND SIN SQR SQRT SUCC TRUNC
标准过程:ASSIGN GET NEW DISPOSE PACK PUT READ
READLN RESET REWRITE UNPACK WRITE WRITELN
函数格式:
function fun_name(参数表):数据类型;
var 变量声明;
begin
函数体;
end;
例题:写出计算两个整数 a,b 的和函数 add(a,b)。
过程格式:
procedure proc_name(参数表);
var 变量声明;
begin
过程体;
end;
例题:写出在屏幕打印一行文字:”hello,Pascal language is very easy!”
函数和过程的调用:
例题:从键盘输入:a,b 两个数,输出由这两个数为直角边的三角形的面积。【】
program xoi00_01;
function area(const a,b:real):real;
操作一
操作二
var s:real;
begin
s:=a*b/;
area:=s;
end;
procedure myproc;
var a,b:real;
s:real;
begin
write('Please input two number a,b:');
readln(a,b);
s:=area(a,b);
writeln('the area of trian is: ',s:5:2);
end;
{============= main program ================}
begin
myproc;
end.
练习:
一、判断以下标识符的合法性:
a3 3a a17 abcd α β λ
二、将下列的数学表达式改写成 PASCAL 表达式:
b^2-4ac
三、求下列表达式的值:
20 mod 19, 15 mod 9, 7 div 8 ,19 div 3,(4>5) and (7<8),(8>9) or ( 9<10),2 and ((3=3) or (3<7))
第一节 顺序结构
顺序结构是程序设计中最简单的结构,也是最基本的结构,它就是按照程序书写的顺序逐句执
行程序中的指令。流程图如下:
例题:计算圆的周长的过程:
输入圆的半径;(操作一)
计算圆的周长;(操作二)
输出圆的周长;(操作三)
基本的程序语句:
赋值语句:
赋值语句是最简单的语句,其一般形式为:
<变量>:=<表达式>;
“:=”称为赋值号,赋值语句的作用是计算表达式的值,并赋给变量。对于任何一个变量必须首
先赋值,然后才能引用,否则,未赋初值的变量将以一个随机值参与运算。另外,赋值号两边的类
型必须相同,但表达式值为整数时,它可自动化为实型后赋给该实型变量,即符合赋值相容。
如:Pi:=; R:=2; Age:=20; S:=Pi*R*R
例:关于赋值的例子
prssogram example;
var a,b:integer;
begin
a:=3;
b:=2;
a:=a+b;
writeln(a);
writeln(b);
end.
输入语句
通过计算机的外设把数据送到计算机内存的过程称为输入。Turbo Pascal 语言的输入语句有如
下两种形式:
read(<变量名表>);
readln(<变量名表>);
<变量名表>是一个或几个由逗号隔开的变量标识符,他们必须在程序说明部分预先说明,他们
可以是整型、实型或字符型,布尔型不可以直接读入。例如 a,b,c 为整型变量,read(a,b,c)之后,
键盘输入:20 30 40 <CR>(<CR>表示回车),结果: a=20,b=30,c=40
readln 语句和 read 语句不同之处在于输入数据到各变量之后,readln 自动换行,从下一行开始再输
入数据。一个 read 语句执行完后,数据行中多余的未读数据可以被下一个输入语句读入;而一个
readln 于执行完后,数据行中多余未读数据就没有用了。readln 语句中可以不包含变量名表。即有
以下等价情况:
read(a,b);readln 等价于 readln(a,b)
输入语句输入的数据类型必须和变量一一对应。如果输入的是一串整数或实数,数据间用空格
或回车分隔;若输入的是一串字符,则不用分隔。
输出语句
输出是将内存中的数据送到外设的过程。Turbo Pascal 的输出语句有两种形式:
write(<输出项表>);
writeln(<输出项表>);
其中<输出项表>是一串用逗号分隔的常量、变量、函数名、表达式或字符串。如果是变量、函
数名、表达式,则将其计算结果输出;如果是常量或字符串,则直接输出其值。
write 和 writeln 的区别在于:write 语句是输出项输出后,不换行,光标停留在最后一项后,
writeln 语句按项输出后,自动换行,光标则停留在下一行的开始位置。
writeln 语句允许不含有输出项,即仅 writeln;表示换行。
Turbo Pascal 语言把输出项的数据显示占用的宽度称为域宽,你可以根据输出格式的要求在输
出语句中自动定义每个输出项的宽度。定义宽度时分为单域宽和双域宽。
单域宽输出格式:writeln(I:n);
在 n 个字符宽的输出域上按右对齐方式输出 I 的值,若 n 大于 I 的实际位数,则在 I 值前面补(n-I
的实际位数)个空格。若 I 的实际位数大于 n,则自动突破限制。n 必须是整数。
双域宽输出格式:writeln(a:n:m);
双域宽主要用于实型数据的输出。n 的用法同上。在 n 个字符宽的输出域上按右队齐方式用小
数点形式输出 a 的数值,m 是小数点后的位数。原来的数据按该该格式指定的小数位数四舍五入。
若 m=0 ,则不输出小数部分和小数点,原数据四舍五入取整。n,m 必须是整数。
例:输出语句的例子
program shuchu;
const s='pascal';
var i:integer;r:real;c:char;b:boolean;
begin
i:=12345;
r:=
c:='a';
b:=true;
writeln('i=');
writeln(i:6);
writeln('r=',r,r:6:1);
writeln('c=',c,c:10);
writeln('b=',b,b:10)
end.
复合语句
复合语句是由若干语句组成的序列,语句之间用分号“;”隔开,并且以 begin 和 end 括起来,作
为一条语句。复合语句的一般形式:
begin
语句 1;
语句 2;
……
语句 n;
end;
例:变量值的交换
program swap;
var a,b,t:integer;
begin
a:=10;b:=20;
begin
t:=a;
a:=b;
b:=t;
end;
writeln('a=',a,'b=',b)
end.
例题 1:输入圆的半径,求出圆的周长和面积:
Progam CalCircle;
var R,C,S:Real;{变量声明}
begin
write(‘输入圆的半径:’);
readln(R);
C:=2*Pi*R;
write(‘周长=’,C);
readln;
S:=Pi*sqr(R);{sqr(R)=R*R}
write(‘面积=’,S);
readln;
end.
例题 2:找出下面程序中的语法错误。
Program Example1;
{计算圆环面积的程序,R2 表示外圆环的半径,R1 表示内圆环的半径,R2>R1}
var R1,R2:Real;
begin
S=(R2+R1)*(R2-R1)*Pi
{Pi= 为常数}
writeln(s)
end;
纠正以后的程序
Program Example1;
{计算圆环面积的程序,R2 表示外圆环的半径,R1 表示内圆环的半径,R2>R1}
var R1,R2:real;
S:real;{每一个变量都必须声明}
begin
S=(R2+R1)*(R2-R1)*Pi; {Pi= 为常数}
writeln(s); {语句必须以“;”结束}
end.{主程序必须以“.”结尾}
练习:
编写程序实现以下功能:
1、输入三角形三边的长,计算三角形的面积。
计算公式:
Pascal 程序中计算平方根的函数为:sqrt(x);{x:real; x 0}
基本要求:有友好的输入输出界面,不需要考虑输入的 a,b,c 是否可以构成三角形,假设输入的数
据符合要求。
第二节 IF 分支结构
例题: 输入一个考试分数,如果大于等于 60 就说恭喜你考试
及格,如果小于 60 就说真差劲,要努力哦!
program JudgeScore;
输入分数→score;
如果 Score≥60 那么
输出“恭喜你考试及格”
否则
输出“真差劲,要努力哦”
“如果...那么”形式的判断在 Pascal 中使用 If 语句来实现。IF 语句是由一个布尔表达式和两个供选
择的操作序列组成。运行时根据布尔表达式求值结果,选取其中之一的操作序列执行。有两种形式
的 IF 语句:
if <布尔表达式> then <语句>;
if <布尔表达式> then <语句 1>
else <语句 2>;
当布尔表达式的值为真,则执行 then 后面的语句,值为假时有两种情况:要么什么也不做,
要么执行 else 后面的语句。注意 else 前面没有分号,因为分号是两个语句之间的分隔符,而 else
并非语句。如果在该处添了分号,则在编译的时候就会认为 if 语句到此结束,而把 else 当作另一
句的开头,输出出错信息。
前面例题的 Pascal 程序代码:
Program JudgeScore;
var score:real;{声明分数变量 score}
begin
readln(score); {输入分数}
if score>=60 then
begin {score 代表分数的变量}
writeln(‘恭喜你,考试及格!’);
end else begin
writeln(‘真差劲,要努力哦!’);
end; {end if score>=60}
end.
例:求 y=f(x),当 x>0 时,y=1,当 x=0 时,y=0,当 x<0 时,y=-1
program lianxi;
var x,y:real;
begin
if x>0 then y:=1;
if x=0 then y:=0;
if x<0 then y:=-1;
writeln('y=',y);
end.
在 Turbo Pascal 语言 if 语句中被构造的语句只能是一条语句,当条件选择某个分支的计算要用
多个语句描述时,就必须把该分支用 begin 和 end 括来,写成复合语句。在用 if 语句连续嵌套时,
( )( )( )
2
s p p a p b p c
a b c
p
如果你插入适量的复合语句,有利于程序的阅读和理解。
例:当 x>0 时候,计算 x*x,并且输出 x 和 x*x。
program lianxi;
var x,x1:real;
begin
readln('x=',x);
if x>= then
begin
x1:=x*x;
writeln('x*x=',x1);
writeln('x=',x);
end;
end.
当 if 语句嵌套时,Turbo Pascal 约定 else
总是和最近的一个 if 配对。前面介绍了 If
语句的使用情况,下面来概括 if 判断语句
的使用方法。
分支结构的基本情况:
if 条件成立 then
begin
处理;
end;
下一语句;
if 条件成立 then
begin
操作 B;
end else {if 条件不成立 then }
begin
操作 A;
end;
下一语句;
练习:
写出下列关系表达式和逻辑表达式的 Pascal 语句:
1、 区分合格和不合格:x >= 60
2、 60 分到 70 分之间: ( x >= 60 ) and ( x <=70 )
3、判别闰年的条件(年份能被 4 整除,并且不能被 100 整除;或者能被 400 整除的整数年份):
((y mod 4 = 0) and (y mod 100 <> 0 )) or (y mod 400 = 0)
编写程序实现下列功能:
1、从键盘读入一个数,判断它的正负。是正数,则输出"+",是负数,则输出"-"
2、输入 a,b,c 三个不同的数,将它们按由小到大的顺序输出
3、铁路托运行李规定:行李重不超过 50 公斤的,托运费按每公斤 元计费;如超 50 公斤,超
过部分每公斤加收 元。编一程序完成自动计费工作。
4、打印某年某月有多少天。(提示:A、闰年的计算方法:年数能被 4 整除,并且不能被 100 整除;
或者能被 400 整除的整数年份。B、利用 MOD 运算可以判断一个数能否被另一个数整除)
5、从键盘输入 3 个数 a,b,c 输出其中最大的数。
第三节 Case 分支结构
case 语句是由一个表达式和众多可选择的操作序列组成。运行时,根据表达式的求值结果,在
众多的分支中选取一个分支执行。其形式为:
case 表达式 of
常量 1:语句 1;
常量 2:语句 2;
……
常量 n:语句 n;
else 语句 n+1; {可选项}
end;
表达式只能是顺序类型(除了实型以外的简单类
型),其值必须是唯一确定并且和表达式类型相同。case 语句执行和表达式值相匹配的 case 常数所
指向的那条语句,如果没有相匹配的值,则执行 else 部分(如果有的话)或者什么也不做。在 else
前面的语句末尾有分号,这是和 if 语句不同的。
Case 表达式的应用:
例题:输入一个考试分数(整数),根据分数情况报告相应的信息。
要求:假设输入的分数为[0,100]之间的整数。
Program JudgeScore2;
var x:real;
begin
read(x);{输入一个分数}
case x of
0..59:{ }
writeln(‘不及格’;
60..89:{ }
writeln(‘及格’);
90..100;{ }
writeln(‘优秀’);
else
writeln(‘错误的分数’);
end;{case x of}
end.
例:根据学生的成绩给予相应的等级,对应关系如下:
90——100 A
80——89 B
60——79 C
60以下 D
program chengji;
var s:real;ch:char;
begin
write('input the score: ');
readln(s);
if(s>=0)and(s<=100)then
case s div 10 of
10,9:ch:='A';
8:ch:='B';
7,6:='C';
else ch:='D';
end;
writeln(s,'--',ch);
end.
0 60
60 90
90 100
x
x
x
不及格
及格
优秀
0 60x
60 90x
90 100x
练习:
1、我们把字母作如下的分类:大写字母:’A’..’Z’;小写字母:’a’..’z’;数字:’0’..’9’;其他字母,
编写一个程序,根据上述分类的方法,输入一个字母,报告该字母所属的类型。
2、某超市为了促销,规定:购物不足 50 元的按原价付款,超过 50 不足 100 的按九折付款,
超过 100 元的,超过部分按八折付款。编一程序完成超市的自动计费的工作。
第四节 for 循环结构
程序设计时我们经常要做一些重复的任务通过反复的执行某一个动作来完成任务,编写这一类
程序我们使用循环结构来实现。如计算 1+2+3+….+100。Pascal 中循环结构通过使用 For、While、
Repeat 三种语句来实现。
For 语句是形式最简单的循环语句。
例题 1:输入正整数 N,计算
分析: =1+2+3+…+N,因此我们必需重复的执行 S:=S+i,其中 S 代表和,
S=1 {i=1}
S=1+2 {i=2}
S=1+2+3 {i=3}
S=1+2+3+4 {i=4}
….
S=1+2+3+4+…+N {i=N}
i 从 1 变化到 N,计算前 I 项的和:1+2+3+…+I,写成 Pascal 代码如下:
For i:=1 to N DO S:=S+i;{i 从 1 变化到 N 重复执行 S:=S+i}
完整的程序如下:
Program Example1_4
Var
N,I,S:integer;
Begin
Write(‘输入正整数 N:’);Readln(N);
S:=0;
For I:=0 to n do S:=S+I;
Writeln(‘1+2+3+…+’,n,’=’,s);
End.
FOR 循环有两种形式:
升序形式:for <控制变量>:=<初值> to <终值> do <语句>
降序形式:for <控制变量>:=<初值> downto <终值> do <语句>
for 语句功能描述:
虽然 for 循环形式简单,但是执行的机制却很复杂。其基本过程如下:
1. 计算初值并记忆
2. 判断初值是否超出终值、如果超过则执行步骤 7,
否则执行步骤 3
3. 把初值赋给控制变量
4. 执行 do 后面的语句(循环体)
5. 判断控制变量的值 是否达道终值,如果是则执行
步骤 6,否则执行步骤 7
6. 控制变量取下一个值(升序取后继,降序取前驱)
7. (循环结束)执行下一语句.
例题:编写程序输出序号从 32 到 126 的 ASCII 字符与对应
1
N
i
i
1
N
i
i
代码之间的对应关系。每行输出 5 个字符,输出结果如下如所示。(Example4_2)
program example4_2;
var i, j: byte;
begin
for i := 32 to 126 do
begin
if (j mod 5 = 0) then writeln;
write(i: 5, chr(i): 2);
j := j + 1;
end;
end.
程序说明:
标准函数 chr(i)可以得到代码为 i 的字符。j mod 5
求 j 模 5 的余数。语句 if (j mod 5 = 0) then writeln;用于
控制换行,每行写 5 个字符的对应关系。语句 write(i:
5, chr(i): 2);用于格式化输出结果。
编程完成下列计算:
1、
2、
3、把数码 1,2,3,4,…,9 分成 3 组,每组构成一个 3 位数,使这 3 个 3 位数恰好成 1:2:3,
该怎样分?求出所有的解答来。(如:192,384,576 就是一组解答)
4、 求出所有的三位数 ,它除以 11 所得余数等于它的三个数字的平方和。
第五节 while、repeat 循环结构
While 语句是另外一种实现循环的语句,一般形式如下:
While <条件> do <语句>
While 循环的执行过程如下:
1. 判断条件是否成立,条件成立时执行步骤 2,否则执行步骤 4
2. 执行 do 后面的语句(循环体)
3. 返回步骤 1
4. 结束循环,执行下一语句
注意:一定要有使条件取假(False)的时候,否则会出现死循环。
例题:从键盘输入一批学生考试数据,统计这些数据中大于 80 的数的个数。
分析:因为学生的人数没有确定,因此不方便用 for 循环来完成此项工作,但是用 while 循环比较
容易实现。(example4_3)
while score>=0 do
输入一个学生成绩→score;计算总分;
Pascal 代码:
while score >= 0 do
begin
readln(score);
total := total + score;
end;
完整的程序代码:
program example4_3;
var
score: integer;
2 2 2 2
1
1 2 ...
N
i
i N
11 1 ( 1)
1 ......
2 3
n
n
xyz
total: integer;
c: char;
begin
writeln('输入学生分数:');
readln(score);
total:=0;
while score >= 0 do
begin
readln(score);
total := total + score;
end;
writeln('总分为:',total);
read(c);
end.
Repeat 语句与 while 语句基本类类似,只是 while 先判断条件,reapeat 语句先执行循环体然后再判
断。
Repeat
<语句>;{循环体部分}
Until <条件>;{循环结束条件}
执行过程如下:
1. 执行循环体
2. 判断条件,如果布满足重复 1,否则 执行步骤 3
3. 结束循环,执行下一语句
例题:改写 Example4_3 程序使用 Repeat 循环语句实现。(Example4_4)
program example4_4;
var
score: integer;
total: integer;
c: char;
begin
writeln('输入学生分数:');
total := 0;
repeat
readln(score);
total := total + score;
until score < 0;
writeln('总分为:', total);
read(c);
end.
练习:
1、 计算下列式子的值:
(1) 1+3+5+…+99
(2) 1+2+4+8+…+128+256+512+1024
(3) 1+(1+2)+(1+2+3)+…+(1+2+3+4+…+N)
2、 有一分数序列: 求出这个数列的前 20 项的和。
3、 求水仙花数。所谓水仙花数,是指一个三位数 ,如果满足 ,则 abc 是水
仙花数。
4、 输入一个整数,计算它各位上数字的和。(注意:是任意位的整数)
5、 输入一整数 A,判断它是否质数。(提示:若从 2 到 A 的平方根的范围内,没有一个数能整除
A,则 A 是质数。)
1 3 5 8 13 21
, , , , , ,......
2 2 3 5 8 13
abc 3 3 3a b c abc
6、 求两个数的最小公倍数和最大公约数。(提示:公约数一定小于等于两数中的小数,且能整除
两数中的大数。公倍数一定大于等于两数中的大数,且是大数的倍数,又能给两数中的小数整
除。)
7、 编写一个译码程序,把一个英语句子译成数字代码。译码规则是以数字 1 代替字母 A,数字 2
代替字母 B,……,26 代替字母 Z,如遇空格则打印一个星号‘*’,英文句子以‘.‘结束。
8、 “百钱买百鸡”是我国古代的著名数学题。题目这样描述:3 文钱可以买 1 只公鸡,2 文钱可以
买一只母鸡,1 文钱可以买 3 只小鸡。用 100 文钱买 100 只鸡,那么各有公鸡、母鸡、小鸡多
少只?与之相似,有"鸡兔同笼"问题。
9、 输入一个正整数 N,把它分解成质因子相乘的形式。如:36=1×2×2×3×3; 19=1×19(提示:设
因子为 I,从 2 开始到 N,让 N 重复被 I 除,如果能整除,则用商取代 N,I 为一个因子;如果
不能整除,再将 I 增大,继续以上操作,直到 I 等于 N。)
10、 编 程 实 现 : 求 之 值 , 其 中 a 是 一 个 数 字 。 例 如 :
(当 n=5 时),n 由键盘输入。
11、 一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如:6 的因子为 1、2、3,
而 6=1+2+3,因此 6 是“完数”。编程序找出 1000 以内的所有完数。
12、 编一程序,输入 a,b,c,d,e,f,然后解出方程组 的解。
第六节 数据类型
简单数据类型
Pascal 语言基本数据类型由:integer(longint,shortint,byte),real,char,Boolean.等构成。
自定义数据类型:
我们可以 在基本数据类型的基础上定义新的数据类型,类型定义的保留字为“Type”,格式为:
TYPE
<类型标识符>=<数据类型>
如:
Type
MyLong=Longint;
枚举类型:
“枚举”的意思就是把所需要的对象都一个一个的列举出来。比方说星期是一个只有 7 个元素的数
据,因此我们可以定义一种数据类型 TWeekDay 代表星期,如果一个变量定义为 TWeekDay 类型,
那么他的取值范围就是 Sunday..Saturday,另外颜色 TColor 也一样。习惯上我们在 自定义类型名
称前加上“T”,如 TColor,TWeekDay,而且单词以大写字母开始。
Type
TWeekDay=(Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday);
TColor=(Red,Yellow,Blue,,White,Black);
枚举变量的第一个代表 0,第二个 代表 1,以此类推,如上面定义的 TweekDay 类型,Sunday=0,
Monday=1,…,Saturday=6。
例题:输入今天的日期数字:0=Sunday,1=Monday,…6=Saturday,输出明天的日期,用英文
单词表示。【】
program xoi00_02;
Type TWeekDay=(Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday);
var today,tomorrow:TWeekDay;
number,i:integer;
begin
write('Enter today number:');readln(number);
if (number<0) or (number>6) then
writeln('Error number')
else begin
today:=Sunday;
... ...
n
ns a aa aaa aaa aaa
64 7 48
2 22 222 2222 22222
aX bY c
dX eY f
for i:=0 to number-1 do today:=succ(today);
if today=Saturday then
tomorrow:=Saturday
else
tomorrow:=succ(today);
write('Tomorrow is:');
case tomorrow of
Sunday:writeln('Sunday');
Monday:writeln('Monday');
Thursday:writeln('Thusday');
Wednesday:writeln('Wednesday');
Thursday:writeln('Thursday');
Friday:writeln('Friday');
Saturday:writeln('Saturday');
end;{if today=saturday then}
end;{if (number<0) or (number >6)}
end.
子界类型:
子界类型是在其它的离散类型的值域中取出一部分构成独立的类型。
子界类型的一般定义形式如下:
TYPE
<子界类型标识符>=<下界常量>..<上界常量>;
如: TYPE Tmonth=1..12;
TYPE Tscore=0..100;
例 按月、日、年顺序读入一日期,输出该日期是这一年中的第几天。
program date;
var year:0..2010;
month,i:1..12;
day:1..31;
dayth:integer;
begin
read(month,day,year);
dyath:=0;
for i:=1 to month-1 do
case i of
1,3,5,7,8,10,12:dayth:=dayth+31;
2:if ((year mod 4=0)and(year mod 100<>0)or(year mod 400 =0)
then dayth:=dayth+29
else dayth=:=dayth+28;
4,6,9,11:dayth:=dayth+30;
end;
dayth:=dayth+day;
writeln(dayth)
end.
数组类型:
定义数组:
Type
数组类型标识符=Array[下标类型] OF 数组元素类型
数组元素类型本身也可以是复杂的自定义类型,如子界类型,数组类型,记录等。
例如:定义存放学生姓名的字符数组:
TYPE TName=Array[1..20] of Char;
定义一个存放班级学生(50 人)名单的数组:
TYPE TStudents=Array[1..50] of TName
也可以这么定义:
TYPE TStudents=Array[1..50] of Array[1..20] of Char;
例 1:输入 5 个考分数,计算它们的总分。【】
program xoi00_03;
Type TScore=Array[1..5] of integer;
var score:TScore; i:integer;sum:integer;
begin
for i:=1 to 5 do
begin
write('Enter Number #',i);
readln(score[i]);
end;
sum:=0;
for i:=1 to 5 do
begin
sum:=sum+score[i];
end;
writeln('Total Score is:',sum);
end.
例 2:从键盘输入 10 个数,将这 10 个数逆序输入,并求这 10 个数的和,输出这个和。
program p1;
var
a: array[1..10] of integer;
i, s: integer;
begin
for i := 1 to 10 do
read(a[i]);
for i := 10 downto 1 do
write(a[i], ' ');
writeln;
s := 0;
for i := 1 to 10 do
s := s + a[i];
writeln('s=', s);
end.
例 3:用筛法求 100 以内的素数(质数)。
分析:素数是除了 1 和它本身以外没有其它约数的数。用筛法求素数的方法是:用质数筛去合数:
从第一个素数 2 开始,把它的倍数去掉;这样 2 以后的第一个非 0 数就一定也是素数,把它的倍数
也删了……重复这个删数过程,直到在所找到的素数后再也找不到一个非 0 数。把所有非 0 数输出。
program p2;
var
a: array[1..100] of integer;
i, j, k: integer;
begin
for i := 1 to 100 do
a[i] := i;
a[1] := 0;
i := 2;
while i <= 100 do
begin
k := i;
while k <= 100 do
begin
k := k + i;
a[k] := 0;
end;
{----上面将所有 a[i]的倍数清 0}
i := i + 1;
while a[i] = 0 do
i := i + 1;
{----查找接下来的第一个非 0 数}
end;
for i := 1 to 100 do
if a[i] <> 0 then write(a[i], ' ');
end.
字符串类型:
如果数组存放的是字符,则成为字符数组。例如前面提到的学生姓名:Tname 可以存放 20 个字
符。为了操作方便 Turbo Pascal 提供了字符串类型和操作函数。字符串类型:String。例如前面的学
生姓名可以定义为:Type TName=String[20];
字符串定义时,如不指定长度,则按该类型的最大长度(255 个字符)分配空间,使用时最大
可用长度为 255 个;如果在中括号中给出一个具体的值(1—255 之间),则按这个值的大小分配空
间。使用时,最大的可用长度即为该值。
字符串类型既可按数组方式输入、输出,也可直接输入、输出:readln(s);writeln(s);多个字
符串输入时以回车作为数据间的分隔符;每个 readln 语句只能读入一个字符串。
操作函数:
连接函数:concat(s1,s1,…,sn),相当于:S1+S2+…+Sn
截取子字符串:copy(S,I,L),从字符串 S 左边第 I 个字符起连续截取 L 个字符。
长度函数:length(S),计算字符串 S 的长度。Length(S)=Ord(S[0])
子串点的函数:pos(P,S),返回 P 在 S 中第一次出现的位置。
删除子串过程:delete(S,I,L),在 S 中从的 I 个字符起删除 L 个字符。
插入子串函数:insert(S,D,L),在 D 中的第 I 个字符位置插入字符串 S。
记录类型:
记录类型由固定数量的具有不同类型的成分组成,在实际的程序设计中,这种类型非常有用,
比方说学生的信息包括:学号,姓名,语文,数学,英语成绩,平均分等组成,用一个简单的数据
类型无法表达。我们可以这样定义:
Type
TScore=0..100;
TScores=Array[1..5] of TScore;
TStudent=Record
NO:String[5];
Name:String[16];
Score:TScores;
Avg:Real;
End;{End Type TStudent}
TStudents=Array[1..50] of TStudent;
在程序中可以使用 Var student:Tstudents;定义一个学生变量,可以使用 student[1].Name 来访问学生
的姓名。
集合类型:
集合是指相同类型的数据汇集在一起构成的数据结构,如学生集合,类似于数学中的集合,但
是构成集合的数据类型必须是简单的离散类型,如:Byte,Shortint,Longint,char,Boolean,枚
举,子界类型。
定义:
Type
<集合数据类型标识符>= Set of <基类型>;
例如:
Type UperLetters= Set of [‘A’..’Z’];
Type EvenDigits=Set of [0,2,4,6,8];
集合的运算:并:+;差:-;相等:=;不等:<>;包含:>=;包含于:<=;属于:in;
具体含义参考数学中的集合运算。
例 4:传说中有一个残暴的国王,喜欢杀戮百姓。有一次,他抓到 30 个百姓并要一一杀掉。在这 30
个百姓中间有一个聪明人,他站出来对国王说:“请国王大发慈悲,赦免二人不死。”国王问:“赦
免哪二人不死?”那个聪明人回答说:“我们 30 个人围成一圈,从 1 开始报数,凡数到 5 的人就拉
出去杀掉。剩下的人继续从 1 开始报数,循环反复,直到剩下两个人为止,这两个人被赦免。”国
王一听很有意思,采纳了聪明人的建议,赦免了两个人,而那个聪明人就是其中之一。请你设计一
个程序,由计算机判断聪明人要站在什么位置,才能躲过这一场屠杀。
问题分析:
首先,设百姓的人数为 M 人,设数到 N 的人被杀掉。用数组 A(M)存放 M 个人是否还在圈
中的信息。其中,A(I)=1 表示第 I 个人还在圈中。A(I)=0 表示第 I 个人已被杀掉。开始时,
数组 A 中所有的元素都是 1,表示每个人都站在圈中。用 K=K+A(I)来实现报数功能,因为只
有还在圈中的人才能使 K 的值增加。用变量 D 来记录出圈的人数,当 D=M 时,表示所有的人都
出圈了。最后出圈的两个人就是被赦免的人。
程序清单:【】
program xoi00_05;
const m = 100;
const n = 10;
var a: array[1..m] of integer;
i, d, k, p: integer;
begin
writeln; writeln('====================');
for i := 1 to m do a[i] := 1;
d := 0; k := 0;
while true do begin
for i := 1 to m do begin
k := k + a[i];
if k <> n then continue;
write(i: 4);
p := p + 1;
if p > 9 then begin p := 0; writeln; end;
a[i] := 0;
k := 0;
d := d + 1;
if d = m then exit;
end;
end; {while}
end.
例 5:输入一个十进制数,将其转换成二进制数。
输入:[KEYBOARD] 输出:[SCREEN]
255
FF
[问题分析] 模拟手算.
program bin;
const max = 20;
var i, j: integer; str: array[1..max] of byte;
procedure print;
var k, r: integer;
begin
k := max;
repeat
dec(k);
until str[k] = 1;
for r := k downto 1 do write(str[r]);
writeln;
end;
begin
write('Please input an integer between 1..32767:'); readln(i);
j := 0;
repeat
inc(j);
str[j] := i mod 2; i := i div 2;
until i = 1;
str[j + 1] := 1;
print;
end.
练习:
1、 数学黑洞 6174:已知:一个任意的四位正整数。将数字重新组合成一个最大的数和最小的数相
减,重复这个过程,最多七步,必得 6174。即:7641-1467=6174。将永远出不来。求证:所有
四位数数字(全相同的除外),均能得到 6174。输出掉进黑洞的步数。
2、 随机产生 20 个三位数,将这 20 个数按从小到大的顺序排列,要求在排列中,用尽可能少的交
换次数。
3、 输入 10 个学生的姓名,编一程序将它们按字母的顺序排列。
4、 有一组数,其排列形式如下:11,19,9,12,5,20,1,18,4,16,6,10,15,2,17,3,
14,7,13,8,且尾部 8 和头部 11 首尾相连,构成环形的一组数,编程找出相邻的 4 个数,
其相加之和最大,并给出它们的起始位置。
5、 有一组数其排列顺序如下:(设有 N 个)3,6,11,45,23,70,67,34,26,89,90,15,
56,50,20,10。编一程序交换这组数中任意指定的两段。
6、 有 M 个猴子围成一圈,每个有一个编号,编号从 1 到 M。打算从中选出一个大王。经过协商,
决定选大王的规则如下:从第一个开始,每隔 N 个,数到的猴子出圈,最后剩下来的就是大王。
要求:从键盘输入 M,N,编程计算哪一个编号的猴子成为大王。
7、 请你设计一个程序,让计算机找出 40 个自然数来,使得其中任意两个数之差均不相等。
问题分析:
首先,开辟一个数组 S(I),准备存放这 40 个数,再开辟一个数组 CHA(I),用来存放两个数的
差。
寻找某一个满足条件的自然数的过程如下:
把 1 和 2 放进数组 S 中; 把 1 放进数组 CHA 中; 当寻找下一个自然数时,要把这个自然数
与数组 S 中的每一个数相减,再判断所得的差是否在数组 CHA 中;如果所得的差不在数组 CHA
中,说明又找到一个满足条件的自然数。把这个自然数放进数组 S 中,同时把这个自然数与数组 S
中原有的每一个自然数的差记录在数组 S 中去。如果所得的差与数组 CHA 中的某一个数重复,说
明这个自然数不符合条件,继续寻找下一个自然数。 重复步骤(3),直到找到 40 个自然数为止。
第七节 常用函数
Pascal 中的数学函数
求绝对值函数 abs(x)
定义:function Abs(X): (Same type as parameter);
说明:X 可以是整型,也可以是实型;返回值和 X 的类型一致
例子:
var
r: Real;
i: Integer;
begin
r := Abs(); { }
i := Abs(-157); { 157 }
end.
取整函数 int(x)
定义:function Int(X: Real): Real;
注意:X 是实型数,返回值也是实型的;返回的是 X 的整数部分,也就是说,X 被截尾了(而不
是四舍五入)
例子:
var R: Real;
begin
R := Int(); { }
R := Int(); { }
end.
截尾函数 trunc(x)
定义:function Trunc(X: Real): Longint;
注意:X 是实型表达式. Trunc 返回 Longint 型的 X 的整数部分
例子:
begin
Writeln(, ' becomes ', Trunc()); { 1 }
Writeln(, ' becomes ', Trunc()); { 1 }
Writeln(, 'becomes ', Trunc()); { -1 }
Writeln(, 'becomes ', Trunc()); { -1 }end.
四舍五入函数 round(x)
定义:function Round(X: Real): Longint;
注意:X 是实型表达式. Round 返回 Longint 型的 X 的四舍五入值.如果返回值超出了 Longint 的表
示范围,则出错.
例子:
begin
Writeln(, ' rounds to ', Round()); { 1 }
Writeln(, ' rounds to ', Round()); { 2 }
Writeln(, 'rounds to ', Round());{ -1 }
Writeln(, 'rounds to ', Round());{ -2 }
end.
取小数函数 frac(x)
定义:function Frac(X: Real): Real;
注意:X 是实型表达式. 结果返回 X 的小数部分; 也就是说,Frac(X) = X - Int(_X).
例子:
var
R: Real;
begin
R := Frac(); { }
R := Frac(); { }
end.
求平方根函数 sqrt(x)和平方函数 sqr(x)
定义:平方根:function Sqrt(X: Real): Real;
注意:X 是实型表达式. 返回实型的 X 的平方根.
平方:function Sqr(X): (Same type as parameter);
注意:X 是实型或整型表达式.返回值的类型和 X 的类型一致,大小是 X 的平方,即 X*X.
例子:
begin
Writeln('5 squared is ', Sqr(5)); { 25 }
Writeln('The square root of 2 is ',Sqrt()); { }
end.
字符串函数
求长度 length
定义:function Length(S: String): Integer;
例子:
var
S: String;
begin
Readln (S);
Writeln('"', S, '"');
Writeln('length = ', Length(S));
end.
复制子串 copy
定义: function Copy(S: String; Index: Integer; Count: Integer): String;
注意:S 是字符串类型的表达式。Index 和 Count 是整型表达式。Copy 返回 S 中从 Index 开始,Count
个字符长的一个子串。
例子:
var S: String;
begin
S := 'ABCDEF';
S := Copy(S, 2, 3); { 'BCD' }
end.
插入子串 insert
定义:procedure Insert(Source: String; var S: String; Index: Integer);
注意:Source 是字符串类型的表达式。 S 是任意长度字符串类型变量。Index 是整型表达式。Insert
把 Source 插在 S 中 Index 处。如果结果字符串的长度大于 255,那么 255 之后的字符将被删除。
例子:
var
S: String;
begin
S := 'Honest Lincoln';
Insert('Abe ', S, 8); { 'Honest Abe Lincoln' }
end.
删除子串 delete
定义:procedure Delete(var S: String; Index: Integer; Count:Integer);
注意:S 是字符串类型变量。 Index 和 Countare 是整型表达式。Delete 删除 S 中从 Index 开始的 Count
个字符。如果 Index 大于 S 的长度,则不删除任何字符;如果 Count 大于 S 中从 Index 开始的实际
字符数,则删除实际的字符数。
例子:
var
s: string;
begin
s := 'Honest Abe Lincoln';
Delete(s,8,4);
Writeln(s); { 'Honest Lincoln' }
Delete(s,9,10);
Writeln(s); { 'Honest L' }
end.
字符串转为数值 val
定义: procedure Val(S; var V; var Code: Integer);
在这里:
S 是由一系列数字字符构成的字符串类型变量;。
V 是整型或实型变量;
Code 是 Integer 型变量
注意:Val 将 S 转为它的数值形式。
例子:
var s:string;I, Code: Integer;
begin
s:='1234';
val(s,i,code);
writeln(i); { 1234 }
end.
数值转为字符串 str
定义: procedure Str(X [: Width [: Decimals ]]; var S:string);
注意:将数值 X 转成字符串形式。
例子:
var
S: string[11];
begin
Str(I, S);
IntToStr := S;
end;
begin
Writeln(IntToStr(-5322));
Readln;
end.
求子串起始位置 pos
定义:function Pos(Substr: String; S: String): Byte;
注意:Substr 和 S 字符串类型表达式。Pos 在 S 中搜索 Substr 并返回一个 integer 值。这个值是 Substr
的第一个字符在 S 中的位置。如果在 S 中没有找到 Substr,则 Pos 返回 0。
例子:
var S: String;
begin
S := ' ';
{ Convert spaces to zeroes }
while Pos(' ', S) > 0 do
S[Pos(' ', S)] := '0';
end.
字符完全串连+
定义:操作符+把两个字符串联在一起。
例子:
var s1,s2,s:string;
begin
s1:='Turbo ';
s2:='pascal';
s:=s1+s2; { 'Turbo pascal' }
end.
字符串压缩空格串连-
定义:操作符-去掉第一个字符串最后的空格后,将两个字符串联在一起。
例子:
var s1,s2,s:string;
begin
s1:='Turbo ';
s2:='pascal';
s:=s1-s2; { 'Turbopascal' }
end.
第八节 指针
指针的动态变量
1.定义指针类型
在 Turbo Pascal 中,指针变量中存放的某个存储单元的地址,即指针变量指向某个存储单元。
一个指针变量仅能指向某一种类型的存储单元,这种数据类型是在指针类型的定义中确定的,称为
指针类型的基类型。指针类型定义如下:
类型名=^基类型名;
例如:type q=^integer;
var a,b,c:q;
说明 q 是一指向整型存储单元的指针类型,其中"^"为指针符。a,b,c 均定义为指针变量,分别
可以指向一个整型存储单元。
上例也可定义为:
var a,b,c:^integer;
指针也可以指向有结构的存储单元。
例如:type person=record
name:string[10];
sex:(male,female);
age:20..70
end;
var pt:^person;
pt 为指向记录类型 person 的指针变量。
2.动态变量
应用一个指针指向的动态存储单元即动态变量的形式如下:
指针变量名^
例如:p^、q^、r^
指针变量 p 和它所指向的动态变量^p 之间有如下关系:
P->P'
以下语句把整数 5 存放到 p 所指向的动态变量 p^ 中去:
p^:=5;
以下语句把 p 所指向的 p^中的值赋给整型变量 i:
i:=p^;
如果指针变量 p 并未指向任何存储单元,则可用下列赋值语句:
p:=nil;
其中 nil 是 Turbo Pascal 保留字,表示“空”,相当于 C 里面的 null
对动态变量的操作
在 Turob Pascal 程序中,动态变量不能由 var 直接定义而是通过调用标准过程 new 建立的。过
程形式为:
new(指针变量名);
如果有下列变量定义语句:
var p:^integer;
仅仅说明了 p 是一个指向整型变量单元的指针变量,但这个整型单元并不存在,在指针变量 p
中还没有具体的地址值。在程序中必须通过过程调用语句:new(p);才在内存中分配了一个整型变量
单元,并把这个单元的地址放在变量 p 中,一个指针变量只能存放一个地址。在同一时间内一个指
针只能指向一个变量单元。当程序再次执行 new(p)时,又在内存中新建立了一个整型变量单元,并
把新单元的地址存放在 p 中,从而丢失了旧的变量单元的地址。
为了节省内存空间,对于一些已经不使用的现有动态变量,应该使用标准过程 dispose 予以释
放。过程形式为:dispose(指针变量名);为 new(指针变量名)的逆过程,其作用是释放由指针变量
所指向的动态变量的存储单元。例如在用了 new(p)后在调用 dispose(p),则指针 p 所指向的动态变
量被撤销,内存空间还给系统,这时 p 的值为 nil。
例:输入两个数,要求先打印大数后打印小数的方式输出,用动态变量做。
program dongtai;
type intepter=^integer;
var p1,p2:intepter;
procedure swap(var,q1,q2:intepter);
var p:integer;
begin
p:=q1;q1:=q2;q2:=p;
end;
begin
new(p1);new(p2);
writeln('input 2 data: ');readln(p1^,p2^);
if p1^ then writeln('output 2 data: ',p1^:4,p2^:$);
end.
第九节 文件操作
类型文件
按数据的二进制代码形式存放时的文件称为类型文件。如果再按照组成类型文件的元素数据结
构分,又可以分为有类型文件和无类型文件。其定义为:
type 类型名=file of 基类型;{有类型文件}
类型名=file; {无类型文件}
例如:var f:file of integer;
说明 f 为名的变量对应文件将用于存放整数。
var g:file;
说明 g 为名的变量对应文件的数据无任何规定。
Turbo Pascal 有关类型文件的函数和过程
(1)assign 过程
形式:assign(f,str);
功能:将文件名字符串 str 赋给文件变量 f,程序对文件变量 f 的操作代替对文件 str 的操作。
(2)rewrite 过程
形式:rewrite(f);
功能:建立并打开一个新的允许写磁盘文件,其文件名必须先由 assign 过程赋给变量 f。这时,
指向文件元素的指针指向第一个元素,rewrite 过程所建立的文件为空文件。
(3)reset 过程
形式:reset(f);
功能:打开一个已经存在的磁盘文件,其文件名必须先由 assign 过程赋给变量 f,该文件只能读,
指向文件元素的指针指向第一个元素。
(4)read 过程
形式:read(f,var 表);
功能:从磁盘文件 f 中,将数据依次读到 var 表表示的各个变量中。
(5)write 过程
形式:write(f,var 表);
功能:将 var 表所表示的各个变量的值依次写到磁盘文件 f 上。
(6)close 过程
形式:close(f);
功能:关闭和 f 关联的磁盘文件,在写操作时自动产生一个文件结束标志。
(7)seek 过程
形式:seek(f,n);
功能:把文件指针移到 f 指明文件的第 n 个元素。
(8)eof 函数
形式:eof(f);
功能:若文件指向文件尾,则返回 true,否则返回 false。
对有类型文件的写操作步骤为:
assign(f,str);
rewrite(f);
write(f,var 表);
close(f);
对有类型文件的读操作步骤为:
assign(f,str);
reset(f);
read(f,var 表);
close(f);
例:在磁盘上建立一个 1~50 的平方数的数据文件 。要求以一个数,这个数的平方数的
格式写入。
program zhoufei;
var f:file of integer;
i:integer;
begin
assign(f,'');
rewrite(f);
for i:=1 to 50 do write(f,i,sqr(i));
close(f)
end.
文本文件
文本文件的内容有 ASCII 字符集中的字符组成,因此文本文件也称 ASCII 码文件,它可以用
DOS 中的 type 命令列出内容。文本文件具体是由一系列行组成,每一行可以包括 0 个或多个字符
型成分,并以也行结束符结尾,文本文件类型 TXT 和类型文件 file of char 区别在于后者不包含行
结束符。
文本文件和类型文件在读写上的差别在于前者只能按次序顺序读写,而后者可以不按照次序读
写。适用文本文件的函数和过程除了用于类型文件操作的过程和函数外主要还有:
(1)readln 过程
形式:readln(f,var 表);或 readln(f);
功能:从磁盘文件 f 中,将数据依次读到 var 表表示的各变量中(其中 readln(f)只读数据),并将文
件指针移到行结束符后,就是下一行开头。
(2)writeln 过程
形式:writeln(f,var 表)或 writeln(f);
功能:将 var 表所表示的各个变量的值依次写到磁盘文件 f 上去(writeln(f)不写值),然后再写
一个行结束符。
(3)append 过程
形式:append(f);
功能:打开一个已经存在的磁盘文件,其文件名必须和 assign 过程中的变量名 f 相对应,该文
件只能写,此时文件指针指向文件尾。
(4)eoln 函数
形式:eoln(f);
功能:若文件指针指向行结束符或文件结束符,则返回 true,否则返回 false。
对文本文件的写操作步骤:
assign(f,str);
rewrite(f); 或 append(f);
write(f,var 表);或 writeln(f);
close(f);
对文本文件的读操作步骤:
assign(f,str);
reset(f);
readln(f,var 表);或 readln(f);
close(f);
例:随机产生 30 个随机整数存放于文本文件 中
program zhoufei;
const n=30;
var ra:text;
i:integer;
begin
randomize;
assign(ra,'');
rewrite(ra);
for i:=1 to n do writeln(ra,random(100));
close(ra)
end.
练习:
1、从键盘输入一行字符,把输入的字符存入磁盘文件中。
2、编一个程序,从磁盘读入一个文本文件(英文字符),统计文件中的字符数目和单词数目(假设
单词以空格、逗号、分号、句号分隔,文章中不含有其它分隔字符)。
【综合实验】:文件、统计管理
编写一个建立学生基本情况的直接存取文件,并能根据学生编号检索其基本情况的程序。
【,演示程序:】
学生基本情况存储在记录student内,他有编号、姓名、性别、年龄和五门课成绩五个域。采用直
接存取方式利用seek过程存贮记录数,由于学生编号从10001-29999,因此,记录数为编号数减
10000。为了确定检索已结束,最后的编号为65535。如果根据编号已检索到该生,这输出其基本情
况,如果检索不到,程序中自动将编号加1,重复检索,直到编号65535,仍未检索到则表示没有该
生的记录,可以继续检索其它学生的基本情况。
(1)算法:
a.定义一个记录文件
TYPE
student=RECORD
number:word;
name:lstring(10);{lstring,IBM Pascal提供的高级数组类型:L串。
name为可变字符串,其可变字符长度为10}
sex:lstring(6);
age:integer;
grades:array[1..5] of real
end;
VAR
i:integer;
total,avg:real;
n,m:word;
answer,c:char;
buf:student;
sfile:file of student;
t:boolean;
b.建立一个记录文件并输入记录
assign(sfile,'');
:=DIRECT;
rewrite(sfile);
answer:=' ';
while (answer<>'.') do
begin
write('Enter student number(10001-29999) ');
write('name,sex(f-m),age..');
with buf do
begin
readln(number);readln(name);
readln(sex);readln(age);
writeln('sc1,sc2,sc3,sc4,sc5 ');
for i:=1 to 5 do
readln(grades[i]);
seek(-10000)
end;
write(sfile,buf);
writeln('type''''.'''' to end');
readln(answer)
end;
seek(sfile,+1-10000);
:=65535;
write(sfile,buf);
close(sfile);
c.根据输入的学生编号检索学生的基本情况
:=direct;
reset(sfile);
t:=false;
write('Enter students number(10001-29999)..');
readln(n);m:=n;
writeln(' grades report');
write('number':6,'name':10);
write('age':4,'sex':4,' ');
write('total':5,'1':5,'7':5);
write('3':5,'4':5,'5':5 ');
writeln('avg':5);
while not t do
begin
seek(sfile,m-10000);
get(sfile);buf:=sfile^;
with buf do
begin
if number=65535 then
begin
writeln('not found this student ');
t:=true
end
else if number=n then
begin
t:=true;
total:=0;
for i:=1 to 5 do
total:=total+grades[i];
avg:=total/5;
write(number:6,name:10,age:4,' ');
write(sex:4,' ',total:5:1,' ');
for i:=1 to 5 do
write(' ',grades[i]:4:1);
writeln(' ',avg:4:1,' ')
end
else
begin
t:=true;
writeln('not found');
m:=m+1
end
end
end;