您现在的位置:小学生自学网>> 信息>> pascal语言>> 基础教程

pascal从循环到过程复习教材

作者: 来源: 发布时间:2009年05月12日 点击数:
 

直到循环(REPEAT-UNTIL)类型

直到循环语句的语法格式是:

repeat语句序列;
  (循环体)
 
until
布尔表达式;
 
其作用是:重复执行语句序列(循环体),直到布尔表达式的值为 TRUE为止。即,当执行完一次语句序列后,布尔表达式的值已经为 TRUE了,这时循环将不会再被执行,而转向执行 UNTIL语句以下的语句。

例:计算 M=1+2+3+4+……,直到 M的值大于 5050为止。 [例: 5 1]

var m,I:integer;
begin
    m:=0;
    I:=0;
    Repeat
        I:=I+1;
        M:=m+I;
    Until m>5050;
    Writeln(I,’   ’,m);
End.

在上述程序中,我们使用了 PASCAL中的两个作用强大的概念:累加和循环。
累加:我们在上述程序中没定了两个累加器: I M。累加器初值我们在第一句中设定了为 0,之后每次运行一次 I =I+1后, I的值就比原来大 1。每运行一次 M =M+I后, M的值就被 M+I所替代。

循环:这里我们使用的是直到循环,即重复执行循环体中的两个语句,直到 M>5050这个条件满足为止(即这个布尔表达式的值为 TRUE为止)。

上述程序运行后,会在输出屏幕上显示两个值: 101 5151。即当 I的值为 101时,这时所算得的 M的值为 5151。亦即, 1+2+3+…… 101=5151

象上述这种 X=1+2+3+…… 种加法,我们就把它叫累加,这里的 X就是累加器,一般初值为 0

N=1*2*3*4*5*6*……这种乘法我们把它叫累乘,这里 N就是累乘器,一般初值为 1(为什么?)。

一般的: 1*2*3*…… N,我们把这个式子的结果叫做 N的阶乘( N!)。如: 4 =1*2*3*4

 

 

 

例:计算 18! [ 5 2]

var I:integer;
   x:longint;
begin
   I:=0;
   X:=1;
   Repeat
      I:=I+1;
      X:=x*I;
   Until I=18;
   Writeln(x);
End.

        
当程序开始时, I的初值被定为 0 X的初值被定为 1(累乘器)。然而开始进入循环,每次 I的值比原来增加 1,然后再乘进 X中去,直到 I等于 20时,最后一次把 I乘进 X后,这时 I=20这个条件已经满足( I=20的值已经为 TRUE),所以循环就被退出,而程序转向执行 UBTIL以后的语句: WRITELN X);。

请大家想一想,为什么 X要定义为 LONGINT型。

练习

1、输入一个正整数N,把它分解成质因子相乘的形式。
   如:36=1 X 2 X 2 X 3 X 3
19=1 X 19
   (提示:设因子为I,从2开始到N,让N重复被I除,如果能整除,则用商取代NI为一个因子;如果不能整除,再将I增大,继续以上操作,直到I等于N。)

 

当(WHILE)语句 


当语句的语法格式是:
while 
布尔表达式 do begin
 语句序列;(循环体)
end; 
其作用是,当布尔表达式的值为 TRUE时,才会运行语句序列(循环体),否则循环将不会被执行,即从循环头部就退出,而转向执行 END后的语句。

例:计算 18! [ 5 3]

var I:integer;
   x:longint;
begin
   I:=0;
   X:=1;
   While I<18 do begin
      I:=I+1;
      X:=x*I;
   End;
   Writeln(x);
End.
请大家把此程序与上一节的 [ 5 2]进行比较,看两种循环在运用时有何不同。

WHILE
语句是在循环开始时就判断布尔表达式的值时否为 TRUE,如果为 TRUE,就进入循环,运行循环体,如果为 FALSE,就不运行循环体,而直接转向执行 END后的语句 WRITELN X);。

REPEAT
 WHILE循环的示意框图如下所示: 




从上述框图中可以看出,要使用循环语句时,必须要确定循环体及条件(布尔表达式)两个重要因素,亦即首要考虑的是:我要重复执行哪些语句,我要重复到什么时候为止!

[
 5 4],从键盘上输入两个整数 M N,求它们的最大公约数。

分析:我们只需从 M N中更小的一个数开始,每次让其减 1,直到这个数能同时被 M N数整除为止。在下述程序中,我们在程序头部调用了 CRT单元,是为了使用 CLRSCR语句来清屏,即把输出屏幕上的字符清除干净。

Uses crt;                              {
调用CRT单元}
Var m,n,x:integer;
Begin
   Clrscr;                             {
清屏}
   Write(‘Please input 2 numbers:’)
   Readln(m,n);
   If m>n then x:=n else x:=m;
   While (n mod x<>0) or (m mod x<>0) do begin
      x:=x-1;
   End;
   Writeln(x);
End.
 
上述程序如果改用 REPEAT语句来做的话,程序为:
uses crt;
var m,n,x:integer;
begin
   write(‘Please input 2 numbers:’)
   Readln(m,n);
   If m>n then x:=n+1 else x:=m+1;
   Repeat
      X:=x-1;
   Until (m mod x=0) and (n mod x=0);
   Writeln(x);
End.

请大家考虑上述两个程序为何会有这样有不同之处。



练习

  1计算下列式子的值:
   11+3+……+99
   21+2+4+8+……+128+256

  2、输入一个整数,计算它各位上数字的和。(注意:是任意位的整数)

  3、输入一整数A,判断它是否质数。(提示:若从2A的平方根的范围内,没有一个数能整除A,则A是质数。)

  4、求两个数的最小公倍数和最大公约数。(提示:公约数一定小于等于两数中的小数,且能整除两数中的大数。公倍数一定大于等于两数中的大数,且是大数的倍数,又能给两数中的小数整除。)

  5、编写一个译码程序,把一个英语句子译成数字代码。译码规则是以数字1代替字母A,数字2代替字母B……26代替字母Z,如遇空格则打印一个星号‘*’,英文句子以‘.‘结束。

  6、求水仙花数。所谓水仙花数,是指一个三位数abc,如果满足a^3+b^3+c^3=abc,则abc是水仙花数。 

   7百钱买百鸡是我国古代的著名数学题。题目这样描述:3文钱可以买1只公鸡,2文钱可以买一只母鸡,1文钱可以买3只小鸡。用100文钱买100只鸡,那么各有公鸡、母鸡、小鸡多少只?与之相似,有"鸡兔同笼"问题

 

FOR循环语句

    前面所计的两个语句都是在未知循环次数的情况下而用的循环语句,但在程序中,如果我们已经知道循环的次数而来编程序的话,就可以使用 FOR循环语句,这也是 PASCAL及其它高级语言中用得最多的语句。其语法格式有两种,如下:

(1) 增量为 1

for 变量名:=初值 to 终值 do begin
 语句序列(循环体);
end;

(2) 增量为 -1

for 变量名:=初值 downto 终值 do begin
 语句序列(循环体);
end;

变量名的类型由程序头部中定义,而其初值、终值必须和它是同一类型。该变量的类型是能是有序数据类型。

上述两种格式都是用变量的初值与终值来规定循环的次数。如以下两个小程序:

Var I:integer;
Begin
For I:=1 to 5 do begin
 Write(I);
End;
End.
运行结果:
12345

Var I:integer;
Begin
For I:=5 downto 1 do begin
 Write(I);
End;
End.
运行结果:
54321

由上可以看出 FOR循环的作用。

[ 5 5]:从键盘输入一个字符串,把它按正序及逆序分别输出:

uses crt;
var s:string;
l,I:integer;
begin
clrscr;
write(‘Please input the string:’);
readln(s);
l:=length(s);
for I:=1 to l do begin
 write(s[I]);
end;
writeln;
for I:=l downto 1 do begin
 write(s[I]);
end;
end.
[
5 6]计算

uses crt;
var s,a:integer;
begin
clrscr;
s:=0;
for a:=1 to 10 do begin
 s:=s+a*a;
end;
writeln(s);
end.
[
5 7]计算 1+3+5+7+…… 101的值:

uses crt;
var m,n:integer;
begin
clrscr;
m:=0;
for n:=0 to 50 do begin
 m:=m+(2*n+1);
end;
writeln(m);
end.
请大家注意上述程序中的几个小技巧,一个是 FOR N =0 TO 50,共循环 51次;一个是 M =M+ 2*N+1),其是的 2*N+1得到的是一序列的奇数。

 

 

 

多重循环语句

多重循环语句即循环嵌套,也就是一个循环语句的循环体中还有循环语句。

[ 5 8]编程序打印九九乘法表:

uses crt;
var I,j:integer;
begin
clrscr;
for I:=1 to 9 do begin
 for j:=1 to 9 do begin
  write(j:1,’*’,i:1,’=’,I*j:2);
 end;
 writeln;
end;
end.
运行结果:

1*1= 1

2*1= 2

3*1= 3

4*1= 4

5*1= 5

6*1=6

7*1= 7

8*1= 8

9*1= 9

1*2=2

2*2= 4

3*2= 6

4*2= 8

5*2=10

6*2=12

7*2=14

8*2=16

9*2=18

1*3=3

2*3= 6

3*3= 9

4*3=12

5*3=15

6*3=18

7*3=21

8*3=24

9*3=27

1*4=4

2*4= 8

3*4=12

4*4=16

5*4=20

6*4=24

7*4=28

8*4=32

9*4=36

1*5=5

2*5=10

3*5=15

4*5=20

5*5=25

6*5=30

7*5=35

8*5=40

9*5=45

1*6=6

2*6=12

3*6=18

4*6=24

5*6=30

6*6=36

7*6=42

8*6=48

9*6=54

1*7=7

2*7=14

3*7=21

4*7=28

5*7=35

6*7=42

7*7=49

8*7=56

9*7=63

1*8=8

2*8=16

3*8=24

4*8=32

5*8=40

6*8=48

7*8=56

8*8=64

9*8=72

1*9=9

2*9=18

3*9=27

4*9=36

5*9=45

6*9=54

7*9=63

8*9=72

9*9=81

注意:循环有嵌套时,必须分清层次,切不可把循环进行交叉。

[ 5 9]编程序分别打印以下三图:

(1)

Uses crt;
Var I,j:integer;
Begin
Clrscr;
For I:=1 to 5 do begin
For j:=1 to 5 do begin
Write(‘*’);
End;
Writeln;
End;
End.

(2)

Uses crt;
Var I,j:integer;
Begin
Clrscr;
For I:=1 to 5 do begin
Write(‘ ’:20+i);
For j:=1 to 5 do begin
Write(‘*’);
End;
Writeln;
End;
End.

(3)

Uses crt;
Var I,j:integer;
Begin
Clrscr;
For I:=1 to 5 do begin
Write(‘ ’:20-I);
For j:=1 to 5 do begin
Write(‘*’);
End;
Writeln;
End;
End.

请大家注意看清上述三个小程序,其功能是分别打印出上述三个由“ *”组成的小图形。三个图形的不同之处是:第一个直上直下,是个矩形;第二个是左斜的平行四边形;第三个是右斜的平行四边形。所以三个对应的程序也就有所不同,第( 2)、( 3)个程序比第( 1)个多了一句,即显示红色的那一句。这两句的作用是使每一行开头打印几个空格,即让图形左或右斜。 WRITELN的作用是打印完一行后换行。

[ 5 10]编程打印下列图形:

Uses crt;
Var I,j:integer;
Begin
Clrscr;
For I:=1 to 5 do begin
 Write(‘ ’:20-I);
 For j:=1 to 2*I-1 do begin
  Write(I:1);
 End;
 Writeln;
End;
End.





清屏

打印每一行前的 20-I个空格,这样每行都比上一行左移

每一行打印 2*I-1
打印该行行数

[ 5 11]打印 1 — 100间的所有素数:

素数,即为除了 1和它本身外没有另外的因数的整数。所以我们判断一个数 N是否素数,可以用 2 N-1所有数去除 N,如果没有一个数能被 N整除,则 N为素数。

当然,其实我们可以不用用 2 N-1这第多的数去除,而只需用 2至不大于 N的平方根的整数去除 N即可(为什么)?

这里我们的程序就用 2 TRUNC SQRT N))来判断,到后面我们还会谈到:如果要判断一个数是否素数,可只用小于 TRUNC SQRT N))的所有素数去除即可。

Var I,j:integer;
P:boolean;
Begin
For I:=2 to 100 do begin
 P:=true;
 For j:=2 to trunc(SQRTI) do   begin
   If I mod j=0 then p:=false;
  End;
 If p then write(I:5);
End;
End.





循环从 2 100
再判断 I是否素数前,先把判断器 P的值设为 TRUE

2 trunc(SQRT I )的数来除 I

如果 I能整除 J,则 P的值改为 FALSE

如果 P的值仍为 TRUE,则 I就是素数,打印出来

[ 5 12]以下是 A B C三人说的话:

A“ B在说谎 B“ C在说谎 C“ A B都在说谎。现在问,到底谁说真话,谁说谎?

分析: A B C三人,要么说谎,要么说真话,即三个的状态要么为 FALSE,要么为 TRUE,所以,可让 A B C三个变量进行循环,循环初值为 TRUE,终值为 FALSE。而三个人所说的话即为三个逻辑表达式,其值也为 TRUE FALSE,并且与 A B C的值是有关系的。 A B C三个所说的话转化为逻辑表达式即为:

A B=FLASE

B C=FALSE

C:( A=FALSE AND B=FALSE

以上三个逻辑表达式的值中, TRUE的个数应该与 A B C三个变量中 TRUE的个数相同。并且,每一个变量的值应该与其对应的话的逻辑表达式的值相等。如: A应该等于( B=FALSE)这个逻辑表达式。程序如下:

Var a,b,c:boolean;

Begin

  For a:=false to true do begin

    For b:=false to true do begin

       For c:=false to true do begin

         If (a=(b=false)) and (b=(c=false)) and (c=((a=false) and (b=false)))

         then Begin

           Writeln(a:10,b:10,c:10);

        End;

      End;

End;

  End;

      End.

练习

  1计算下列式子的值:
   11+2+……+100
   21+3+5+……+97+99

  2、输入一个四位数,求它各位上数字的和。

   3、求水仙花数。所谓水仙花数,是指一个三位数abc,如果满足a^3+b^3+c^3=abc,则abc是水仙花数。

  4、宰相的麦子:相传古印度宰相达依尔,是国际象棋的发明者。有一次,国王因为他的贡献要奖励他,问他想要什么。达依尔说:只要在国际象棋棋盘上(共64格)摆上这么些麦子就行了:第一格一粒,第二格两粒,……,后面一格的麦子总是前一格麦子数的两倍,摆满整个棋盘,我就感恩不尽了。国王一想,这还不容易,刚想答应,如果你这时在国王旁边站着,你会不会劝国王别答应,为什么?

循环结构练习

1 随机产生一些1—100之间的整数,直到产生的数为50为止。
2
计算1—1000之间能同时被35整除的整数的和。
3
打印下列图形:

4
一百匹马驮一百块瓦,一匹大马可以驮3块,一匹母马可驮2块,小马2匹可驮1块。试编程求需要各种马多少匹?
5
有三种纪念邮票,第一种每套一张售价2元,第二种每套一张售价4元,第三种每套9张售价2元。现用100元买了100邮票,问这三种邮票各买几张?
6
赵、钱、孙、李、周五人围着一张圆桌吃饭。饭后,周回忆说:吃饭时,赵坐在钱旁边,钱的左边是孙或李;李回忆说:钱坐在孙左边,我挨着孙坐。结果他们一句也没有说对。请问,他们在怎样坐的?
7
、找数。一个三位数,各位数字互不相同,十位数字比个位、百位数字之和还要大,且十位、百位数字之和不是质数。编程找出所有符合条件的三位数。
注:1. 不能手算后直接打印结果。
2. “
质数素数,是指除1和自身外,再没有其它因数的大于1的自然数。

8、选人。一个小组共五人,分别为ABCDE。现有一项任务,要他们中的3个人去完成。已知:(1AC不能都去;(2BC不能都不去;(3)如果C去了,DE就只能去一个,且必须去一个;(4BCD不能都去;(5)如果B去了,DE就不能都去。编程找出此项任务该由哪三人去完成的所有组合。

9、输入一个字符串,内有数字和非数字字符。如A123X456Y7A302ATB567BC,打印字符串中所有连续(指不含非数字字符)的数字所组成的整数,并统计共有多少个整数。

10ABC三人进入决赛,赛前A说:“BC得第二,我得第一B说:我进入前两名,丙得第三名C说:“A不是第二,B不是第一。比赛产生了一、二、三名,比赛结果显示:获得第一的选手全说对了,获得第二的选手说对了一句,获得第三的选手全说错了。编程求出ABC三名选手的名次。

11、甲、乙、丙、丁四人共有糖若干块,甲先拿出一些糖分给另外三人,使他们三人的糖数加倍;乙拿出一些糖分给另外三人,也使他们三人的糖数加倍;丙、丁也照此办理,此时甲、乙、丙、丁四人各有16块,编程求出四个人开始各有糖多少块。

12、截数问题: 任意一个自然数,我们可以将其平均截取成三个自然数。例如自然数135768,可以截取成13,57,68三个自然数。如果某自然数不能平均截取(位数不能被3整除),可将该自然数高位补零后截取。现编程从键盘上输入一个自然数N(N的位数<12)计算截取后第一个数加第三个数减第二个数的结果。

13、从键盘输入一段英文,将其中的英文单词分离出来:已知单词之间的分隔符包括空格、 问号、句号(小数点)和分号。
例如:输入:There are apples; oranges and peaches on the table.
输出:
there
are
apples
oranges
and
peaches
on
the
table

14、山乡希望小学收到一箱捐赠图书,邮件上署名是兴华中学高二班,山乡希望小学 长送来了感谢信,可是兴华中学高二年级有四个班,校长找来了四个班的班长,问他们是哪 个班做的这件好事。一班的班长说:是四班做的。二班的班长说:是三班做的好事。 班的班长说:不是我们班。四班的班长说:三班的班长说的不对。
四个班的班长都说不是自己班做的,这就难坏了校长,后来得知四个班的班长中有两个 说得是真话,有两个没有说真话,请你利用计算机的逻辑判断编一个程序,找出究竟是哪个 班做了这件好事。不能手算后直接打印结果。

15ABCDE五个人合伙夜间捕鱼,凌晨时都疲惫不堪,各自在河边的树丛中找地 方睡着了,日上三竿,E第一个醒来,他将鱼数了数,平分成五分,把多余的一条扔进河中, 拿走一份回家去了,D第二个醒来,他并不知道有人已经走了,照样将鱼平分成五分,又扔 掉多余的一条,拿走自己的一份,接着CBA依次醒来,也都按同样的办法分鱼(平分成 五份,扔掉多余的一条,拿走自己的一份),问五人至少合伙捕到多少条鱼。
也许你能用数学办法推出鱼的条数,但我们的要求你编出一个程序,让计算机帮你算出鱼的总数。

16、试编程找出能被各位数字之和整除的一切两位数。

17、一个正整数的个位数字是6,如果把个位数字移到首位,所得到的数是原数的4倍,试编程找出满足条件的最小正整数。

18、某本书的页码从1开始,小明算了算,总共出现了202个数1,试编程求这本书一共有多少页?

19、从键盘上输入两个不超过32767的整数,试编程序用竖式加法形式显示计算结果。
例如: 输入 123, 85
显示:  
123
  +  
85
  
-------------
   
208
 

20
、有30个男人女人和小孩同在一家饭馆进餐,共花了五十先令,其中男宾3先令,女宾2先令,小孩1先令。试编程求出男人女人小孩各多少人?

 

 

 

 

一维数组
〖语法分析〗

  在编程时用到一批类型相同的数据,为了处理上的方便,通常以数组的形式来定义这一批数据。

  1、数组的定义格式:
var
   a:array [1..10] of integer;
   其中:a是这一批数据的名称,称为数组名;arrayof是定义数组的保留字;中括号中的数字是数据编号的下限和上限,同时也说明了数据的个数(上限-下限);最后一个是数据的基类型,如integercharrealboolean

   2、数组元素的输入:
数组名代表的并不是一个变量,而是一批变量,因而,不能直接整个数组读入,而是要逐个数组元素读入,通常用循环结构来完成这一功能。下面是几个常用输入数组元素的例子:
for i:=1 to 10 do read(a[i]);
   {————从键盘读入数组元素的值;最常用的方法}
for i:=1 to 10 do a[i]:=i;
   {————数组元素a[1]a[10]的值分别为110;数据赋初值
}
for i:=1 to 10 do a[i]:=0;
   {————数组元素清0;最常用的数据初始化的方法
}
for i:=1 to 10 do a[i]:=random(100);
   {————随机产生10100以内的数,赋给各数组元素}

   3、数组元素的输出:
   和数组元素的输入相同,数组元素的输出也不能由一个write语句直接完成。同样要逐个数组元素输出。通常也用循环结构来完成这一功能:
for i:=1 to 10 do write(a[i],' ');{————
数组元素之间用空格分隔}
writeln;

   4、数组的应用:
   1:从键盘输入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.


  例2:从键盘输入10个数,将这10个数从大到小的顺序输出。

program p2;
Var n:array[1..10] of integer;
I,j,t:integer;
Begin
  For I:=1 to 10 do Readln(n[I]);
  For I:=1 to 9 do begin
 
For j:=I+1 to 10 do begin
 
 
If n[I]<n[j] then begin
   
 
T:=n[I];
   
 
N[I]:=n[j];
   
 
N[j]:=t;
 
 
End;
 
End;
  End;
  For I:=1 to 10 do begin
 
Write(n[I]:5);
  End;
End.

  例3:用筛法求100以内的素数(质数)。

     分析:素数是除了1和它本身以外没有其它约数的数。用筛法求素数的方法是:用质数筛去合数:从第一个素数2开始,
      
把它的倍数去掉;这样2以后的第一个非0数就一定也是素数,把它的倍数也删了……重复这个删数过程,直到在所找到
      
的素数后再也找不到一个非0数。把所有非0数输出。

program p3;
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. 
       
练习题:

 1、随机产生20100以内的数,输出;按从小到大的顺序排序,输出。
 2、有一组数,其排列形式如下:1119912520118416610152173147138
且尾部8和头部11首尾相连,构成环形的一组数,编程找出相邻的4个数,其相加之和最大,并给出它们的起始位置。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

二维数组
〖语法分析〗

  一维数组在编程中多用于描述线性的关系:如一组数;一组成绩;一组解答等。数组元素只有一个下标,表明该元素在数组中的位置。二维数组在编程中多数用于描述二维的关系:如地图、棋盘、城市街道、迷宫等等。而二维数组元素有两个下标:第一个下标表示该元素在第几行,第二个下标表示在第几列。二维数组的定义格式如下:
var
   aarray[1..10,1..5] of integer
   其中:a是数组名,由程序员自定;arrayof是定义数组的保留字;(这两点和一维数组定义的格式一样)中括号中的两个范围表示二维数组共有多少行、多少列(第一个范围表示行数,第二个范围表示列数);最后一个表示数组元素的类型,规定和一维数组一样。如上例,定义了一个二维数组a,共有105列。

   使用二维数组要注意:
   1、数组元素的指称:数组名[行号,列号]。如第三行第四个元素:a[3,4]
   对某一行进行处理。如累加第4行的数据。则固定行号为4。如:for i:=1 to 5 do s:=s+a[4,i];
   对某一列进行处理。如累加第4列的数据。则固定列号为4。如:for i:=1 to 10 do s:=s+a[i,4];

   2、二维数组的输入输出要用双重循环来控制:
for i:=1 to 10 do{————
控制行数}
begin
   for j:=1 to 5 do read(a[i,j]){————第一行读入5个元素
}
   readln;{————读入一个换行符
}
end;
{————
最常用的方法:从键盘读入数据初始化二维数组
}
for i:=1 to 10 do
  
for j:=1 to 5 do a[i,j]:=0;
{————
最常用的方法:将二维数组清
0}
for i:=1 to 10 do
begin
  
for j:=1 to 5 do write(a[i,j]:4);
  
writeln;
end;
{————
最常用的输出方法:按矩阵形式输出二维数组的值}

   3、二维数组的应用:
1:竞赛小组共有20位同学,这学期每位同学共参与了三项比赛,请统计每位同学的平均分。
分析:定义一个203列的二维数组来存放这些成绩。定义一个20个元素的一维数组来存放平均分。
program p1;
var
   a:array [1..20,1..3] of integer;
  
b:array [1..20] of real;
  
i,j:integer;
begin
  
for i:=1 to 20 do
  
begin
     
for j:=1 to 3 do read(a[i,j]);
    
readln;
  
end;
{————
从键盘上读入20个同学的三次竞赛成绩
}
  
for i:=1 to 20 do b[i]:=0;
{————
先将平均分数组清
0}
  
for i:=1 to 20 do
  
begin
     for j:=1 to 3 do b[i]:=b[i]+a[i,j];{————计算总分
}
     b[i]:=b[i]/3;{————计算平均分
}
  
end;
  
for i:=1 to 20 do write(b[i]:5:1);
{————
输出平均分
}
writeln;
end.

2:设有一程序:
  
program ex5_3;
  
const n=3;
  
type matrix=array[1..n,1..n]of integer;
  
var a:matrix;
   
i,j:1..n;
  
begin
   
for i:=1 to n do
   
begin
    
for j:=1 to n do
     
read(a[i,j]);
    
readln;
   
end;
  
for i:=1 to n do
  
begin
   
for j:=1 to n do
    
write(a[j,i]:5);
   
writeln;
  
end;
  
end.
   且运行程序时的输入为
:
  
2□1□3←┘
  
3□3□1←┘
  
1□2□1←┘
   则程序的输出应是
:
  
2□3□1
  
1□3□2
   3□1□1

3:输入一串字符,字符个数不超过100,且以"."结束。 判断它们是否构成回文。
   分析:所谓回文指从左到右和从右到左读一串字符的值是一样的,如12321,ABCBA,AA等。先读入要判断的一串字符(放入数组letter中),并记住这串字符的长度,然后首尾字符比较,并不断向中间靠拢,就可以判断出是否为回文。
   源程序如下:
   program ex5_5;
   var  

     letter  : array[1..100]of char;
     i,j   : 
0..100;
     ch   : 
char;
  
begin
    {读入一个字符串以'.'号结束
}
   
write('Input a string:');
   
i:=0;read(ch);
   
while ch<>'.' do
   
begin
    
i:=i+1;letter[i]:=ch;
    
read(ch)
   
end;
    {判断它是否是回文
}
   
j:=1;
   
while (j<i)and(letter[j]=letter[i])do
   
begin
    
i:=i-1;j:=j+1;
   
end;
    if j>=i 
then writeln('Yes.')
   
else writeln('No.');
   end.

4:奇数阶魔阵
   魔阵是用自然数123…n2n阶方阵的各个元素位置,使方阵的每行的元素之和、每列元素之和及主对角线元素之和均相等。奇数阶魔阵的一个算法是将自然数数列从方阵的中间一行最后一个位置排起,每次总是向右下角排(即Aij的下一个是Ai+1,j+1)。但若遇以下四种情形,则应修正排数法。
   1 列排完(即j=n+1时),则转排第一列;
   2 行排完(即i=n+1时),则转排第一行
;
   3 An,n的下一个总是
An,n-1;
   4 Aij已排进一个自然数,则排Ai1j2

   例如3阶方阵,则按上述算法可排成:
           4 3 8
          
9 5 1
           2 7 6

  有了以上的算法,解题主要思路可用伪代码描述如下:
   1 in div 2+1,yn /*排数的初始位置*/
   2 
a[i,j]1;
   3 
for k:=2 to n*n do
   4 计算下一个排数位置(i,j);

   5 if a[i,j]<>0 then
   6 
ii-1;
   7 
jj-2;
   8 
a[i,j]k;
   9 endfor

   对于计算下一个排数位置,按上述的四种情形进行,但我们应先处理第三处情况。算法描述如下:
   1 if (i=n)and(j=n) then
   2 jj-1; /*下一个位置为
(n,n-1)*/;
   3 
else
   4 
ii mod n +1;
   5 
jj mod n +1;
   6 endif;

   源程序如下:
   program ex5_7;
  
var
   
a : array[1..99,1..99]of integer;
   
i,j,k,n : integer;
  
begin
   
fillchar(a,sizeof(a),0);
   
write('n=');readln(n);
   
i:=n div 2+1;j:=n;
   
a[i,j]:=1;
   
for k:=2 to n*n do
    
begin
     
if (i=n)and(j=n) then
      
j:=j-1
     
else
      
begin
       
i:=i mod n +1;
       
j:=j mod n +1;
      
end;
     
if a[i,j]<>0 then
      
begin
       
i:=i-1;
       
j:=j-2;
      
end;
     
a[i,j]:=k;
    
end;
   
for i:=1 to n do
    
begin
     
for j:=1 to n do
      
write(a[i,j]:5);
     
writeln;
    
end;
   end.


练习题:
1
输入N个同学的语、数、英三科成绩,计算他们的总分与平均分,并统计出每个同学的名次,最后以表格的形式输出。
2
、输入10个学生的姓名,编一程序将它们按字母的顺序排列。
3
输出杨辉三角的前N(N<10)

       1
       1 
1
       1 2 
1
       1 3 3 
1
       1 4 6 4 1

4、求一个5 X 5数阵中的马鞍数,输出它的位置。所谓马鞍数,是指在行上最小而在列上最大的数。如下:
5 6 7 8 9
4 5 6 7 8
3 4 5 2 1
2 3 4 9 0
1 2 5 4 8
11列上的数就是马鞍数。

5、验证数学黑洞:所有四位数,除了数字全相同的外,其它的,经过不多于七次的下列操作,一定可以得到6174;并且,一旦得到6174之后,就掉进黑洞,再也得不到其它的数(61747641-1467 = 6174):
将这个四位数的数字按从大到小和从小到大重组成两个数,大数减去小数。
例:输入3214
1
4321 - 1234 = 3087
2
8730 - 378 = 8352
38532 - 2358 = 6174

6、猴子选大王:有M个猴子围成一圈,每个有一个编号,编号从1M。打算从中选出一个大王。经过协商,决定选大王的规则如下:从第一个开始,每隔N个,数到的猴子出圈,最后剩下来的就是大王。
要求:从键盘输入MN,编程计算哪一个编号的猴子成为大王。

7、有M个人围成一圈,每人有一个编号,从编号为1的人开始,每隔N个出圈,按出圈次序排成一列,其编号刚好按顺序从1M。要求:从键盘输入MN,编程计算并输出这M个人原来在圈中的位置。

8、前N个自然数排成一串: X1,X2,X3.....Xn,先取出x1,x2,x3移到数串尾,再取出x4,x4,x6移到数串尾,....... 类推直至取完.取出的序列恰好是:1,2,3......n,要求输入N,求原来的数串的排列方式.

9、猴子捉兔子:围绕着山顶有10个洞,狐狸要吃兔子,兔子说:可以,但必须找到我,???? ???我就藏身于这十个洞中,你从10号洞出发,先到1号洞找,第二次隔1个洞找,第三次隔2个洞找,以后如此类推,次数不限。但狐狸从早到晚进进出出了1000次,仍没有找到兔子。问兔子究竟藏在哪个洞里?

 

 

字符与字符串处理

一、字符与字符串类型的使用

Var 字符变量名:char

字符类型是一个有序类型,字符的大小顺序按ASCII码的大小决定。相关的函数有succpredordchr等。

VAR A:CHAR;

BEGIN

READLN(A);

WRITELN('A:',A);

WRITELN('SUCC(A):',SUCC(A));

WRITELN('PRED(A):',PRED(A));

WRITELN('ORD(A):',ORD(A));

WRITELN('CHR(ORD(A)):',CHR(ORD(A)));

END.

例:按字母表顺序和逆序每隔一个字母打印。即打印出:

a c e g i k m o q s u w y

z x r v t p n l j h f d b

for i:=1 to 13 do write(chr(63+2*i):4);writeln;

for i:=1 to 13 do write(chr(92-2*i):4);writeln

字符串

〖语法分析〗

字符串用于存放整批的字符数据。通常编程中使用字符串存放字符化了的数字数据。如高精度运算时存放操作数和运算结果。字符串可以看作是特殊的字符串数组来处理。当然,它也有自已的特点。下面是字符串定义的格式:
var s:string; s1:string[15];
 s[1] s[2] … s[255]  s[0]  ord(s[0])
字符串定义时,如不指定长度,则按该类型的最大长度(255个字符)分配空间,使用时最大可用长度为255个;如果在中括号中给出一个具体的值(1—255之间),则按这个值的大小分配空间。使用时,最大的可用长度即为该值。

1、字符串的输入、输出:
字符串类型既可按数组方式输入、输出,也可直接输入、输出:readln(s)writeln(s);多个字符串输入时以回车作为数据间的分隔符;每个readln语句只能读入一个字符串。

2、有关字符串的操作:

操作

类型

作用

返回值

例子

length(s)

函数

求字符串 s的长度

整型

s:='123456789';
l:=length(s);{l
的值为 9}
字符串的长度存放在 s[0]中, ord(s[0])的值与 length(s)的值相同。

copy s,w,k)

函数

复制 s中从 w开始的 k

字符串

s:='123456789';
s1:=copy(s,3,5);{s1
的值是 '34567'}

val(s,k,code)

过程

将字符串 s转为数值,存在 k中; code是错误代码

 

var s:string;k,code:integer;
begin
s:='1234';
val(s,k,code);
write(k);{k=1234}

str(i,s)

过程

将数值 i转为字符串 s

 

i:=1234;
str(i,s);
write(s);{s='1234'}

Delete(s,w,k)

过程

s中删除从第 w位开始的 k个字符

 

s := 'Honest Abe Lincoln';
Delete(s,8,4);
Writeln(s); { 'Honest Lincoln' }

Insert(s1, S, w)

过程

s1插到 s中第 w

 

S := 'Honest Lincoln';
Insert('Abe ', S, 8); { 'Honest Abe Lincoln' }

Pos(c, S)

函数

求字符 c s中的位置

整型

S := ' 123.5';
i :=Pos(' ', S);{i
的值为 1}

+

运算符

将两个字符串连接起来

 

s1:='1234';
s2:='5678';
s:=s1+s2;{'12345678'}

[63]26英语字母正向、逆向打印出来。

Const s:string[26]=’abcdefghijklmnopqrstuvwxyz’;

Var t:string[26];

I:integer;

Begin

  t:=’                          ‘;           {26个空格}

  For I:=1 to 26 do begin

     T[I]:=s[27-I];

  End;

  Writeln(s);

  Writeln(t);

End.

[64]找出所有的四位回文数:(回文数就是一个数从左往右读与从右往左读都是同一个数)

var s:string[4];

n:integer;

begin

  for n:=1000 to 9999 do begin

      str(n,s);

      if (s[1]=s[4]) and (s[2]=s[3]) then write(n:6);

  end;

end.

或者用如下程序:

var n:integer;

s,t:string;

begin

  for n:=10 to 99 do begin

      str(n,s);

      t:=s+s[2]+s[1];

write(s:6);

  end;

end.

上述两个程序,哪个快,哪个慢?

       

练习题:

1、读入一串字符,以句号结束,然后让其倒序输出。
  如输入:I am a student.
  输出:tneduts a ma I

2、读入一串数字,以句号结束,请统计其中‘0到‘9的各个数字的个数。
  如输入:91254782354987012345978. 
  输出:0:1 1:2 2:3 3:2 4:3 5:3 7:3 8:3 9:3
3、输入一段文章(255个字符以内),求文章中单词的个数(相同单词只记一次,Thethe认为是同一个单词,只记一次)。
4
、请编写一个程序,让它能够计算两个200位以内的整数的和。
5
、做一个加法器。完成30000以内的加法,两个加数间用“+”连接,可以连加,回车表示式子输入完成;“#”表示结束运算,退出加法器。

看程序写结果
1.
var ch:string;
   i:byte;
begin
  readln(ch);
  for i:=1 to ord(ch[0]) do
   write(ch[i]:2);
  writeln
end.
输入:My name is Tom.
输出:

2.
var i:integer;
begin
  for i:=1 to 13 do write(chr(63+2*i):4);
  writeln;
  for i:=1 to 13 do write(chr(92-2*i):4);
  writeln
end.
输出:

3.
var a:char;
begin
  readln(a);
  writeln('a:',a);
  writeln('succ(a):',succ(a));
  writeln('pred(a):',pred(a));
  writeln('ord(a):',ord(a));
  writeln('chr(ord(a)):',chr(ord(a)));
  writeln('chr(ord(a)+2):',chr(ord(a)+2));
end.
输入:e
输出:

4.
var s:integer;
ch:char;
   count:array['a'..'z'] of integer;
begin
  for ch:='a' to 'z' do count[ch]:=0;
   read(ch);
  while ch<>'!' do
  begin
   if (ch>='a')and(ch<='z') then
    count[ch]:=count[ch]+1;
   read(ch)
  end;
  s:=0;
  for ch:='b' to 'z' do s:=s+count[ch];
  writeln(s)
end.
输入:We are proud OF OUR COUNTRY! 
输出:
 
5.
var a:array[1..100] of string[20];
   s:string;temp:string[20];
   i,j,k,n:integer;
begin
  readln(n);readln(s);i:=1;j:=0;k:=0;
  while i<=length(s) do
   if s[i] in ['0'..'9'] then
   begin
    j:=1;
    while s[i] in ['0'..'9'] do
    begin
     temp[j]:=s[i];
     inc(j);inc(i)inc(i)相当于i:=i+1}
    end;
    temp[0]:=chr(j-1);
    k:=k+1;
    a[k]:=temp
   end
  else
  while s[i]=' ' do inc(i);
  for i:=1 to n-1 do
   for j:=i+1 to n do
    if (a[i]+a[j])<(a[j]+a[i]) then
     begin
      temp:=a[i];a[i]:=a[j];
      a[j]:=temp
    end;
  for i:=1 to n do write(a[i]);
  writeln
end.
输入:4
81
 792 39 79
输出:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

函数

PASCAL给我们提供了一些标准函数,我们不用了解这些函数如何求出来的,只管直接调用它们,挺方便的。如正弦函数,余弦函数,算术平方根......有了这些函数,我们觉得很省事。如:求SIN1)+SIN2)+...+SIN100)=?这个程序我们可以这样编写:

1

    PROGRAM  e1(input,output);

     VAR i:integer;

       s:real;

     BEGIN

       s:=0;

       for i:=1 to 100 do

        s:=s+sin(i);

       writeln('s=',s);

     END.

在这个程序里,我们直接用到了正弦函数,至于SIN1),SIN2)如何求出来的我们不需过问,只管直接用它的结果便是了。

我们来看看下面一个例子:求:1!+2!+3!+...+10!=?

如果要编写程序,我们看到求阶乘的操作要执行10次,只不过每次所求的数不同。我们想:不至于编写10遍求阶乘的程序吧。我们希望有一个求阶乘的函数,假设为JSX),那么我们就可以这样求这道题了:

2

 PROGRAM e1(input,output);

     VAR i:integer;

       s:real;

     BEGIN

       s:=0;

       for i:=1 to 10 do

        s:=s+js(i);

       writeln('s=',s);

     END.

现在的问题是:TURBO PASCAL没提供JSX)这样一个标准函数,这个程序是通不过的。如果是PASCAL的标准函数,我们可以直接调用,如TRUNCX),LNX),SQRTX)......而PASCAL提供给我们的可供直接调用的标准函数不多。没关系,我们编写自己的函数!

·         函数的编写

自己编写一个函数,它的格式如下:

FUNCTION 函数名(形式参数表):函数类型;

VAR 函数的变量说明;

BEGIN

函数体

END

我们来分析一下,一个函数的编写可分成三部份:一是函数首部,即第一个语句。它必须以FUNCTION开头,函数名是自己取的,取名的原则是便于记忆,和文件名的取名规则类似。形式参数(简称形参)表以标识符的形式给出,相当于函数中的自变量。参数可以有多个,也可以有多种类型。不同类型的参数之间用隔开,同类型的参数如有多个,则用隔开,在其后得加上说明。如:

FUNCTION A1ABCINTEGERDEFREAL):REAL

在最后,函数属于哪种类型,还得表示出来。在本例中,该函数为实型。

第二部分是函数的变量说明部分,对在本函数中将要用到的变量作类型说明,这一点和以前学的变量一样。如果程序不用变量,则此部分也可省掉。

第三部分是函数体,本函数的功能实现就在于此,编写的语句就在里面。

3 编写一求阶乘的函数。

我们给此函数取一名字就叫JS

 fUNCTION js(n:integer):longint;

       var i:integer;

        s:longint;

       begin

        s:=1;

        for i:=1 to n do                        

         s:=s*i;

 js:=s;

end;

在本例中,函数名叫JS,只有一个INTEGER型的自变量N,函数JSLONGINT型。在本函数中,要用到两个变量IS,在VAR后已加以说明。在函数体中,是一个求阶乘的语句,但有一点要注意:虽然N的阶乘的值在S中,但最后必须将此值赋给函数JS,此时JS不带任何参数。在任何函数中,最后都要把最终结果赋给函数名,因为该函数的结果是靠函数名返回的。

在这里,函数的参数N是一个接口参数,说得更明确点是入口参数。如果我们调用函数:JS3),那么在程序里所有有N的地方N被替代成3计算。在这里,3就被称为值参。又如:SQRT4),LN5),这里的45叫值参。而SQRTX),LNY)中的XY叫形参。

·         函数的调用

自定义的函数在调用前要先说明,在主程序中的位置如下:

PROGRAM 程序名(INPUTOUTPUT);

VAR 主程序变量说明;

FOUNCTION 函数名(形参表):函数类型;

VAR 函数变量说明;

BEGIN

函数体

END{FUNCTION}

BEGIN

主程序

END .{PROGRM}

在主程序中,我们把函数的全部说明放在主程序的变量说明和程序体之间,然后在主程序的执行部分就可以直接调用自定义函数了。注意:在函数的说明部分,我们要用形参,但在程序的执行部分调用自定义函数时,就得用值参了。

4 利用前面定义的阶乘函数,求5!,9!。

PROGRAM e59(input,outout);

      VAR a1,a2:longint;

     fUNCTION js(n:integer):longint;

      var i:integer;

        s:longint;

      begin

       s:=1;

       for i:=1 to n do

        s:=s*i;

       js:=s;

      end;

     BEGIN

       a1:=js(5);

       a2:=js(9);

       writeln('5!=',a1,' ','9!=',a2);

     END.

在这个程序中,在主程序的BEGIN之前,我们对函数进行了一次说明,在后面的程序中都可以象标准函数那样直接调用自定义函数了。在FUNCTION语句中,用的是形参N,在主程序调用中,调用函数是用的值参,如:JS5);程序执行到这儿会自动将5代入前面的FUNCTION函数中,用5 取代所有的N,最终将结果赋值给JS。所以在A1中一定是5!,A2中是9!。另外,函数不能单独使用,一定要结合主程序才能运行。

如果是求1!+2!+3!+...+10!,则只需把主程序改成:

A1:=0

FOR J:=1 TO 10 DO

A1:=A1JSJ);

WRITELNA1);

在例4中,主程序的变量A1A2叫全程变量,它们除了主程序外,还可以在函数中出现;在函数说明中用到的变量IS则是局部变量,只能在函数部分使用,一旦出了函数则失去意义;别外要注意:全程变量和局部变量尽量不要同名。

5 任意输入10组三角形的三边,求其面积。

已知三角形的三边,是可以求出面积的。我们可以定义一个已知三角形三边求其面积的函数,设为AREAa1,a2,a3)。

    PROGRAM e5(inmput,output);

      VAR a,b,c,s:real;

        i:integer;

      FUNCTION  area(a1,a2,a3:real):real;

       var s1,d:real;

       begin

       d:=(a1+a2+a3)/2;

       s1:=Sqrt(d*(d-a1)*(d-a2)*(d-a3));

       area:=s1;

       end;

 

       BEGIN

       for i:=1 to 10 do

        begin

         writeln('input a,b,c');

         readln(a,b,c);

         if  (a+b<=c) or (a+c<=b) or(b+c<=a)

          then writeln('data error!')

           else writeln('s=',area(a,b,c));

        end;

      END.

在函数说明中,如果形参的个数不止一个,那么在程序中调用函数的实参个数一定要与形参的个数一致,第一个实参对应第一个形参,第二个实参对应第二个形参......次序不能调。

6 定义一个函数CHECKND),让它返回一个布尔值。如果数字D在整数N的某位中出现则送回TRUE,否则送回FALSE

例如:CHECK3257193)=TRUE

CHECK778291)=FALSE

          PROGRAM e6(input,output);

           VAR a,b:integer;

 

            FUNCTION check(n,d:integer):boolean;

            var f:boolean;

             e:integer;

            begin

             f:=false;

             while (n>0) and (not f) do

               begin

                e:=n mod 10;

                n:=n div 10;

                if e=d then f:=true;

             end;

             check:=f;

            end;

 

           BEGIN

           writeln('input n,d');

           read(a,b);

           writeln(check(a,b));

         END.

练习编写一个函数,返回布尔值判别输入三个字符是按序或无序排列。程序中若输入abc则显示顺序排列,若输入cba则显示逆序排列,其他情况显示无序排列,当输入***程序结束。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

过程
过程和函数一样,也是子程序。一个过程对应一个需要完成的任务。PASCAL中提供了不少标准过程,如:READWRITEGETNEWPUT......这些标准过程在程序中可以直接调用。但仅仅这些标准过程还不能满足我们的需要,我们还要自己定义过程,就象函数一样。但函数必须以值的形式返回,而过程不一定返回一个值,只是执行一个任务而已;函数只能返回一个值,而过程可以返回不止一个值。所以函数不能取代过程。

 

22  过程的定义

    过程定义的格式如下:

    PROCEDURE  过程名(形式参数);

      VAR  过程的变量说明;

       BEGIN

        过程体

       END;

     对该格式说明如下:

   一个过程也分为三部分,1:过程的首部。过程必须以PROCEDURE开头,过程名的取名规则和函数名一样,括号里面是形式参数,如形参不止一种,则中间用隔开,同类形参如不止一个,则中间用隔开。另:有时侯过程不用加参数。2:过程的说明部分,用VAR开头,它只能对过程中的变量进行说明,同样是局部变量。另:如果过程不用变量,则可将说明部分省略。3:过程体。它是过程的执行部分。

      我们来定义一个打印由组成的矩阵的过程,该矩阵四行五列。

      7

              PROCEDURE print;

                 var i,j:integer;

                 begin

                  for i:=1 to 4 do

                    begin

                     for j:=1 to 5 do

                       write('*');

                       writeln;

                     end;

                  end;

    该过程就没有参数,直接执行打印一个固定矩阵的任务,而且也没返回值。

7            定义一个求N!的过程。

            PROCEDURE  js(n:integer);

             var s:longint;

                 i:integer;

              begin

                s:=1;

                for i:=1 to n do

                 s:=s*i;

                writeln(n,'!=',s);

              end.

 

   在该过程中,它的值的返回形式和函数不一样:函数是由函数名返回,而过程不是由函数名返回的;在过程的首部不用对过程的类型进行说明。

      

    23  过程的调用

        自定义过程在程序调用之前要先说明,过程的说明就在主程序的执行语句之前。其格式如下:

        PROGRAM  程序名(INPUTOUTPUT);

          VAR  主程序的变量说明;

          

            PROCEDURE  过程名(形式参数表功;

                VAR  过程的变量说明;

                 BEGIN

                  过程体

                  END;

 

             BEGIN

                主程序体

             END.

 

8    任意输入10三角形的三边,用过程把其面积求出。

我们把求一个已知三边的三角形的面积定义一个过程,对比一下和例5有什么不同。

                  PROGRAM e5(inmput,output);

                     VAR a,b,c,s:real;

                         i:integer;

 

                      PROCEDURE  area(a1,a2,a3:real);

                          var s1,d:real;

                          begin

                           d:=(a1+a2+a3)/2;

                           s1:=Sqrt(d*(d-a1)*(d-a2)*(d-a3));

                           writeln('s=',s1);

                           end;

 

                       BEGIN

                         for i:=1 to 10 do

                         begin

                         writeln('input a,b,c');

                         readln(a,b,c);

                         if  (a+b<=c) and (a+c<=b) and (b+c<=a)

                                then writeln('data error!')

                                else area(a,b,c);

                         end;

                       END.

 我们看到:过程的调用和函数不同。函数不能作为独立的一个语句使用,而过程可以。函数的值是由函数名返回的,而过程不能。

  现在我们提出一个要求:用过程求出1!+2!+3!+...+10!=?
  求N!的问题我们在例7已写出来,但阶乘的结果是在过程里用WRITE语句输出的,不能用累加语句把结果求出来。那么,怎样用过程将类似的问题求出来?这就得用到变量参数。

 

24  变量参数
   在过程定义的语句中,有个参数表,在参数表中,除了前面我们已用的值参,还有变量参数。变量参数的作用是:它可以作为过程的出口参数。我们可以把过程中求出的结果用变量参数输出到过程外,在过程外面可以调用该参数,因此,该参数是全局变量。其格式上的区别是在变量参数前加上VAR即可。

那么我们现在来求1!+2!+3!+...+10!=?

9

            PROGRAM  e9(input,output);

              VAR j:integer;

                  s,m:longint;

               PROCEDURE js(n:integer;var m:longint);

                var i:integer;

                begin

                  m:=1;

                  for i:=1 to n do

                    m:=m*i;

                end;

               BEGIN

                s:=0;

                for j:=1 to 10 do

                  begin

                    js(j,m);

                    s:=s+m;

                  end;

                writeln('s=',s);

             END.

  在本例中。我们看到,过程JS中用到了变量参数M,在过程中定义为LONGINT类型;而在主程序的变量说明中也得对变量参数M说明为同种类型LONGINGT。于是,在过程中和主程序中都可以用该变量了。我们在调用这类过程时,在括号中要写上所有的参数,但用不着写上参数的类型和VAR了。

练习
1
、某部队举行一次军事演习,AB两队约好在同一时间从相距100公里的各自驻地出发相向运动。A队的速度为10公里/小时,B队的速度为8公里/小时。一通讯员骑马从A地同时出发为行进中的两队传递消息,速度为60公里/小时。每遇一队立即折回驶向另一队,当两队距离小于0.5公里时,停下来不再传递消息。求此时通讯员跑了多少趟(从一队到另一队为一趟)

2、已知二个合数A=18B=96,键入N[10,400]之间的自然数,求这N个数中所有合数与AB的最大公约数。

子程序中的参数

形参和实参
  子程序调用(过程调用或函数调用)的执行顺序分为以下几步:

   实参和形参结合——〉执行子程序——〉返回调用处继续执行

   子程序说明的形式参数表对子程序体直接引用的变量进行说明,详细指明这些参数的类别、数据类型要求和参数的个数。子程序被调用时必须为它的每个形参提供一个实参,按参数的位置顺序一一对应,每个实参必须满足对应形参的要求

   Turbo Pascal子程序形参有四类:

   1.值参数

   形式参数表中前面没有var,后有类型的参数。它类似过程和函数的局部变量,仅为过程和函数的执行提供初值而不影响调用时实际参数的值。在调用过程或应用函数时,值参数所对应的实际参数必须是表达式,而且它的值不能使文件类型或包括文件类型的值。实参必须和形参赋值相容。

   2.变量参数

   形式参数表中前面有var后由类型的参数。如果需要子程序向调用程序返回值时,应采用变量参数。变量参数要求它的实参是和它同一类型的变量。因为在子程序执行时,遇到对相应形参的引用式定值,就是对相应实参的引用式定值,即对形参的任何操作就是对实参本身的操作。

   3.无类型变量参数

   形式参数表中前面有var而后面没有类型的参数。形参是无类型变量,对应的实参允许为任意类型的变量,但要在子程序中设置的强制类型转换(类型名(无类型变量参数名)),将无类型变量参数改变为相应类型。

   4.子程序参数

   用过程首部或函数首部作为形式参数。

标识符的作用域
   1.全局变量和它的作用域

    全局变量是指在程序开头的说明部分定义和说明的量。它的作用域分为两种情况:

    (1)在全局变量和局部变量不同名时,其作用域是整个程序。

    (2)在全局变量和局部变量同名时,全局变量的作用域不包含同名局部变量的作用域。

   2.局部变量和它的作用域

     凡是在子程序内部使用的变量,必须在子程序中加入说明。这种在子程序内部说明的变量称为局部变量。局部变量的作用域是其所在的子程序。形式参数也只能在子程序中有效。因此也属于局部变量。局部变量的作用域分为两种情况:

     (1)当外层过程序的局部变量名和嵌套过程中的局部变量不同名时,外层过程的局部变量作用域包含嵌套过琛。

     (2)当外层过程的局部变量名和嵌套过程内的局部变量名同名时,外层局部变量名的作用域不包含此过程。