信息学竞赛辅导教科书(电子版)_第1页
信息学竞赛辅导教科书(电子版)_第2页
信息学竞赛辅导教科书(电子版)_第3页
信息学竞赛辅导教科书(电子版)_第4页
信息学竞赛辅导教科书(电子版)_第5页
已阅读5页,还剩246页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第一篇 PASCAL语言第一章 绪论1.1 Turbo Pascal 概述Pascal是1971年瑞士苏黎士工学院N.Wirth教授专为结构化程序设计而设计的一种高级语言,历时三十载,经久不衰,已成为世界上广泛流行的程序设计语言之一。Pascal之所以受到欢迎,是因为1.Pascal是结构化的语言Pascal语言全面清晰地体现结构化思想。不仅提供了直接实现“顺序结构”、“选择结构”和“重复结构”的语句,而且还可以定义子程序(“函数”和“过程”)。在编程时可以完全不使用转向语句,使程序的执行顺序与行文顺序保持一致,便于理解;2.Pascal的数据类型丰富 Pascal语言不仅提供了整型、实型、字

2、符型、布尔型等标准数据类型,而且还允许用户按照语法规则自定义枚举型、子界型、数组型、集合型、记录型、指针类型和文件类型,便于数值计算和非数值信息处理;3.Pascal语言可以实现模块的独立化要求 Pascal语言允许在函数和过程内部定义局部变量,允许在主程序和子程序之间传递参数,使得每一个子程序模块都能反映一个相对独立的性质,模块之间的联系简单清晰,便于修改; 由于Pascal语言精确地表达了程序设计的基本概念,结构性好,表达能力强,因此成为学校程序设计课程的教学语言,计算机会考和奥林匹克信息学竞赛的规定语言。本书将详尽地讲解Pascal的语法规则和turbo. Pascal的集成环境,所有示

3、例都采用Pascal语言或类Pascal语言编写。Turbo Pascal是编译型的程序设计语言,编译程序将源文件(源程序文件)转换成目标文件(二进制代码文件)。其过程如图1:图1所有编辑、编译、运行和调试过程集中在Turbo Pascal集成环境(IDE)中进行。IDE 界面如图1所示:图1屏幕中央为编辑窗口,用户在该窗口输入和修改源程序。屏幕的底行为“热键命令”表,在集成环境的任何地方,按动“热键”即可执行对应的命令。屏幕顶行为主菜单。主菜单有十项,它们是File 文件处理子菜单Edit 编辑子菜单Search 查找、替换子菜单Run 运行子菜单Compile 编译子菜单Debug 调试处

4、理子菜单Tools 工具子菜单Option 选择项处理子菜单Window 观察子菜单Help 帮助子菜单在集成环境的任何地方,只要按“热键”F10就可以激活主菜单。在主菜单上可以用、选择相应的子菜单。选中的菜单会以彩色或高亮度标出,这时键入Enter后便可进入。更简便的方法是同时按Alt和所选子菜单的首字母,进入相应的子菜单。在子菜单状态下按Esc,可使子菜单消失,返回主菜单。子菜单是一个下拉式菜单,内含多个可供选择的命令。例如File子菜单共有十项Open F3 打开一个文件New 建立一个新文件Save F2 存盘Save as 另存为Save all 全部存盘Print 打印Get in

5、fo 改变目录DOS shell 进入DOS环境Exit Alt+x 退出Turbo Pascal集成环境我们可按、选择相应的命令,亦可通过键入命令的首字母选择。F3、F2和Alt+x为“热键”,含“热键”的命令可在集成环境的任何地方使用。例如,无论何时按F2,都可以将当前编辑窗口中的文件存盘。不含“热键”的命令只能在File子菜单中使用。在主菜单中,最有吸引力的恐怕莫过于帮助子菜单(Help)了。该子菜单列出了所有帮助信息的详细目录,是一个完善的帮助系统。这个帮助系统不仅为初学者自学提供了丰富的资料,而且是成熟的编程者备查的“字典”。为了方便大家随时查询,系统还专门设置了热键F1,在集成环境

6、的任何地方,只要按该键就可进入帮助子菜单。Help子菜单共有5项,由上而下依次是 Contents 帮助内容 Index Shift+F1 帮助索引 Topic search Ctrl+F1 主题查找 Previous topic Alt+F1 上一次的帮助主题 Help on help 在线帮助在编辑程序文本时,如果想了解某个Pascal结构(函数、变量、类型等)的帮助信息,可把光标移至该处,按Ctrl+F1(同时按下Ctrl和F1),系统将立刻回答你的查询。我们在这里强调帮助子菜单,是因为它的完整性和实用性是任何一本Pascal的教科书或工具书所不能及的。它涵盖了Pascal的语法细节,并

7、提供了大量实用的库程序,用户上机编程时可以“信手拈来”。经常学习帮助子菜单中的内容,不仅可以提高对系统的熟练程度,而且可以提高英文的阅读水平,更重要的是可以获得比知识本身更有价值的东西自主探索、学会学习。1.2实例的演示 在这一章节中,我们想通过两个实例的演示,使读者初步了解Pascal程序的基本结构,掌握系统编辑、存储、编译、调试和运行用户程序的一般过程。【例121】五环图调用cal的作图程序单元,画出图1.2.1所示的五环图图1.2.1输入 r(圆的半径);x0,y1(左上角圆的圆心坐标); d(x坐标的位移);y2(下方两个圆的圆心的行坐标)输出五环图形状,直至按回车键为止。注:系统中有

8、一个作图程序单元graph,里面包含了许多库程序。例如“Circle(x,y,r)”在屏幕上画一个以(x,y)为圆心、r为半径的圆。编程者可以利用这些库程序作图。程序开始时,设置调用作图程序单元的命令“uses graph”。并在调用库程序前通过“DetectGraph(gd,gm)”设置驱动程序和图模式编号;“InitGraph(gd,gm,BGI)”初始化图形系统。在调用了单元graph中所需要的库程序后,必须通过“closeGraph”命令关闭图形系统。 我们在所在的子目录下键入“BP”(或在windows桌面上选中快捷键“BP”),进入集成环境,然后按“ALT+E”选择编辑子菜单。此时

9、,光标位于编辑窗口的左上角,等待你键入程序:program circles;uses graph; 调用系统内名为graph 的程序单元var gd,gm:integer; gd图设备的驱动程序编号;gm图模式编号 r,x0,d,y1,y2: integer;r半径;(x0,y1)左上角圆的圆心坐标;dx坐标的位移;y2下方两个圆的圆心的y坐标begin DetectGraph(gd,gm); 设置驱动程序和图模式编号 InitGraph(gd,gm,BGI); 初始化图形系统 Readln(r,x0,y1,d,y2); 读入五环图的信息 Circle(x0,y1,r); Circle(x0+

10、2*d,y1,r);Circle(x0+4*d,y1,r); 画上一行的三个圆 Circle(x0+d,y2,r); Circle(x0+3*d,y2,r); 画下一行的两个圆CloseGraph; 关闭图形系统end.main由上例可以看出程序的一般结构: program 程序名; 说明部分 begin 语句部分 end除需要通过“uses 单元名”调用子程序库的情况外,任何程序都以“program 程序名”开始。例如上述程序的首部为“program circles”,circles为编程者自定义的程序名。“program 程序名”只是从形式上给程序定义一个名称,与程序的执行无甚影响,因此可

11、以省略;源程序中用到的常量、变量、转移位置、函数和过程、用户自定义的数据类型,必须在说明部分中定义,程序不允许使用未经定义的标识符。每一种说明都以特定的保留字开始(如表1):说明内容变量说明常量说明类型说明行号说明函数说明过程说明保留字varconsttypelabelfunctionproceduer表1【例121】五环图的上述程序仅有变量说明(对程序所使用的变量及其类型加以说明),说明程序使用变量gd,gm和r,x0,d,y1,y2,它们都为整数类型。语句部分以“begin”开始,以“end”结束。语句间用“;”隔开;程序的书写方式灵活,即允许一行写一条语句;也允许一行写几条语句;甚至允许

12、空行。允许在程序的任何位置插入注释(注释用 括起来),以便阅读。注释对程序的执行不起任何作用。我们可以通过下述方法提高编辑效率:使用多重并行窗口允许在屏幕上设置多个编辑窗口,同时显示多个源程序。打开的窗口数最多可达100。但在同一时刻,只能对一个窗口中的文件进行编辑,该窗口称谓“当前窗口”。打开窗口 输入文件 打开一个空的文本窗口(filenew) 当前窗口中的文件取名为nonami.pas,i为打开窗口的顺序(0i99) 在窗口中打开文件(fileopenF3) 选择了子命令fileopenF3后,屏幕中央显示如下信息(图1.2.2) 图1.2.2控制窗口管理 选择窗口 windowsfil

13、e同时显示所有窗口,可通过ALT+窗口编号选择窗口;windowslist显示打开窗口和关闭窗口的文件列表; windowsnext(F6)选择后一个窗口为当前窗口; windowspreuious选择前一个窗口为当前窗口; 设置窗口显示方式windowssizemove(ctrl+F5)通过shift+方向键()扩大或缩小当前窗口;zoom(F5)满屏显示当前窗口与恢复原窗口大小位置的切换;windowscascade串行显示所有窗口;windowsclose关闭当前窗口;文本块的粘贴 如果需要输入的内容(称为文本块)在当前窗口或另一个窗口存在的话,则可以通过粘贴的方式,将这些文本块从它处经

14、由记录板移至当前位置。例如上述程序中有5个Circle命令。我们只需要输入一个Circle,其余4个可通过粘贴和修改获得。粘贴文本块的过程如图1.2.3所示: 图1.2.3 建立或取消文本块如果在Wondows系统下,则从文本块的开始位置起,按动鼠标至文本块的结束位置,白色的亮条覆盖的区域即为文本块;如果在DOS系统下,则按照下述方式建立文本块:若文本块为光标所在的字符,则按Ctrl+K+T;若文本块为光标所在的行,则按ctrl+kl;若文本块为一段,则将光标移至文本块的开始位置,按ctrl+kb。然后将光标移至文本块的结束位置,按ctrl+kk。此时,白色的亮条覆盖该区域,标志文本块建立。

15、取消文本块选择Editclear(ctrl+Del)。 文本块拷贝至记录板文本块有两种方式进入记录板:若文本块需要从源程序中删去,则选择Editcut(shift+Del);若文本块需要在源程序中保留,则选择Editcopy(ctrl+ins)。若需要显示和修改记录板的内容,选择Editshow clipboard。 文本块由记录板粘贴至指定位置 如果目标位置在另一个窗口,则将该窗口设定为当前窗口。光标移至目标位置,选择Editpaster(shift+ins)。此时,记录板中的文本块被粘贴。编辑后的文件在运行前必须存盘,以免出现意外情况(例如死机或陷入死循环)而丢失信息。存盘的方式有若以原名

16、存盘,则选择filesave(F2)。选择该命令后,原文件被覆盖。若当前窗口用New创建,则需输入文件名;若待存储的文件需要以新文件名命名,则选择filesave as。选择该命令后,原文件变成副本保留在内存;若需要将所有被打开窗口中的文件存盘,则选择filesave all;文件存盘后,可以退出集成环境,在DOS或Windows下检查文件是否已存入指定位置。退出的方式有两种:若需要释放系统所占的内存,则选择fileexit(Alt+x);若需要保留系统所占的内存,则选择fileDOS shell。在DOS状态下键入“exit”命令,便可返回集成环境。文件存盘后,便可以放心编译或运行程序了,不

17、必担心出现“前功尽弃”的事。选择compilecompile命令,编译当前编辑的源文件。若源文件有语法错误,则返回编辑窗口,光标指向错误行,顶行显示错误类型;若源文件语法正确,则产生可执行代码文件(即类型为Exe的文件),该文件可以脱离集成环境,直接在计算机中运行;如果不需要产生可执行代码文件的话,则可避开编译过程,直接在集成环境中运行源程序。我们采取后一种运行方式,按ctrl+F9运行五环图程序。当你输入五环图的信息(左上角圆的圆心坐标(x0,y1),x坐标的位移d,下方两个圆的圆心行坐标y2)后会发现程序返回了集成环境。是不是程序没有被执行呢?当然不是。原因在于计算机的速度太快,显示在DO

18、S屏幕上的运行结果瞬间被集成环境覆盖了。那么,怎样才能观察到运行结果呢,有两种途径:若希望在编辑窗口下方开辟DOS窗口,则选择Windowsoutput;若希望整个屏幕作为DOS窗口,则选择Windowsuses screen(Alt+F5)。在DOS状态下按Esc或Alt+F5,可返回的集成环境;除了使用的集成环境下的命令外,我们还可以通过程序本身来解决这个问题:在程序结束前(即“End”前)增加一条语句“readln;”即五环图显示在DOS屏幕时,程序并未运行结束,在等待你键入一个回车。直至回车后才返回的集成环境。我们今后编写程序时,不妨可以借鉴这个经验。在运行五环图程序时,五环图的大小、

19、位置和美观程度取决于输入数据(r,x0,y1,d,y2)。建议你们输入“66 180 200 72 272”看一看屏幕上的五环图是不是达到了最佳效果。5.程序的调试 程序设计工作是一项容易出现差错的工作。一般来说,程序的错误有两种:语法错。这类错误可由编译程序查出。避免这类错误发生的办法只有一个认真学习和切实掌握语言的功能和规范。语义错,即源程序经编译通过之后,在运行中出现的各种错误。通常有以下几种:书写错误的计算公式。忽视很少出现的极端情况,如溢出、越界、死锁、死循环等。程序结构或逻辑出错。根据运行结果查验程序是否按预定的要求工作。如果程序被证明语义有错,就转入调试,确定程序中可疑错误的确切

20、性质,改正错误。调试程序的方法一般有两种:静态查错。即不用执行程序,仅根据程序和框图对求解过程的描述来发现错误。动态查错。即在程序执行的过程中寻找错误的确切位置。Turbo Pascal的集成环境中含大量的动态调试功能,这些功能主要集中在主菜单Run,Debug,option中,这些主菜单如图1所示:图1.2.4下面举一个实例,介绍如何利用集成环境中的调试功能进行程序测试和排错的一些经验:【例122】计算数列计算数列 s=1+3+5+7的前n(1n500)项的数和。输入: n输出: 数和s题解 由数列的形式可以看出,第1项数为1,相邻两个数等差2。显然,第n项数为2*n-1。输入下述程序(注意

21、:程序左端的数码是为解释调试过程设置的,不用输入):vari,n:integer; i当前项;n项数。i和n的数据类型为整数s:longint; 和,数据类型为长整型begin s:=0; 初始时和为0 i:=1; 第一项为1 readln(n); 读项数 while i2*n-1 do 若当前项小于等于上限,则循环 begin s:=s+i; 当前项计入和 i:=i+2; 计算下一项 end;while writeln(total=,s); 输出和 readln; 空等回车end.main(注意:在Pascal程序中,“:=”表示赋值,“=”表示大小相等的关系,与人们的习惯写法不同)由于程序

22、无语法错误,编译一次通过。输入5(回车),屏幕上显示“totol=16”。显然,数列的和应为25。这个答案表明程序有语义错误。为此,我们利用集成环境中的调试功能进行动态查错。选择DebugWatch命令,在屏幕下方开辟一个观察窗口,该窗口能在程序运行过程中显示被观察变量的当前值。通过debugadd watch(Ctrl+F7)设置被观察变量i,s。然后按ctrl+F2(RunProgram reset),从头开始执行。在各种执行方式中,选择一次执行一行的方式调试程序。连续按F7(RunTrace Into),白色亮条随当前被执行的行上下移动,各个观察变量的当前值显示在观察窗口。当白色亮条移至

23、第7行,系统便进入了DOS屏幕,等待用户输入数据。在输入数据“5”后系统又返回集成环境,白色亮条在812行间上下移动,表明这几行程序是一个循环结构,其中9-12行是循环体,可以看成逻辑上独立的一条语句。循环的条件是i2*n-1,每执行一次循环,当前项i记入数列和s。但问题是,循环了四次后程序便退出循环(由第8行跳至第13行),输出前4项的和16。这说明最后一项并未记入数和。当我们将循环条件改为i2*n-1(即第8行改为“while i=2*n-1 do”),程序便可以给出正确的解了。通过上述调试过程,我们对while语句和beginend语句的涵义已经有了一种直觉。由此可见,集成环境中的调试功

24、能不仅可以用来进行动态查错,而且还可以作为学习语言的工具。借助于对程序的跟踪调试,可以使我们了解语法的形成过程,有利于建立一种生动活泼的编程思想。 图1.2.5介绍了使用集成环境调试功能的一般过程。读者在今后学习语言或调试查错时可以借鉴: 图1.2.5(一)调试初始化设置检查状态检查数值越界的情况。查出越界后,将产生出错信息。置 optioncompile菜单中的 Range checking项为 On。 过程或函数执行前检查堆栈可用内存情况。若堆栈没有足够空间,会产生运行错误 置 optioncompile菜单中的 Stack checking项为 On。最简便和周全的办法是按ctrl+o+

25、o。编辑窗口的第1行显示所有编译开关状态$编译命令字。将其中的-(关闭状态)改为+(打开状态)。2设置观察状态在观察中设置一些变量、数据结构、表达式作为观察量,它们反映出程序运行中的当前量。 debug菜单中列举如下功能: 在屏幕下方开辟观察窗口(Watch窗口),选择 watch项; 在Watch窗口中加入一个变量。将光标移至需观察的变量,选择Add watch项(或按Ctrl+F7)。 选择Add watch项,输入需观察的变量,例如调试【例122】计算数列的程序,可设定观察变量i(当前项)和s(数列和);(二)单步跟踪一次执行一行程序以观察其结果。当调用过程或函数时,可以选择是否将该过程

26、或函数一步跳过,还是一步步跟踪下去。Run菜单中列举了如下功能: 一次执行完过程和函数调用, 选择 Step Over项(或按 F8)。 以一次一行的方式执行用户程序, 选择 Trace Into项(或按 F7)(三)执行到光标所在行将光标移到某处,然后从 Run菜单中选择 Goto Cursor(或按F4), 可使用户直接到达要调试的地点。例如,在调试【例122】时,将光标移到第8行while i2*n-1 do 按F4,程序运行至该行。(四)断点 可在程序中设置一些行作为断点(红色亮条所在的行为断点)。当程序运行到断点时, 停止运行。此时就可以检查变量值, 进行单步跟踪或运行程序直到下一断

27、点。debug 菜单中列出相应功能。当然 在程序运行中,也可用Ctrl+Break来中断运行,就如同在瞬间设立一个断点。设置光标所在的行为断点。选择add breakpoint项(或按Ctrl+F8);删除所有断点或或确定下一断点位置。选择breakpoint项;例如,在调试【例122】时,将光标移到第8行while i2*n-1 do 按Ctrl+F8,第8行被一条红色的亮条覆盖,表示该行为断点。如果按Ctrl+F9,则程序直接运行至断点。 显然,在调试方式(二)、(三)、(四)中,单步跟踪的盲目性最大,调试效率最低;执行到光标所在行的方式次之;将可能出错的位置设为断点进行调试,效率最高。(

28、五)求值和修改 选择Debugvaluatemodife(或按Ctrl+F4),屏幕上出现了Evaluate窗口、result窗口和New value窗口。求值 在Evaluate窗口中输入一个表达式,在result窗口立即显示表达式的当前值。这样,可以在表达式结果被程序其它部分使用之前,测试其正确性。修改 在Evaluate窗口输入需赋新值的变量,然后在New value窗口输入一个新值并回车, 则在Result窗口中显示该变量被赋值后的情况。 注:退出Evaluate窗口前,Watch窗口中的值不变。(六)路标在Debug菜单中设置了两个追踪程序执行路径的功能:在多模块程序中,找到过程和函

29、数的说明部分。选择Find function项。根据所在的路径和函数跟踪到调用它们的地方,并检查调用时候传递的参数。选择Call stack项(或按Ctrl+F3)(七)准备编译运行调试后的程序通过改变某些编译方式,取消某些根据调试需要设置的选择项,提高运行效率。例如在optioncompile命令中, 置range checking、stack checking的选择项为off。如果是通过按ctrl+o+o设置编译开关状态的话,则将其中的+(打开状态)改为-(关闭状态)。除一个例外:如果程序中使用了浮点运算,则$n+保留。1.3 输入语句和输出语句 Pascal语言提供输入语句和输出语句供程

30、序使用。输入语句从外部设备读入数据给程序指定的变量;输出语句把计算结果用某种适当的形式输出到外部设备。通常的输入设备是键盘,输出设备是显示器或打印机。一个程序可以有0个或任意多个输入(如果没有输入语句,则通过常量说明或赋值语句设置初始数据);但至少有一个输出,因为没有输出结果的程序是毫无意义的。功能:从键盘读入数据项,并把它存到变量中去,使该数据能在以后的计算中使用。输入语句的一般形式为: read(v1,v2,vn); readln(v1,v2,vn);从键盘逐次读入数据,分别赋给变量v1,v2,vn,它们的数据类型可以是整数型、实数型、字符型或字符串型, 其类型在程序中由变量说明来定义。一

31、次输入多个变量值时,要求数据之间用空格分隔,readln语句要求输入数据后必须回车,使得后继操作从下一行的头上开始。例如语句 read(a,b); readln(a,b);其中变量a和b为整数类型。程序执行至read(a,b)时,键盘输入 10_20系统分别将10存入变量a,20存入变量b。程序执行至readln(a,b)时,键盘输入 30_40(回车)系统除将30存入变量a,40存入变量b外,还将回车符转化为空格符存入变量b,相当于执行read(a); readln(b);功能:把程序计算的结果,按适当的形式输出到屏幕。输出语句的一般形式为: write(Item1,Item2,Itemn)

32、; writeln(Item1,Item2,Itemn);其中Itemi(1in)表示输出项,它有两种形式:表达式:首先对表达式求值,然后输出值。表达式限定为整型、实型、字符型和布尔型。字符串:即前后用单引号( )括起来的任意字符组成的串。输出时,所有项按列出顺序打印在一行上。若使用write语句,则光标置于同一行末项后;若使用writeln语句,则光标移到下一行。为方便列表,用户可为每个输出项指定一个域宽。指定方法是输出项后跟上一个: 和一个指定域宽的整型表达式,即形式为“项:域宽”。如果输出项的长度少于域宽,则往右靠齐;如果输出项的长度多于域宽,则取实际长度。如语句writeln(A=,a

33、:3,A+B=,a+b:6);若程序中a已赋值1000,b已赋值500,则输出字样为 执行writeln(A=,a:3,A+B=,a+b:6);相当于执行write(A=,a:3);writeln(,A+B=,a+b:6);在Pascal程序中,实数(real)以浮点型格式输出。例如805.67对应的浮点数为8.056700000000E+02。这种实数表达方式很不方便。我们可以通过下述形式强迫实数以定点型格式输出: 实数表达式:域宽:小数位数例如,t的值设为63.123。下面三条输出语句分别有它们右边所示的输出格式: write(t); write(t:6:2); write(t:6:5);

34、【例131】匀加速运动输入匀加速运动的初速度v0、加速度a和时间t。输出t时间后的速度vt、t时间内走过的路程s和平均速度v。所有输出数据保留小数点后两位。题解:按照匀加速运动的公式t时间后的速度vt= v0+a*tt时间内走过的路程s= v0*t+平均速度v=由于输出数据的长度取决于实际长度,因此域宽设为0。按照输出格式要求,小数位数设为2。由此得出如下程序:varv0,v,vt,t,s,a:real;begin readln(v0,a,t); 输入初速度,加速度和时间 vt:=v0+a*t; 计算末速度 s:=v0*t+(a*t*t)/2; 计算路程 v:=s/t; 计算平均速度 writ

35、eln(vt=,vt:0:2); 输出末速度 writeln(s=,s:0:2); 输出路程 writeln(v=,v:0:2); 输出平均速度 readln; 空读回车end.main【例132】输出一个菱形输出图1.3.1所示的菱形:图1.3.1题解我们将图1.3.1中的菱形等分成上下两部分,其中第1-4行为上半部分,第5-7行为下半部分。第一行的*所在的列为基准列(设为40列)。在上半部分,除第1行外,每一行左端的*比上一行左端的*左移一个位置;右端的*比上一行右端的*右移一个位置。在下半部分,每一行左端的*比上一行左端的*右移一个位置;右端的*比上一行右端的*左移一个位置。由此得出程序

36、:const s=40; 基准列begin writeln(*:s); 输出菱形的上半部分 writeln(*:s-1,*:2); writeln(*:s-2,*:4); writeln(*:s-3,*:6); writeln(*:s-2,*:4); 输出菱形的下半部分 writeln(*:s-1,*:2); writeln(*:s); readln; 空等回车end.main上述程序为了输出高度为7行的菱形,不厌其烦地使用了7句writeln语句。如果我们要求输出的菱形高度为任意行(行数为奇数)的话,这种直叙的方式显然是不行的,必须寻找一种规律:第1行和第n行仅一个*,位置在基准列;中间行(

37、第2行n-1行)中,前行为菱形的上半部分,其余行为菱形的下半部分。菱形的上半部分,左端*的位置在s-i列(i为中间行的顺序),相隔2*i个位置为右端的*;在菱形的下半部分,左端*的位置在s-(n-i-1)列(i为中间行的顺序),相隔2*(n-i-1)个位置为右端的*。按照上述思想,我们编写如下程序。希望读者借助于集成环境中的调试功能跟踪运行该程序,通过这种自学方式增加一点对循环语句(for)、判断语句(if)和复合语句(beginend)的感性认识,对今后学习有好处。在编程过程中,算法创造是第一位的,语法知识只是为之服务的工具。为了算法实现的需要,才去学习和使用Pascal的有关语句。两者的关

38、系一定要摆正。const s=40; 基准列var i,n:integer; 循环变量,菱形的行数begin readln(n); 读菱形的行数 writeln(*:s); 输出菱形的第1行 for i:=1 to n-2 do 输出菱形的第2(n-1)行 begin if i=b then goto 20; 若a大,则转去减b b:=b-a; goto 30; 若b大,则b减a,并转去判断a是否为020: a:=a-b; 计算a减b的差30: if a0 then goto 10; 若差非0,则循环 writeln(gcd(,m,n,)= ,b); 输出最大公约数 readln;end. m

39、ain 上述程序的执行流程是一个循环。由于重复次数(即a和b相减的次数)预先未知,而只知重复控制条件(a=b),因此只能同时使用ifthen和GOTO语句。由于GOTO语句和ifthen语句产生控制转向,进程不能严格按程序语句的正文顺序前进,程序结构性差,程序逻辑复杂。PASCAL的控制结构基本上采用了结构程序设计所推荐的顺序、选择、重复的控制结构,可以完全避免GOTO语句的使用,因此能正确地、清晰地表达了计算过程的逻辑结构。用这三种基本控制结构相互嵌套,可连接成层次分明的“结构化程序”,能够求解任何复杂的可计算问题。 2.2 顺序结构顺序结构用来表示一个操作序列,控制从操作序列的第一个操作开

40、始,顺序执行每一个操作,直至执行完序列的最后一个操作为止。PASCAL用复合语句描述这种顺序控制结构。格式: begin 语句1; 语句n-1;语句n end其中Begin和end相当于一个语句括号,将语句1语句n括起来,表示这个语句序列由复合语句构造,在逻辑上已是一个整体,在语法上已成为一条独立语句。所有成分语句按照书写顺序执行。因此每当句法要求只能出现一个语句的地方,且在实际描述算法时,计算动作又很复杂,就可用复合语句来构造。在使用复合语句时,应注意如下几个问题:在程序中,begin和end必须成对出现。主程序可看作是一条复合语句,以.结尾。有一点必须注意,在程序中分号;作为语句间的分隔符

41、,但复合语句与控制结构的保留字(如begin,END或者条件选择结构的THEN,ELSE等)之间不应有分号。例如if 条件 then begin end 不应有分号 else 语句 若复合语句的最后一条成分语句与END之间出现分号,就认为该语句与END之间逻辑上存在一个空语句( 不执行任何操作的语句)。begin和end之间至少含两条语句,但主程序除外。复合语句可以嵌套使用,即在一条复合语句中,可以再嵌套复合语句。图2对于多层语句的书写,一般采用阶梯形,同一层的begin和end对齐,不同层次的复合语句错落有致,使得层次分明,结构清晰。这样做,不仅有利于begin与end的配对,而且便于分析阅

42、读。2.3选择结构 从几个可能的操作序列中,按条件选择其中一个执行,这就是选择结构的基本涵义。选择结构的形式有二种:条件选择结构;多路选择结构;布尔表达式 凡值为布尔型的表达式皆为布尔表达式。包括布尔常量、布尔变量或布尔函数,也包括关系表达式和有逻辑运算符的布尔表达式。通过六种比较运算符 、=、=、x,表示根据x值确定与5的大小关系。若x=-1,则关系式为true;若x=6,则关系式为false。用逻辑运算符 not(非)、and(与)、or(或)将若干个关系表达式(或布尔表达式)连接起来,形成了布尔表达式。not为一元运算符,将右边的关系表达式(或布尔表达式)的值取反。例如not false

43、的值为true。and为二元运算符。当且仅当两边的关系表达式(或布尔表达式)的值皆为true时,运算结果为true;否则为false。例如(0=x)and(x=8)表示当x落在0,8区间的话,结果为true;否则为false。or亦为二元运算符。当两边的关系表达式(或布尔表达式)中至少有一个的值为true时,运算结果为true;否则为false;在上述三种逻辑运算中,运算的优先顺序依次为notandor。 条件选择结构条件选择结构有一个布尔表达式和两个供选择的操作序列组成。运行时根据布尔表达式求值的结果,选取其中之一的操作序列执行之。PASCAL用条件语句来描述条件选择结构,其格式如图和图:若

44、布尔表达式的值为真,则执行then后面的语句;若布尔表达式的值为假时有两种情况:要么执行else后面的语句,要么什么也不做(无else)。注意:布尔表达式不能写成if 布尔表达式then;语句;虽然上述语句不会出现语法错误,但由于then后画蛇添足的;代表了一个空语句,因此无论布尔表达式的值如何,都将执行“if 布尔表达式then;”的后继语句。允许then的后继语句又是一个条件选择结构。例如 if c1 then if c2 then if cn then 语句; (c1、c2、cn为布尔表达式)上述语句等效于if (c1)and(c2)and(cn) then语句;在PASCAL条件语句中

45、被构造的语句只能是一条语句,当条件选择某个分支的计算要用多个语句描述时,就得把该分支用Begin和end括起来,写成复合语句。另外,实际书写多重IF语句连续嵌套时,插入适量的复合语句,可澄清多重IF语句的内部结构。例如下面语句显得有点模糊: IF e1 then IF e2 THEN s1 ELSE s2;试问,ELSE对应着哪一个IF? PASCAL约定ELSE总是与最近的一个IF配对。根据这个约定, 将上述结构改写成如下锯齿形书写形式,就清楚得多了。 IF e1 THEN BEGIN IF e2 THEN s1 ELSE s2;END;then这里特别提醒读者的是,在转换布尔表达时要十分注

46、意转换前后的等效性。例如 if(ad)and(bc) then 语句1 else 语句2;与下述语句 if ab then if bc then 语句1 else 语句2 是不等效的,而与 if ab then beginif bc then 语句1 else语句2;endthen else 语句2; 是等效的。 多路选择结构有一个表达式和众多可选择的操作序列组成。运行时根据表达式的求值结果,在众多的分支中选取一个分支执行。图2多路选择结构在PASCAL中用分情形语句case说明描述,其格式为:case 表达式of 常量表1: 语句1; 常量表n: 语句n; else 语句n+1 任选项,可有

47、可无 end; casecase语句执行与表达式值相匹配的case常量所指向的那条语句,如果没有相匹配的值,则执行else后的语句n+1或什么也不做(无else行)。在使用case语句时须注意:end与case对应(end相当于case语句的结束标志),而不是与begin对应;case常量必须唯一确定且必须与表达式同类型,每一个常量只能在常量表中出现一次且仅出现一次;否则会在执行哪一条语句上出现二义性;表达式只能是序数类型;注:序数类型是一种有序的数据类型集合,序数类型的每一个值都有一个次序,次序值可由下列函数确定: ord(x)返回序数类型值x的次序值; pred(x)返回序数类型值x的前驱

48、(x非有序集合中的第一个值); succ(x)返回序数类型值x的后继(x非有序集合中的最后一个值);序数类型包括整数类型(integer)、字符类型(char)、布尔类型(boolean)、枚举类型、子界类型,这些类型的每一个值都有一个次序,其对应关系如表2.3.1所示:X的数据类型序数值ord(x)整数类型X字符类型X的Ascll码布尔类型X=false ord(x)=0X=true ord(x)=1子界类型(常量1常量2)Ord(X)=x的序数值(常量1x常量2)枚举类型(标识符1,标识符k)X=标识符1 Ord(x)=0X=标识符k Ord(x)=k-1 表2.3.1【例231】判断闰年

49、输入年分,输出该年是否为闰年的信息。题解首先,我们来分析闰年的条件:公元世纪的整数能被4整除(年份 mod 4=0),但不能被100整除(年份 mod 100 0);公元世纪的整数能被400整除(年份 mod 400=0)上述两个条件中,只要有一个条件满足,则确定该年为闰年。由此得出判断闰年的布尔表达式: (年份 mod 4=0)and (年份 mod 100 0)or(年份 mod 400=0)var y:integer; 公元世纪的整数begin readln(y); 输入年份 if(y mod 4=0)and(y mod 1000)or(y mod 400=0) 判断是否闰年then w

50、riteln(year,y,is a leap year)else writeln(year,y,is not a leap year);end.main 【例232】按12小时记时法计算时间输入24小时记时法的时、分,输出12小时记时法的时、分。题解 按照输入24小时记时法,小时在023之间,分钟在059之间。转换成12小时记时法的办法:在1323时间段的小时减去12,并将0时转换成12时。var hour,minute:integer; 小时和分钟begin readln( hour,minute); 输入24小时记时法的小时和分钟 if(hour=0)and(hour=0)and(min

51、ute12 then hour:=hour-12; if hour=0 then hour:=12; end;then writeln(Time is ,hour,:,minute,pm); 输出12小时记时法的时、分end. main 【例233】计算税率现已知财产税的计算公式 财产税=估价值*税率税率按表2.3.2所示的方式计算:财产估价值税率=600006%表2.3.2输入财产估价值,要求输出财产税。题解 财产估价值分4个区间,落入各个区间的税率不同,可以使用case语句分情形处理。但问题是每个区间的估价值有1000020000个,如果都设为case常量,则匹配效率太低。我们不妨将财产估

52、价值整除10000,根据整商计算税率varc:integer; 估价值除以10000的整商v,r,t:real; 估价值,税率,财产税begin readln(v); 读估价值 if v=0 若估价值为正数,则计算税率 then begin c:=trunc(v/10000); if c6then c:=6; case c of0,1: r:=0.03; 2: r:=0.04; 3,4,5: r:=0.05; 6: r:=0.06;end;case t:=v*r; 计算财产税 writeln(assessed volue is ,v:0:2,tex is ,t:0:2); 输出财产税 end;

53、then readln;end.main【例234】计算今天星期几按照年 月 日的格式输入今天的日期。计算和输出今天是星期几的信息。题解 设年、月、日为y、m、d。按照余数公式 (a1+a2+an)mod k=(a1 mod k+a2 mod k+anmod k)mod k我们首先计算公元0000至去年(y-1)间每年天数对7的余数,累计它们的和y;然后计算今年1月至上月(m-1)的天数对7的余数m;最后得出(y+m+d)mod 7为今天的星期信息。1.计算公元0000至y-1年对7的余数和y 闰年的天数为366,对7的余数为2;平年的天数为365,对7的余数为1。公元0000年至去年(y-1

54、)含个闰年。由此得出公元0000至y-1年对7的余数和为y=y-1+。2计算今年1月至上月(m-1)的总天数对7的余数m若今年为闰年((y mod 4=0)and(y mod 1000)or(y mod 400=0)且月份大于2(m2),则m=m+1;3.根据表达式(y+m+d)mod 7的值,分情形输出今天是星期几的信息var y,y0,m,d,m0,s,week:integer;begin readln(y,m,d); 读今天的日期 y0:=y-1; 计算去年的年号 y0:=y0+y0 div 4-y0 div 100+y0 div 400; 计算公元0000至去年对7的余数和 case

55、m of 计算1月至m-1月的总天数对7的余数m0 1,10: m0:=0; 5: m0:=1; 8: m0:=2; 2,3,11: m0:=3; 6: m0:=4; 9,12: m0:=5;4,7: m0:=6; end;caseif(y mod 4=0)and(y mod 1000)or(y mod 400=0)and(m2) then m0:=m0+1; case(y0+m0+d)mod 7 of 根据(y+m+d)mod 7的值,分情形输出今天是星期几的信息 0:writeln(Sunday); 1: writeln(Monday); 2: writeln(Tuesday); 3: w

56、riteln(Wednesday); 4: writeln(Thursday); 5: writeln(Friday); 6: writeln(Saturday); end;casereadln;end.main 2.4重复控制结构重复控制结构为计算机程序描述重复计算提供控制手段。一个重复控制结构需指明以下三件事情中的两件:被重复执行的语句;是否重复的条件;详细指明重复方式。在PASCAL语言,用while,repeat和for三种语句描述重复控制结构。while的功能:在指定的条件成立(布尔表达式的值为true)时,重复执行指定的语句。程序流程如图所示:图语句格式:while 布尔表达式do

57、语句;while重复结构的特点是先求布尔表达式的值,然后确定是否执行do后面语句(通常是复合语句)表示的计算操作序列。为了能使while重复能终止,布尔表达式应包含有动态变化的变量v。变量v的初值在进入while重复之前设置,保证布尔表达式的值为真,进入正常的重复。在重复体中v的值有更改,重复操作若干次后的结果使表达式的值为假,于是重复结束。如果在重复体中v的值无更改的话,重复会无休无止地进行下去,这种现象称之为“死循环”。在循环体中,可通过break语句(调用库过程break)退出while循环。通常,人们按照下述步骤设计while结构的程序:确定重复条件;确定重复体;为使重复体正常工作确定

58、v的初值;【例241】计算多项式设多项式exp(x)=1+x+(10-10)输入x输出exp(x)的值(保留小数点后四位)题解 设s和;t当前项;ix的幂次。即s=t0+t1+t2+ti确定重复条件abs(t)1e-10;确定重复体由ti=*=ti-1*得出重复体ii+1;tt*;ss+t; 设定初值 i0;t1;s1;由此得出程序:var i,X:integer; x的幂次和自变量 t,s:real; 当前项和多项式的值 begin readln(x); 读自变量的值 i:=0; t:=1; s:=1; 赋初值 while abs(t)1e-10 do 若当前项未达到精度要求,则新增一项 b

59、egini:=i+1;t:=t*x/i;s:=s+t; end;while writeln(EXP(,X,)= ,S:0:4); 输出多项式的值 readln; END.main【例242】计算数字串输入一个任意字符串,从中取出一个数串(若字符串中含多个数串,则取第一个数串),并将之转换为数值。例如输入E45.36.,得出数值.。输入字符串输出数值题解转换过程如图2所示:图2译数全过程分四个阶段:s0初始阶段;s1译整数阶段; s2译小数阶段; s3结束阶段;输入字符分三类:、其他字符。设class为字符类型标志译数过程将进入哪一个阶段,取决于当前读入字符的类型。这一转换过程由表241所示:

60、表241表中有九个译数动作,按由左而右、自上而下排列,方格右下角圆圈内的数字即为动作序号,正好为s*3+class (s为行号,即阶段序号)。按照动作分类 动作1,3 :无任何操作; 动作4 :由阶段1进入阶段2,s2; 动作2,5 :译整数; 动作6,7,9 :转入结束阶段; 动作8 :译小数;数符ch通过ord(ch)-ord(0)转换为数字。在译整数阶段,每处理一个数符前,当前译出的整数*10,计入数符对应的数字,然后进入(或保持)阶段1;在译小数阶段,若译小数点右边的i个数符,则数符转换为数字后*(10-i),计入译数结果。var result,d:real; 译数结果,译小数的权 s

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论