资源预览内容
第1页 / 共158页
第2页 / 共158页
第3页 / 共158页
第4页 / 共158页
第5页 / 共158页
第6页 / 共158页
第7页 / 共158页
第8页 / 共158页
第9页 / 共158页
第10页 / 共158页
亲,该文档总共158页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
1教师(PASCAL语言)培训讲习江东区教研室 贾 为办班的目的:1、提高与扎实信息学科教师的专业素养。今后会在各类信息学科教师考核中有所侧重。2、形成一个学习与研究PASCAL语言的氛围,建立一支培训团队,促进我区的青少年信息学竞赛工作起步与发展。3、抛砖引玉。互帮互学,建立学习共同体。4、本期培训班以讲习PASCAL语言中基本语句为主,面向全体信息学科专业教师,进行由简单到复杂的编程思维训练,通过本期培训学会安装、调试PASCAL程序,能够读懂程序,并掌握独立编制简单程序的能力。建议参考书:1.PASCAL语言(中学版/小学版)第2版张文双,吴树娟主编(北京理工大学出版)2.数据结构与算法设计张文双、王学红主编(北京理工大学出版)3.奥赛经典信息学奥林匹克教程(基础篇、语言篇、提高篇) 湖南师范大学出版社出版 (宁波新江厦四楼书店有售。)序言:信息学奥赛的发展序言:信息学奥赛的发展1989年5月首次举办国际信息学奥林匹克竞赛,简称IOI,成为继数学、物理、化学之后的又一门国际(中学生)奥林匹克竞赛。1991年起全国青少年计算机竞赛更名为全国青少年信息学(计算机)奥林匹克竞赛,简称NOI。由中国科学技术协会主管,中国计算机学会主办。全国青少年信息学奥林匹克联赛,简称为NOIP,参加联赛是参加NOI的必要条件。信息学奥林匹克竞赛内容信息学奥林匹克竞赛内容1.1.程序设计知识。熟练使用一门程序设计语言编写程序;程序设计知识。熟练使用一门程序设计语言编写程序;程序设计知识。熟练使用一门程序设计语言编写程序;程序设计知识。熟练使用一门程序设计语言编写程序;熟悉常用的基本算法:如穷举法、排序(冒泡)法、搜熟悉常用的基本算法:如穷举法、排序(冒泡)法、搜熟悉常用的基本算法:如穷举法、排序(冒泡)法、搜熟悉常用的基本算法:如穷举法、排序(冒泡)法、搜索法、回溯法、递归算法,排列组合等。索法、回溯法、递归算法,排列组合等。索法、回溯法、递归算法,排列组合等。索法、回溯法、递归算法,排列组合等。2.2.数据结构知识。简单变量、数组、队列、栈、串、记录、数据结构知识。简单变量、数组、队列、栈、串、记录、数据结构知识。简单变量、数组、队列、栈、串、记录、数据结构知识。简单变量、数组、队列、栈、串、记录、指针、链表、树、图和文件。指针、链表、树、图和文件。指针、链表、树、图和文件。指针、链表、树、图和文件。3.3.调试程序技能。调试程序技能。调试程序技能。调试程序技能。FreePascal安装、启动与退出安装、启动与退出从江东信息网ftp:/ftp.jdedu.net,用户名xinxi,密码xinxi2007,下载Free Pascal 2.04(大小为42M)。点击install.exe自动安装程序在指定的路径目录中。(15分钟)在路径:目标盘符ppbingo32v2找到fp.exe文件,右键创建快捷方式后,复制到桌面上。单击桌面快捷图标即可启动Free Pascal 2.04。点击菜单栏:file下拉exit项即可退出pascal环境。按 alt+enter,进行全屏切换。Pascal 程序的输入与调试例T0_1:用数字打印三角形。Program T0_1; var j,h:integer;Begin for j:=1 to 5 do begin write ( :16-j); for h:=1 to 2*j-1 do write(h); writeln; end;End. 用主菜单的Compile中的菜单项Compile,或Alt+F9组合键,即可对程序进行编译。若文件没取名,则先建立文件名。 如果编译有错误,会显示相关出错信息。注意free Pascal安装时,有时会碰到与杀毒软件冲突的事情,编译也会不成功,需先将杀毒软件屏蔽。 运行程序:选择主菜单Run中的菜单项Run,或按ctrl+F9键。 查看结果。选择主菜单Debug中的菜单项Output可以查看结果。 保存文件。用主菜单file中的save或按F2键保存文件。第1课 认识PASCAL语言Pascal是一种计算机通用的、编译型的高级程序设计语言。它由瑞士Niklaus Wirth教授于六十年代末设计并创立。是一种按结构化程序设计原则描述的高级语言。主要特点有:严格的结构化形式;丰富完备的数据类型;运行效率高;查错能力强。NOI(全国奥林匹克信息学竞赛)把Pascal语言定为唯一提倡的程序设计语言 第1课 认识PASCAL语言让我们先来看一个PASCAL程序,通过这个程序了解PASCAL的规则。例例L1_1 L1_1 已知半径,求圆周长和面积的程序。程序说明:程序说明:PROGRAMcircle(input,output);(*第第1行:程序首部行:程序首部*)CONST(*第第2行:常量说明行:常量说明*)PI=3.14159;VAR(*第第4行:变量说明行:变量说明*)r,l,s:real;BEGIN(*第第6行:语句部分行:语句部分*)read(r);(*第第7行:输入语句行:输入语句*)l:=2*PI*r;(*第第8行:赋值语句行:赋值语句*,计算周长,计算周长)s:=PI*r*r;(*第第9行:赋值语句行:赋值语句*,计算面积,计算面积)write(r,l,s);(*第第10行:输出语句行:输出语句*)END.(*第第11行:语句部分以行:语句部分以END.结束结束*)完整的PASCAL程序框架Program 程序名(程序参数表); Label 标号说明; Const 常量说明; Type 类型说明; Var 变量说明; Function 函数说明; procedure 过程说明; begin 程序语句; end. 在在Free Pascal Free Pascal 中可省程序参数表。中可省程序参数表。 在程序执行部分使用的标号、常在程序执行部分使用的标号、常量、类型、变量、记录、文件、过量、类型、变量、记录、文件、过程和函数,都必须在说明部分进行程和函数,都必须在说明部分进行说明。但并不是每个程序都必需的,说明。但并不是每个程序都必需的,根据需要而设。根据需要而设。 程序执行部分是指程序执行部分是指BeginBegin开始到开始到最后一条最后一条End. End. 结束语句的部分,是结束语句的部分,是程序的核心。它由一系列语句组成,程序的核心。它由一系列语句组成,语句之间用语句之间用“ “;” ”隔开,允许一行隔开,允许一行写多个语句,也允许一个语句写成写多个语句,也允许一个语句写成几行。一般情况下一行只写一个语几行。一般情况下一行只写一个语句。句。1、PROGRAM写在最左边顶格;2、注释的大括号、和CONST、VAR、BEGIN、END等语句上下对齐,且它们比PROGRAM向右移两个字符;3、各个语句和程序语句也是上下对齐,它们比第2点中的各语句又向右移两个字符;4、语句间多余空格与空行,编译时会忽略。程序的书写格式:程序的书写格式:数制的转换1、常用的进位计数制有:十进制、二进制、八进制、十六进制。名称基数标志符十进制0,1,2,3,4,5,6,7,8,9,D二进制0,1B八进制0,1,2,3,4,5,6,7Q十六进制0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,FH十进制D二进制B八进制Q十六进制H00000001000111200102230011334010044501015560110667011177810001089100111910101012A11101113B12110014C13110115D14111016E15111117F161000020102 2、常用进制对照表、常用进制对照表3、十进制与二进制的相互转换例1:将十进制数20.6875转换成二进制数。(1)整数部分的转换:“除以2倒序取余法”。2 20 0 2 10 0 2 5 1 2 2 0 2 1 1 0(2)小数部分的转换:“乘2取整法”。 0.6875 0.3750 0.75 0.5 2 2 2 2 1.3750 0.75 1.5 1.0 1 0 1 1 正序取整倒序取余合在一起得:(20.6875)10=(10100.1011)2例2:将(11001.0101)2转换成十进制数。(11001.1101)2 = 124+123+022+021+120+12-1+12-2 +02-3+12-4 =16+8+1+0.5+0.25+0.0625 =(25.8125)10 十进制数和二进制数的转换可以推广 到十进制与八进制、十进制与十六进制数的转换。如十进制数转换在八进制数的方法是:“除以8倒取余法”;十进制小数转换成八进制小数的方法是:“乘8取整法”。课堂作业:(1)(1101101.101)2 =( )10 (2) (45.625)10 =( )2第2课 PASCAL的数据类型、标识符、表达式、语句 数据对于一门程序语言是非常重要的,数据的一个非常重要的特征就是它的类型。PASCAL规定:程序中出现的变量必须先说明才能使用。二个值,即整数类型包括正整数(+号可略)、负整数和零。1,204在会计统计中是允许的,但在pascal中是非法的。整数类型的标识符为integer,取值范围为:-32768n 32767。在free pascal中,允许整数采用十六进制(前加$)或二进制(前加%)表示。 如 x := %101,相当于 x:=5 ,y:=$10, 相当于y:=16 整数的类型:名称类型标识符数据范围短整型Shortint-128127长整型Longint-21474836482147483647字节型Byte0255字型Word065535整数类型Int64-92233720368547758089223372036854775807无符号整数Qword int64018446744073709551615注意:int64int64不是有序类型。直接给一个不是有序类型。直接给一个 int64int64类型的变量赋值一个超过类型的变量赋值一个超过longintlongint范围的范围的整数是非法的,这是因为整数是非法的,这是因为free pascalfree pascal在表达式的计算中默认最大类型为在表达式的计算中默认最大类型为longintlongint。标识符标识符是以字母开头的字母、数字组合,用来表示常量、变量、类型、文件、函数、过程或程序的名字。x,y,max,min,sum,a15,a3b7都是合法的标识符。而5x,x-y,ex10.5都是非法的标识符。标识符的长度一般不要超过8个字符。标识符的选取最好有一定意义,这样便于记忆,也增加了程序的可读性。表达式和运算符 算术运算符: + , - , * , /, div(整除), mod(取余)关系运算符:=, , , =, , 逻辑运算符:AND,OR,NOT表达式就是将数据和运算符结合使用,组成一组有意义的运算式。在PASCAL语言中规定,表达式按下列运算优先规则计算:1、所有括起来的子表达式必须先计算,且子表达式必须从里到外计算;2、在同一子表达式中的运算符按下列次序计算: 函数;NOT;AND,*,/,DIV,MOD; OR,+,-; ,=,3、在同一个子表达式中,同一优先级的运算按从左到右的次序进行。4、MOD运算结果的符号总是和被除数相同,而与模无关。 -15 mod 6 = -3 -15 mod (-6) = -3 15 mod (-6) =3 PASCAL程序中的运算优先规则 常量与变量常量定义格式: const = ;要求如下:1、要放在程序说明部分。2、必须遵循先定义后使用的原则。3、不允许重复定义,或一次定义多个常量。例如: const a =1; a,b = 10; c = 1 or 2; d := 3;v变量定义格式: var :类型标识符;例如: var a,b :integer; x,y :real; ch :char; t: boolran;但下列说明是非法的:例如: var a,b =integer; ch :char; ch :boolean; a,b后面不能用=,ch不能重复定义。变量一经说明,系统就为其分配内存。程序中使用该变量时,就要在相应的内存单元读写数据,称为对变量的访问。常用函数常用函数与表达式与表达式顺序结构程序设计1 1、赋值语句、赋值语句 赋值语句的格式: 变量标识符 : = 表达式; 功能: 赋值语句是先执行计算表达式的值,然后赋值给变量标识符。 说明:(1)” := “ 称为赋值号,不要与 ” = “ 混淆。赋值有方向性,左边只能是变量,不能是表达式,如 x := 1是非法的。(2)赋值号两边的类型必须相同,但是整型表达式可以赋值给实型,反之不成立。(3)一个赋值语句只能给一个变量赋值,变量可以赋值多次,但只保留最后一次的值。(4)被赋值的变量可以作为表达式因子参与运算,如: i:=i+1;是合法的。(5)对变量的赋值是对变量的存入访问。如d:=a;语句执行后,d的变量内容就已经是a变量的内容,但是a变量的值并没有消失与改变。 在实际编程中,我们经常使用a:=a+1;作为计数器,用s:=s+x;作为累加器,用t:=t*n;作为累乘器。2、输入(read、readln)语句输入语句格式:格式1: read ;格式2: readln ();功能:执行该语句时,程序进入等待状态,等待用户从键盘输入数据,输入的数据将依次赋给变量表中的变量,而后程序继续执行其他语句。说明:(1)变量表中变量超过一个时,中间用逗号隔开。从键盘输入数据时,数据的个数不能少于变量个数,否则电脑一直处于等待状态。当数据多于变量个数时,对于readln语句将其忽略,对于read语句时,会补下一句read语句读入,如果没有输入语句,也将其忽略。(2)输入数值型数据时,必须用空格或回车键分隔,最后一定要用回车键。输入字符型数据时,不能有空格与回车键,必须连续输入,因为空格与回车键也会当作字符。(3)输入的数据必须是常量,且必须与对应的变量类型相一致。(4)readln();可以没有变量名表,此时该语句等待从键盘输入回车键。 Readln (x) ; 等价于执行了二条语句:read(x); readln();3、输出(write 、writeln)语句输出语句的格式:格式1 write ;格式2 writeln ();功能:按指定的格式将输出项的内容输出到屏幕上。说明:(1)输出项如果是多项时,各项间用逗号分隔。(2)输出项可以是常量、变量、函数、表达式。常量直接输出,变量时输出变量的存储单元内容,遇到函数与表达式时,先计算、再输出。(3)write 语句输完最后一项时,不换行,等待下一条 write语句继续输出。Writeln语句输完最后一项时换行,该语句允许没有输出项,起到换行作用。 writeln(x); 等价于执行了write(x); writeln();例:X:=2; y:=3; writeln(x=,x,y=,y); writeln(x+y=,x+y,x*y=,x*y)输出结果为:x=2 y=3x+y=5 x*y=6writewrite语句可以输出实型、语句可以输出实型、整型、字符型、布尔型值,整型、字符型、布尔型值,也可以输出字符串。若在也可以输出字符串。若在writewrite语句中不加场宽说明,语句中不加场宽说明,则按标准场宽输出。在这则按标准场宽输出。在这里,场宽是指输出值的位里,场宽是指输出值的位数。数。自定义场宽(1)单场宽。单场宽。用来控制整型、字符型、布尔型数据的输出格式,不能用于实数型。 格式:n 说明:n(正整数) 表示输出时所占的列数。单场宽一律右对齐,前用空格。(2)双场宽。双场宽。用来控制实数的输出格式。 格式: :n1:n2 说明: n1表示输出总占列数,包括符号位、整数部分、小数点和小数部分;n2表示小数部分的列数。 当数据突破场宽时,首先保证整数部分的有效性,小数部分按n2场宽进行四舍五入显示,但内存中仍是原来的精确度。 单场宽右对齐,双场宽向小数点看齐,多余的小数位数补零。例T2_1:交换两个变量的值。(1)利用中间变量)利用中间变量c,实现交换。,实现交换。ProgramT2_1_1;Vara,b,c:integer;Beginwrite(pleaseinputa,b=?);read(a,b);write(before:,a=,a,b=,b);c:=a;a:=b;b:=c;writeln(after:,a=,a:8,b=,b:8);End.(2)不用中间变量,也可实现交换。)不用中间变量,也可实现交换。ProgramT2_1_2;Vara,b:integer;Beginwrite(pleaseinputa,b=?);read(a,b);write(before:,a=,a,b=,b);a:=a+b;b:=a-b;a:=a-b;writeln(after:,a=,a:8,b=,b:8);End.例例T2_2:鸡兔同笼问题。已知鸡和兔的总头数鸡兔同笼问题。已知鸡和兔的总头数是是H,总腿数为,总腿数为F,求鸡和兔各多少只?,求鸡和兔各多少只?分析:设鸡为分析:设鸡为C只,兔为只,兔为R只,则只,则C+R=H2*C+4*R=F解得:解得:C=(4*H-F)/2,R=H-C。程序为:程序为:ProgremT2_2;varh,f,c,r:real;beginreadln(h,f);c:=(4*h-f)/2;r:=h-c;writeln(click:,c);writeln(rabbit:,r);end.例T2_3: 随机产生一个三位自然数,求其百位、十位、个位上的数字。分析:要产生随机数,必然用到随机函数。Random是随机函数能产生0,1之间的随机实数。 随机产生三位数的表达式为: trunc(random*900)+100假设三位数X,百位数分另别为A,B,C,则存在如下关系:A= X DIV 100B= (X-A*100) DIV 10C= X MOD 10程序为:Program T2_3; VAR x,a,b,c:integer; begin randomize; 它的作用是每次运行程序时,random函数产生不同的随机数。起到埋种子作用。 x:=trunc(random*900)+100; writeln(x=,x); a:=x div 100; b:=(x-a*100) div 10; c:=x mod 10; writeln(a:5,b:5,c:5); End. 例T2_4 已知三角形的两边及夹角,求第三边及面积。数学建模:设三角形的两边及夹角分别为a,b,第三边为c,面积为s。则 ,若以角度值输入,在计算sin和cos时应转换为弧度。角度转弧度的公式为:弧度=角度程序:程序:Program T2_4;Program T2_4; const const pi=3.14159; pi=3.14159; var var a,b,alfa,c,s:real; a,b,alfa,c,s:real; begin begin read (a,b,alfa); read (a,b,alfa); alfa:=alfa*pi/180; alfa:=alfa*pi/180; c:=sqrt(a*a+b*b-2*a*b*cos(alfa); c:=sqrt(a*a+b*b-2*a*b*cos(alfa); s:=1/2*a*b*sin(alfa); s:=1/2*a*b*sin(alfa); write(alfa=,alfa,c=:8,c,s=:8,s); write(alfa=,alfa,c=:8,c,s=:8,s); end. end.例T2_5: 输入一个字符,求其序号、前导(即前一字符)、后继(即后一字符)。ProgramT2_5;ProgramT2_5;varvarch,pch,sch:char;ch,pch,sch:char;num:integer;num:integer;beginbeginwriteln;writeln;write(pleaseinputacharacter:);write(pleaseinputacharacter:);readln(ch);readln(ch);write(pch:,pred(ch),sch:,succ(ch),num:,ord(ch);write(pch:,pred(ch),sch:,succ(ch),num:,ord(ch);readln();readln();end.end. 测试删除倒数第二条语句测试删除倒数第二条语句测试删除倒数第二条语句测试删除倒数第二条语句readln();readln();后,执行情况有何不同?后,执行情况有何不同?后,执行情况有何不同?后,执行情况有何不同?例T2_6: 输入x,y。若在圆环内,输出true,若在圆环外;输出false。圆环如图所示。讨论:如图所示,若下式1x2+y24成立则在圆环内,否则在圆环外。设布尔变量bool,当x,y在圆环内时,让它取值为true,否则取值为false。“ “(x x,y y)若在圆环内)若在圆环内” ”的表达式:的表达式:(x2+y212)(x2+y212)且且(x2+y222) (x2+y222) 程序:程序: program T2_6;program T2_6; var var x,y :real; x,y :real; bool:boolean; bool:boolean; begin begin writeln; writeln; write(x=?); write(x=?); readln(x); readln(x); write(y=?); write(y=?); readln(y); readln(y); bool:=(x*x+y*y=1) and (x*x+y*y=1) and (x*x+y*y50除了上面给出的IF语句形式外,PASCAL中还有另外一种IF语句形式。即IF (条件) THEN (语句)在条件为真时,执行THEN后的语句。在条件为假时,不执行THEN后的语句,在两种情况下的后继语句都是IF语句的下一个语句。例例L3_2 读入三个数,找出并打印其中的最大数。解:PROGRAM L3_2; VAR a,b,c:real; BEGIN write(a=?); read(a); write(b=?); read(b); write(c=?); read(c); IF ab THEN a:=b; IF ac THEN a:=c; writeln(ZuiDaShu:,a) END.3.2.2 3.2.2 复合语句复合语句在IF语句中,跟在THEN或ELSE后的语句可能不止一个,这时要用到复合语句的概念。复合语句是一个以BEGIN开始,以END结束的语句。在BEGIN与END之间可以包括若干个语句,每个语句之间以分号分开。一般形式为:BEGINBEGIN (语句(语句1 1);); (语句(语句2 2);); (语句(语句n n)ENDEND一个复合语句从外部看来,相当于一个语句。3.2.3 IF语句的嵌套在IF语句中,THEN或ELSE后的语句本身也可能是IF语句。此时称为IF语句的嵌套(或称为复合IF语句)。例如语句 IF(条件1) THEN(语句1) ELSE IF(条件2) THEN(语句2) ELSE(语句3) 就是一个复合IF语句,在它的ELSE后又是一个IF语句。有时IF语句可能会有两种不同的理解。 注意:在进行注意:在进行IFIF语句的嵌套时应注意语句的嵌套时应注意IF IF 与与 ELSEELSE的配对关系,的配对关系,ELSEELSE是不能是不能省略的,否则将造成逻辑错误。解决的办法是写一个空语句或者采用复合省略的,否则将造成逻辑错误。解决的办法是写一个空语句或者采用复合语句,即增加语句括号(语句,即增加语句括号(beginbeginend)end)。从内层开始,。从内层开始,ELSEELSE总是与它上面总是与它上面最近的(示曾配对的)最近的(示曾配对的)IFIF配对。配对。例L3_3: 有一个函数表达式为:编写程序,输入x,输出y的值。3.3 CASE语句 CASE语句是实现选择结构程序设计的另一种语句。它的使用有时比IF语句来得简单、直观。 CASE语句(或称情况语句)的一般形式是 CASE (表达式) OF (值表1):(语句1); (值表2):(语句2); (值表n):(语句n); ELSE 语句n+1; END; 在CASE语句头上的表达式必须是有序类型(整型、字符型、布尔型以及后面要介绍的枚举型、子界型)。值表是一些由逗号分开的常数。表达式所有可能的值必须在值表中出现,且每个值只能出现一次。 如果当前表达式的值在某个值表i中出现,则该程序只执行对应值表i的语句i,然后执行整个CASE语句后的下一语句。 else 可以省略,此时若无表达式的值与之相匹配的常数表时程序将向下运行并跳出case语句。 例L3_5 输入年、月,输出该月有几天。讨论:每年的讨论:每年的1、3、5、7、8、10、12月,每月,每月有月有31天;天;4、6、9、11月,每月有月,每月有30天;天;2月闰年有月闰年有29天,平年有天,平年有28天。天。年号能被年号能被4整除,但不整除,但不能被能被100整除,或者年整除,或者年号能被号能被400整除的年均整除的年均是闰年。是闰年。用用year、month、days分别表示年、月、每月分别表示年、月、每月天数。它们均为整数。天数。它们均为整数。闰年的条件可以写成如闰年的条件可以写成如下的布尔表达式:下的布尔表达式:(yearMOD4=0)AND(yearMOD1000)OR(yearMOD400=0)Program L3_5; var year,month,days:integer; begin read (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 1000) or (year mod 400 =0) then days:=29 else days:=28; end; writeln (year,year,month,month:,days:,days);End.例L3_6 编制程序,根据输入的x值,计算y与z并输出。PROGRAM L3_6;PROGRAM L3_6; CONST CONST PI=3.14159; PI=3.14159; VAR VAR x,y,z:real; x,y,z:real; BEGIN BEGIN write(x=?); write(x=?); read(x); read(x); IF x=2.5 IF x=2.5 THEN y:=x*x+1 THEN y:=x*x+1 ELSE y:=x*x-1; ELSE y:=x*x-1; IF x0 IF x0 THEN z:=-PI/2*x+3 THEN z:=-PI/2*x+3 ELSE IF x=0 ELSE IF x=0 THEN z:=0 THEN z:=0 ELSE z:=PI/2*x-5; ELSE z:=PI/2*x-5; writeln(x=,x:6:2,y=,y:6:2, z=,z:6:2) writeln(x=,x:6:2,y=,y:6:2, z=,z:6:2) END. END.作业:XT3_1对一批货物征收税金,价格在对一批货物征收税金,价格在1万元以上的货物万元以上的货物征税征税5%,在,在5000元以上,元以上,1万元以下的货物征税万元以下的货物征税3%,在,在1000元以上,元以上,5000元以下的货物征税元以下的货物征税2%,1000元以下元以下的货物免税。编写一程序,读入货物价格,计算并输出的货物免税。编写一程序,读入货物价格,计算并输出税金。税金。XT3_2输入某学生成绩,若成绩在输入某学生成绩,若成绩在85分以上,输出分以上,输出verygood,若成绩在,若成绩在60分到分到85分之间,输出分之间,输出good,若成绩,若成绩低于低于60分,输出分,输出nogood。XT3_3输入班号,输入该班学生人数。应用输入班号,输入该班学生人数。应用CASE语句语句编程序。编程序。班级201202203204205班额4547424648第4课 循环结构循环结构(或称重复结构)是程序中的一个基本结构,在循环结构(或称重复结构)是程序中的一个基本结构,在解许多问题中是很有用的。我们知道,在许多复杂的问题解许多问题中是很有用的。我们知道,在许多复杂的问题中,常常需要做大量类同的计算处理。尽管计算机的运算中,常常需要做大量类同的计算处理。尽管计算机的运算速度很快,然而要把这些大量类同的计算处理的每一步都速度很快,然而要把这些大量类同的计算处理的每一步都写成语句,并输入计算机中,其工作量是相当大的。有时写成语句,并输入计算机中,其工作量是相当大的。有时是难以完成的。是难以完成的。循环结构程序设计可以帮助我们有效地解决这一难题。利循环结构程序设计可以帮助我们有效地解决这一难题。利用循环结构程序设计,使得我们有可能只编写少量的语句,用循环结构程序设计,使得我们有可能只编写少量的语句,让计算机重复执行它许多次,从而完成大量类同的计算要让计算机重复执行它许多次,从而完成大量类同的计算要求。求。在在PASCAL中,实现循环程序设计的主要语句有中,实现循环程序设计的主要语句有FOR语句、语句、WHILE语句和语句和REPEAT语句。语句。一、FOR语句格式1:(递增型) FOR x:= TO DO 格式1: (递减型) FOR x:= downTO DO FOR X:= 1 TO 10 DOFOR X:= A TO Z DO 控制变量控制变量初值初值控制变量控制变量终值终值falsetrue执行语句执行语句控制变量控制变量succ(控制变量)控制变量) 控制变量控制变量初值初值控制变量控制变量终值终值falsetrue执行语句执行语句控制变量控制变量pred(控制变量)控制变量)FOR X:=10 DOWNTO 1 DOFOR X:=10 DOWNTO 1 DOFOR X:=Z DOWNTO A DOFOR X:=Z DOWNTO A DOT4_001 计算1+2+3+10PROGRAM T4_001; VAR s,n:integer; BEGIN s:=0; FOR n:=1 TO 10 DO s:=s+n; writeln(s=,s) END.s=0当n=1 s=s+n=0+1=1;当n=2 s=s+n=1+2=3当n=3 s=s+n=3+3=6当n=4 s=s+n=6+4=10当n=5 s=s+n=10+5=15当n=6 s=s+n=15+6=21当n=7 s=s+n=21+7=28当n=8 s=s+n=28+8=36当n=9 s=s+n=36+9=45当n=10 s=s+n=45+10=55例T4_002 : 输入10个任意整数,求它们的和. PROGRAM T4_002; VAR s,n,a:integer; BEGIN s:=0; FOR n:=1 TO 10 DO BEGIN read(a); s:=s+a; END; writeln(s=,s) END.例例例例T4_003T4_003: 计算计算计算计算n!n!(n!=123n!=123nn)PROGRAM T4_003; VAR n,i,sum:integer; BEGIN read(n); sum:=1; FOR i:=1 TO n DO sum:=sum*i; writeln(n!=,sum); END.注意N8,否则会溢出。例T4_004:任何一个 n3一定可以表示成n个连续的奇数和。输入n(n100),输出n3对应的表达式。数学题解:设表达式中的最小奇数为x;当N=1时,最小奇数X=1,1个奇数;当N=2时,最小奇数X=3,2 个奇数;当N=3时,最小奇数X=7,3 个奇数; N N3 1 1 2 23=8=3+5 3 33=27=7+9+11 4 43=64=13+15+17+19 当 N=K 时,最小奇数 X 前己有 1+2+3+(K-1) 个奇数,则第K个奇数 K*(K-1)X = *2+1=K*(K-1)+1=N*(N-1)+1 2ProgramT4_004;vari,n,a:longint循环变量,连续的奇数个数,当前项,类型循环变量,连续的奇数个数,当前项,类型为长整型为长整型beginreadln(n);a:=n*(n-1)+1;fori:=1ton-1dobeginwrite(a,+);a:=a+2;end;writrln(a);readln;end思考题:用数学方法证明上述定理。作业:T4_005 输入10个任意整数,求它们的平均值。T4_006 按正序和反序分别输出26个英文字母。T4_007 输入20个整数,输出其中最大数。T4_008 输入20个整数,统计其中正、负和零的个数。思考题:求值:作业答案:PROGRAM T4_005; VAR ave:real; i,n,sum:integer; BEGIN sum:=0; FOR i:=1 TO 10 DO BEGIN read(n); sum:=sum+n; END; ave:=sum/10; writeln(ave=,ave:6:2) END. PROGRAM T4_006; VAR i:integer; BEGIN writeln(); FOR i:=1 TO 26 DO write(chr(96+i); writeln(); FOR i:=122 DOWNTO 97 DO write(chr(i) END.PROGRAM T4_006_1; VAR i:char; BEGIN writeln(); FOR i:=ATO Z DO write(i); writeln(); FOR i:=ZDOWNTO A DO write(i) END.作业答案:PROGRAM T4_007; VAR max,i,n:integer; BEGIN read(max); FOR i:=1 TO 19 DO BEGIN read(n); IF max0 THEN Zheng:=Zheng+1 ELSE IF n=0 THEN Ling:=Ling+1 ELSE Fu:=Fu+1; END;FOR writeln(Zheng Shu You: ,Zheng,; Fu Shu You: ,Fu,; Ling You: ,Ling) END.二、while 语句 (当型循环) 当循环次数未知,例如它依赖于某个布尔表达式的值,而此值在循环执行过程中会改变。这种循环不可能由FOR语句实现,PASCAL为此提供了WHILE语句和REPEAT语句。 WHILE语句的一般形式: WHILE DO flaseflase布尔表达式布尔表达式布尔表达式布尔表达式truetrue语句语句语句语句例例T4_009:求求S=2+6+10+98的值。的值。分析:S为求和累加器,X为当前项,赋初值为2,每次循环后增加4,取X98为布尔表达式。ProgramT4_009;ProgramT4_009;VarVars,x:longint;s,x:longint;beginbeginx:=2;s:=0;x:=2;s:=0;whilex=98dowhilex=98do当满足条件时执行后面语句当满足条件时执行后面语句当满足条件时执行后面语句当满足条件时执行后面语句beginbegins:=s+x;s:=s+x;x:=x+4;x:=x+4;end;end;writeln(s=,s);writeln(s=,s);end.end.课堂作业:计算 S=1+2+4+8+128+256的值。例T4_010:求两个自然数的最小公倍数。分析:先从数学角度来分析一下,所谓最小公倍数就是指能被M和N同时整除的最小自然数。先设一个变量i,让它从1开始按自然数增长,将i与M相乘的结果存到变量S中,这样S就是M的公倍数,由于i是从最小开始的,然后再用每一个S除以因子N,若能整除,则S为M和N两个因子的最小公倍数。Program T4_010;var n,m,I,s:longint;begin write(请输入两个自然数); readln(m,n); i:=1; s:=m*I; while s mod n 0 do begin i:=i+1; s:=m*I; end; writrln(s=,s);end.三、repeat语句(直到型循环)REPEAT语句也用于循环次数未知的循环,它的用法与WHILE语句稍有不同。REPEAT语句的一般形式如下:REPEATUNTIL 例 T4_011 计算 (泰勒展开式) 直到最后一项的绝对值小于10-7时停止计算,x由键盘输入。题解:题解:题解:题解: 设设设设 S S为累加器,为累加器,为累加器,为累加器,t t为当前项,为当前项,为当前项,为当前项,i i为为为为X X的幂次的幂次的幂次的幂次 即即即即S=tS=t1 1+t+t2 2+t+t3 3+t+tk k, ,其中其中其中其中(1 1)确定重复条件为)确定重复条件为)确定重复条件为)确定重复条件为abs(t)1e-7abs(t)1e-7(2)(2)确定重复体确定重复体确定重复体确定重复体由由由由(3)(3)设初值设初值设初值设初值 由此得出程序:由此得出程序:由此得出程序:由此得出程序:ProgramT4_011;ProgramT4_011;varvarI:integer;I:integer;t,s,x:real;t,s,x:real;beginbeginreadln(x);readln(x);x:=x*3.14159/180;x:=x*3.14159/180;i:=1;t:=X;s:=0;i:=1;t:=X;s:=0;repeatrepeats:=s+t;s:=s+t;t:=-t*x/(i+1)*x/(i+2);t:=-t*x/(i+1)*x/(i+2);i:=i+2;i:=i+2;untilabs(t)1e-7;untilabs(t)1e-7;writeln(sin(,x,)=,s:0:4)writeln(sin(,x,)=,s:0:4)readln;readln;End.End.作业:T4_012: 计算 当最后一项的绝对值小于10-6时结束,打印输出结果。T4_013: 求满足条件 N! 100000 的最大值N。三种循环语句的相同点与不同点FORWHILEREPEAT语句格式句格式FOR := TO DO WHILE DOREPEATUNTIL 循循环变量量赋值布布尔尔表达式表达式无循无循环变量量循循环次数次数确定,由初确定,由初值和和终值决决定定不确定,由循不确定,由循环体前的布体前的布尔尔表达式决定,当表达式决定,当值为“假假”时,结束循束循环。可能一次循可能一次循环也没有也没有不确定,由循不确定,由循环体后的体后的布布尔尔表达式决定,表达式决定,当当值为“真真”时结束束循循环。至少有一次循至少有一次循环循循环体体多多语句句时,需用,需用BEGIN和和END多多语句句时,需用,需用BEGIN和和END多多语句句时,不需用,不需用BEGIN和和END用计算机解题的基本方法 在对问题有了清楚的分析后,可以仔细地构造求解步骤在对问题有了清楚的分析后,可以仔细地构造求解步骤在对问题有了清楚的分析后,可以仔细地构造求解步骤在对问题有了清楚的分析后,可以仔细地构造求解步骤算法。算法可以自顶向下、由粗到细,逐步求精。算法。算法可以自顶向下、由粗到细,逐步求精。算法。算法可以自顶向下、由粗到细,逐步求精。算法。算法可以自顶向下、由粗到细,逐步求精。描述问题由粗到细的过程,一般可以分为三步:描述问题由粗到细的过程,一般可以分为三步:描述问题由粗到细的过程,一般可以分为三步:描述问题由粗到细的过程,一般可以分为三步:一级算法一级算法一级算法一级算法二级求精二级求精二级求精二级求精写出程序写出程序写出程序写出程序 第5课 多重循环如果一个循环结构的内部(循环体)又包括一个循环结构,就称为多重循环结构。实现多重循环结构仍可以用前面讲的三种循环语句。因为任一循环语句的循环体部分都可以包含另一个循环语句,这种循环语句的嵌套为实现多重循环提供了方便。多重循环的嵌套次数可以是任意的。可以按照嵌套层次数,分别叫做二重循环、三重循环等。处于内部的循环叫作内循环,处于外部的循环叫作外循环。在设计多重循环时,要特别注意内、外循环之间的关系,以及各语句安放的位置,不要搞错。T5_001 求1100之间的素数(质数),每行输出5个素数.素数是大于素数是大于素数是大于素数是大于1 1,且除了,且除了,且除了,且除了1 1和它本身外,不能被其它任和它本身外,不能被其它任和它本身外,不能被其它任和它本身外,不能被其它任何整数所整除的整数。何整数所整除的整数。何整数所整除的整数。何整数所整除的整数。讨论:根据素数的定义可知讨论:根据素数的定义可知讨论:根据素数的定义可知讨论:根据素数的定义可知为了判断某数为了判断某数为了判断某数为了判断某数i i是否为素数,一个最简单的办法是用是否为素数,一个最简单的办法是用是否为素数,一个最简单的办法是用是否为素数,一个最简单的办法是用2 2、3 3、4 4、5 5、i-1i-1这些数逐个去除这些数逐个去除这些数逐个去除这些数逐个去除i i,看能否除,看能否除,看能否除,看能否除尽。若被其中一个数除尽了,则尽。若被其中一个数除尽了,则尽。若被其中一个数除尽了,则尽。若被其中一个数除尽了,则i i不是素数,否则不是素数,否则不是素数,否则不是素数,否则(全都除不尽)(全都除不尽)(全都除不尽)(全都除不尽)i i是素数。(此算法次数较多)是素数。(此算法次数较多)是素数。(此算法次数较多)是素数。(此算法次数较多)用用用用2 2、3 3、4 4、去除,如果都除不尽,则去除,如果都除不尽,则去除,如果都除不尽,则去除,如果都除不尽,则i i是素数。是素数。是素数。是素数。(此算法次数较少)(此算法次数较少)(此算法次数较少)(此算法次数较少)一级算法:一级算法:FORi:=2TO100DOBEGIN1、用、用2到去除到去除i,看看能否除尽,看看能否除尽2、IF除不尽除不尽THEN输出素数输出素数iEND算法需进一步求精。用变量算法需进一步求精。用变量yn来表示是否除来表示是否除尽。尽。一开始让一开始让yn=1,当有一个数能除尽时,让,当有一个数能除尽时,让yn=0表示能除尽,这时表示能除尽,这时i不是素数;若循环不是素数;若循环结束时,结束时,yn仍等于仍等于1,表示都除不尽,这,表示都除不尽,这时时i是素数。是素数。二级求精二级求精1、用、用2到去除到去除i,看看能否除尽,看看能否除尽1-1yn:=11-2WHILEnsqrt(i)DOBEGINn:=n+1IFiMODn=0THENyn:=0END为了每行输出为了每行输出5个数,还需增加一个变量个数,还需增加一个变量counter来计数。来计数。ProgramT5_001;varI,n,yn,counter:integer;beginwriteln();counter:=1;Write(2,);fori:=3to100dobeginn:=1;yn:=1;whilensqrt(i)dobeginn:=n+1;ifImodn=0thenyn:=0;end;ifyn=1thenbegincounter:=counter+1;ifcountermod5=0thenwriteln(i)elsewrite(I,);end;ifend;forEnd.mainT5_002 验证哥德巴赫猜想(任何充分大的偶数都可由两个素数之和表示)。将42*s(s1000)中的所有偶数分别用两个素数之和表示。 哥德巴赫猜想是:对任一充分哥德巴赫猜想是:对任一充分大的偶数大的偶数even,可以找到两,可以找到两个素数个素数p、q。使得。使得even=p+q即即1+1问题。问题。此问题还未得到最后的证明。此问题还未得到最后的证明。我们这里只是对有限范围内的我们这里只是对有限范围内的数,用计算机加以验证,不数,用计算机加以验证,不算严格证明。算严格证明。读入偶数读入偶数even,将它分成,将它分成p和和q,使,使even=p+q。p从从2开始(每次加开始(每次加1),),q=even-p。如果。如果p、q均为素均为素数,则输出结果,否则将数,则输出结果,否则将p加加1再试。再试。一级算法:一级算法:一级算法:一级算法:1 1、读入一个数、读入一个数、读入一个数、读入一个数eveneven;2 2、判断、判断、判断、判断eveneven是否为偶数,如果是偶数,是否为偶数,如果是偶数,是否为偶数,如果是偶数,是否为偶数,如果是偶数,则继续,否则结束程序;则继续,否则结束程序;则继续,否则结束程序;则继续,否则结束程序;3 3、FORp:=2TOtrunc(even/2)FORp:=2TOtrunc(even/2)3-1q:=even-p3-1q:=even-p3-23-2判断判断判断判断p p是否为素数(是否为素数(是否为素数(是否为素数(pyn:=1pyn:=1表示表示表示表示p p为为为为素数,素数,素数,素数,pyn:=0pyn:=0表示表示表示表示p p不是素数)不是素数)不是素数)不是素数)3-33-3判断判断判断判断q q是否为素数(是否为素数(是否为素数(是否为素数(qyn:=1qyn:=1表示表示表示表示q q为为为为素数,素数,素数,素数,qyn:=0qyn:=0表示表示表示表示q q不是素数)不是素数)不是素数)不是素数)3-4IFpyn=1ANDqyn=13-4IFpyn=1ANDqyn=1THENwriteln(even,=,p,+,q)THENwriteln(even,=,p,+,q)二级求精:二级求精:二级求精:二级求精:1 1、read(even)read(even)2 2、IFevenMOD2=0IFevenMOD2=0THENTHEN第第第第3 3步步步步3-23-2、n:=2n:=2WHILEnsqrt(p)DOWHILEnsqrt(p)DOBEGINBEGINn:=n+1;n:=n+1;IFpMODn=0IFpMODn=0THENpyn:=0;THENpyn:=0;END;END;3-33-3、n:=2n:=2WHILEnsqrt(q)DOWHILEnsqrt(q)DOBEGINBEGINn:=n+1;n:=n+1;IFqMODn=0IFqMODn=0THENqyn:=0;THENqyn:=0;END;END;作业:程序找错误(一)错误一:第错误一:第错误一:第错误一:第2 2行少行少行少行少“ “VAR”VAR”;错误二:第错误二:第错误二:第错误二:第5 5行少分号;行少分号;行少分号;行少分号;错误三:第错误三:第错误三:第错误三:第4 4、6 6、8 8行,行,行,行,字符串应用单引号,题字符串应用单引号,题字符串应用单引号,题字符串应用单引号,题中用了双引号;中用了双引号;中用了双引号;中用了双引号;错误四:第错误四:第错误四:第错误四:第8 8行字符串与行字符串与行字符串与行字符串与变量之间少逗号。变量之间少逗号。变量之间少逗号。变量之间少逗号。作业:程序找错误(二)PROGRAMT5_004;PROGRAMT5_004;VARVARn,integer;n,integer;BEGINBEGINwrite(Pleaseinputanumberfrom0to6forwrite(Pleaseinputanumberfrom0to6forweekday:)weekday:)read(n);read(n);CASEnCASEn0:writeln(Sunday);0:writeln(Sunday);1:writeln(Monday);1:writeln(Monday);2:writeln(Tuesday);2:writeln(Tuesday);3:writeln(Wednesday);3:writeln(Wednesday);4:writeln(Thursday);4:writeln(Thursday);5:writeln(Friday);5:writeln(Friday);6:writeln(Saturday);6:writeln(Saturday);END.END.错误一:第错误一:第错误一:第错误一:第2 2行变量与数据类型行变量与数据类型行变量与数据类型行变量与数据类型之间应用冒号,这里用了逗号;之间应用冒号,这里用了逗号;之间应用冒号,这里用了逗号;之间应用冒号,这里用了逗号;错误二:第错误二:第错误二:第错误二:第5 5行少分号;行少分号;行少分号;行少分号;错误三:第错误三:第错误三:第错误三:第7 7行,行,行,行,CASECASE语句少语句少语句少语句少了了了了OFOF;错误四:错误四:错误四:错误四:CASECASE语句没有语句没有语句没有语句没有ENDEND与与与与之配对。之配对。之配对。之配对。作业:程序找错误(三)PROGRAMT5_005;VARch:char;ZiMu,ShuZi,FuHao:integer;BEGINZiMu:=0;ShuZi:=0;FuHao:=0;WHILEch?BEGINread(ch);IF(chA)AND(cha)AND(ch=48ANDord(ch)=48ord(ch)=48) ANDAND(ord(ch)=57ord(ch)=57)。)。)。)。T5_003 “百钱买百鸡”是我国古代的著名数学问题,内容是3文钱可以买1只公鸡,2文钱可以买1只母鸡,1 文钱可以买3只小鸡。用了100文钱买了100只鸡,问有多少只公鸡、母鸡、小鸡?分析:用分析:用分析:用分析:用X X,Y Y,Z Z分别代表购买公鸡、母鸡、小分别代表购买公鸡、母鸡、小分别代表购买公鸡、母鸡、小分别代表购买公鸡、母鸡、小鸡的数量,则存在以下关系:鸡的数量,则存在以下关系:鸡的数量,则存在以下关系:鸡的数量,则存在以下关系:同时满足:同时满足:同时满足:同时满足:1x33,1y50,1x33,1y50,1z1001z100。然后在各变量范围内进行检验,能。然后在各变量范围内进行检验,能。然后在各变量范围内进行检验,能。然后在各变量范围内进行检验,能满足上面两个关系式的变量值。满足上面两个关系式的变量值。满足上面两个关系式的变量值。满足上面两个关系式的变量值。Program T5_003Program T5_003VarVar x,y,z:integer; x,y,z:integer; begin begin for x:=1 to 33 do for x:=1 to 33 do begin begin for y:=1 to 50 do for y:=1 to 50 do z:=100-x-y z:=100-x-y if 3*x+2*y+z/3 =100 then if 3*x+2*y+z/3 =100 then writeln(gong qi:,x,mu writeln(gong qi:,x,mu qi:8,y, xiao qi:8,z);qi:8,y, xiao qi:8,z); end; end; end; end;End.End.第6课 PASCAL语言数据类型数据类型简单类型标准类型用户自定义类型整型实型字符型布尔型枚举类型子界类型构造类型集合类型数组类型字符串类型记录类型指针类型文件类型6.1.1整型的运算项目项目项目项目内容内容内容内容算术算术算术算术运算符运算符运算符运算符+ +、- -、* *、/ /,div(div(取商取商取商取商) )、mod(mod(取模取模取模取模) )关系关系关系关系运算符运算符运算符运算符= =、 、 、=标准标准标准标准函数函数函数函数Pred(Pred(前趋前趋前趋前趋) )、succ(succ(后继后继后继后继) )、ord(ord(序号序号序号序号) )、abs(abs(绝对值绝对值绝对值绝对值) )、sqr(sqr(平方平方平方平方) )、sqrt(sqrt(平方根平方根平方根平方根) )、odd(odd(判奇判奇判奇判奇) )奇数为奇数为奇数为奇数为true,true,偶数偶数偶数偶数falsefalse例T6_000: 如果变量A 既能被7整除又能被11整除,写成PASCAL表达式:(A mod 7=0) and (A mod 11=0)例例 T6_001: 求水仙花数。求水仙花数。所谓水仙花数,如所谓水仙花数,如ABC,如果满足,如果满足A3+B3+C3=ABC,则,则ABC称为水仙花数。称为水仙花数。 例:例:153=13+53+33,所,所以以153就是水仙花数。就是水仙花数。分析:此题关键是分解出分析:此题关键是分解出A、B、C a= I div 100 b= I div 10 10*a C= I mod 10ProgramT6_001;VarI,a,b,c:longint;beginforI:=100to999dobegina:=Idiv100b:=Idiv10-a*10c:=Imod10ifi=a*a*a+b*b*b+c*c*cthenwriteln(is,i)end;end.6.2: 实型名称名称名称名称类型名类型名类型名类型名数据范围数据范围数据范围数据范围位数字节位数字节位数字节位数字节单精度实型单精度实型单精度实型单精度实型SingleSingle1.5E-453.4E+381.5E-453.4E+384 4实实实实 型型型型RealReal2.9E-391.7E+382.9E-391.7E+386 6双精度实型双精度实型双精度实型双精度实型DoubleDouble5.0E-3241.7E+3085.0E-3241.7E+3088 8扩展实型扩展实型扩展实型扩展实型ExtendedExtended1.9E-49321.1E+49321.9E-49321.1E+49321010装配实型装配实型装配实型装配实型CompComp-2-26363+12+126363-1-1之间的整数之间的整数之间的整数之间的整数8 8 这几种实数类型的使用方法与Real的使用方法类似,必须在程序开始打开编译开关$N+,这些类别才能被系统识别。例T6_2: 求 1/1+1/2+2/3+3/5+5/8+前n项(n50)的和。分析:分析:分析:分析:设设设设e=te=t1 1+t+t2 2+t+t3 3+t+ti i+.+t+.+tn n, ,其中其中其中其中t ti i=,(1in)=,(1in)。由数列的特征可以看出,由数列的特征可以看出,由数列的特征可以看出,由数列的特征可以看出,a ai i=b=bi-1i-1,b,bi i=a=ai-1i-1+b+bi-1i-1。由于由于由于由于N50N50,因此,因此,因此,因此a ai i,b bi i,e e的数值超过了标准的整的数值超过了标准的整的数值超过了标准的整的数值超过了标准的整数型和实数型的范围。数型和实数型的范围。数型和实数型的范围。数型和实数型的范围。不得不通过不得不通过不得不通过不得不通过$N+$N+启动启动启动启动浮点运算,并将浮点运算,并将浮点运算,并将浮点运算,并将a ai i,b bi i,e e的数据类型设为的数据类型设为的数据类型设为的数据类型设为extended,extended,使得精度保持使得精度保持使得精度保持使得精度保持在在在在1919位。位。位。位。ProgramT6_2;$N+varI,n:integer;a,b,c,e:extended;beginreadln(n);a:=0;b:=1;e:=0;fori:=1tondobeginc:=b;b=a+b;a:=c;e:=e+a/b;end;forwriteln(e:20:2)end.main6.3:字符型(ASCII码)(1)类型名:)类型名:Char(2)范围:)范围:ASCII码(美国标准信息交换代码)码(美国标准信息交换代码)(3)表示方法:)表示方法:一个字符一个字符(4)字符是有序类型,每个字符都对应一个序号,其中字符)字符是有序类型,每个字符都对应一个序号,其中字符A的序号是的序号是64,字符,字符a的序号是的序号是97。(5)字符类型占内存一个字节。)字符类型占内存一个字节。6.4:布尔型(1)类型名:)类型名:boolean(2)范围:只有两个值)范围:只有两个值false和和true(3)是有序数据:)是有序数据:false序号是序号是0,true的序号是的序号是1。即。即ord(false)=0,ord(true)=1.约定:约定:false999)and(y999)and(y10000)(2)8(2)8乘以乘以乘以乘以X X为二位数为二位数为二位数为二位数(8x9)(8x9)(3)9(3)9乘以乘以乘以乘以X X为三位数为三位数为三位数为三位数(9x99)(9x99)程序:ProgramT6_3;ProgramT6_3;varvarx,y:integer;x,y:integer;beginbeginforx:=10to99doforx:=10to99dobeginbeginy:=809*x+1y:=809*x+1if(y999)and(y10000)and(8*x9)and(9*x99)and(9*x999)and(y10000)and(8*x9)and(9*x99)and(9*x1000)thenbeginthenbeginwriteln(809:19);writeln(809:19);writeln(-:20);writeln(-:20);writeln(x:6,):3,y:10);writeln(x:6,):3,y:10);writeln(8*x:17);writeln(8*x:17);writeln(-:20);writeln(-:20);writeln(y-800*x:19);writeln(y-800*x:19);writeln(9*x:19);writeln(9*x:19);writeln(-,20);writeln(-,20);writeln(1:19);writeln(1:19);end;thenend;thenend;forend;forend.mainend.main6.5: 枚举型(1)格式: type 枚举类型标识符=(标识符1,标识符2,标识符n); (2) 特点:枚举元素只能是标识符,不能是数值常量或字符常量同一枚举元素不能出现在两个及以上枚举型定义中枚举类型有顺序,序列号从0开始 ord(Monday)=0, succ(Friday)=Saturday, pred(Friday)=Thursday枚举类型只能进行赋值和关系运算枚举变量不允许用read或readln语句进行赋值,也不能被write或writeln输出。 例T6_4: 有红、橙、黄、绿、蓝5种顔色的小旗,每次取出3种不同顔色表示不同的信号,输出所有信号的方案及方案总数。分析:枚举值的分析:枚举值的输入,一般先输入,一般先输入序号,通输入序号,通过过CASE语句将语句将枚举值相应地枚举值相应地赋值给枚举变赋值给枚举变量;输出时,量;输出时,通过通过CASE语句语句判断枚举类型判断枚举类型变量的值,输变量的值,输出相应的字符出相应的字符串。串。ProgramT6_4;Typecolor=(red,orange,yellow,green,blue);varm,m1,m2,m3:color;s,p:integer;begins:=0;form1:=redtobluedoform2:=redtobluedoifm1m2thenform3:=redtobluedoif(m3m1)and(m3m2)thenbegins:=s+1write(s,:);forP:=1to3dobegincasepof1:m:=m1;2:m:=m2;3:m:=m3;end;casepcasemofred:write(red:8);orange:write(orange:8);yellow:write(yellow:8);green:write(green:8);blue:write(blue:9);end;case结束结束end;for结束结束writeln;end;if结束结束writeln(total:,s);end.6.6: 子界类型type子界类型标识符子界类型标识符=常量常量1.常量常量2注释:注释:常量常量2必须大于常量必须大于常量1;可以是整型、字符型、布尔型、枚举型等顺序型的两个可以是整型、字符型、布尔型、枚举型等顺序型的两个常量,且必须是同一类型的数据。常量,且必须是同一类型的数据。子界型常量上下界不可以是实数型。子界型常量上下界不可以是实数型。类型定义:类型定义:类型定义:类型定义:typeren=A.F;typeren=A.F;ProgramT6_5;ProgramT6_5;VarVarm,n:A.F;m,n:A.F;s:integer;s:integer;beginbegins:=0;s:=0;form:=AtoEdoform:=AtoEdoforn:=succ(m)toFdoforn:=succ(m)toFdobeginbegins:=s+1;s:=s+1;writeln(m,-,n);writeln(m,-,n);end;end;writeln(zhongshu=,s);writeln(zhongshu=,s);end.end.例例T6_5T6_5: 新学期开学第一天,新学期开学第一天,6 6个小朋友查聚后握手致意,请用个小朋友查聚后握手致意,请用A AF F表示表示6 6个小个小朋友,输出朋友,输出6 6个人相互握手的各种情况,并统计握手的次数。个人相互握手的各种情况,并统计握手的次数。1 1、常量说明语句、常量说明语句、常量说明语句、常量说明语句(1 1)无类型常量的说明)无类型常量的说明)无类型常量的说明)无类型常量的说明CONSTCONST常量名常量名常量名常量名= =无类型常量;无类型常量;无类型常量;无类型常量; (无类型常量是真正的常量,不允许改变其值)(无类型常量是真正的常量,不允许改变其值)(无类型常量是真正的常量,不允许改变其值)(无类型常量是真正的常量,不允许改变其值)例:例:例:例:consts=testconsts=test; (2)(2)有类型常量的说明有类型常量的说明有类型常量的说明有类型常量的说明CONSTCONST常量名:常量名:常量名:常量名: 类型类型类型类型= =类型变量;类型变量;类型变量;类型变量; (对于有类型常量,可以重新被赋值)(对于有类型常量,可以重新被赋值)(对于有类型常量,可以重新被赋值)(对于有类型常量,可以重新被赋值)TrueTrue和和和和 falsefalse是布尔值常量是布尔值常量是布尔值常量是布尔值常量整数标准常量整数标准常量整数标准常量整数标准常量 maxintmaxint,其值为标准整数(,其值为标准整数(,其值为标准整数(,其值为标准整数(integer)integer)的最大的最大的最大的最大值值值值2 21515-1-16.76.7:变量与常量说明:变量与常量说明2 2、类型说明语句:、类型说明语句:、类型说明语句:、类型说明语句:定义形式:定义形式:定义形式:定义形式: typetype类型名类型名类型名类型名= =数据类型;数据类型;数据类型;数据类型; 例如例如例如例如 typetypeindex=1.100;index=1.100;子界类型子界类型子界类型子界类型number=(one,two,three,four);number=(one,two,three,four);枚举类型枚举类型枚举类型枚举类型类型类型类型类型indexindex是用户自定义的子界类型,该类型的变量可取从是用户自定义的子界类型,该类型的变量可取从是用户自定义的子界类型,该类型的变量可取从是用户自定义的子界类型,该类型的变量可取从1 1到到到到100100区区区区间的任一整数值。类型间的任一整数值。类型间的任一整数值。类型间的任一整数值。类型numbernumber是用户的枚举类型,该类型的变量是用户的枚举类型,该类型的变量是用户的枚举类型,该类型的变量是用户的枚举类型,该类型的变量仅可取仅可取仅可取仅可取oneone,twotwo,threethree,fourfour四个标识符之一。四个标识符之一。四个标识符之一。四个标识符之一。 枚举类型只能是标识符,不能是数值或字符常数。枚举类型只能是标识符,不能是数值或字符常数。枚举类型只能是标识符,不能是数值或字符常数。枚举类型只能是标识符,不能是数值或字符常数。例以下定义是错误的:例以下定义是错误的:例以下定义是错误的:例以下定义是错误的:typetypedays=(sun,mon,tue,wed,thu,fri,sat)days=(sun,mon,tue,wed,thu,fri,sat)month=(1,2,3,4,5,6,7,8,9,10,11,12)month=(1,2,3,4,5,6,7,8,9,10,11,12)第7课: 数组与字符串数组是计算机语言常用的一种数据类数组是计算机语言常用的一种数据类型,由具有固定的相同类型的元素按型,由具有固定的相同类型的元素按一定顺序排列而成。我们先看一个例一定顺序排列而成。我们先看一个例子,看出数组的必要性:子,看出数组的必要性:程序读入程序读入50个学生的成绩,求和并输个学生的成绩,求和并输出全班的总分。出全班的总分。ProgramT7_1;Vars,x:real;i:integer;Begins:=0;Fori:=1to50dobeginReadln(x);s:=s+xEnd;Writeln(s=,s);Readln;End.此程序每次输入的成绩放在变量此程序每次输入的成绩放在变量X中,前边的成绩被后边的成绩中,前边的成绩被后边的成绩给冲掉了,只有最有一个成绩存给冲掉了,只有最有一个成绩存在变量在变量X中,如果要保留中间成中,如果要保留中间成绩,程序就比较麻烦。如果用数绩,程序就比较麻烦。如果用数组就方便多了:组就方便多了:Fori:=1to50doreadln(xi);S:=0;Fori:=1to50dos:=s+xi;7.1 数组的定义Array Array ,1, of of 例:例:typeabc=(a1,b1,c1)arr1=array1.100ofinteger;arr2=arraya.zofchar;arr3=array1.2,1.3ofreal;arr4=arraya1,.c1ofboolren;以上定义了四个数组,其中以上定义了四个数组,其中arr1是一是一个一维数组,下标从个一维数组,下标从1到到100,元,元素是整型。素是整型。arr2是一维字符数组,其下标从是一维字符数组,其下标从a到字符到字符z,有有26个元素。个元素。arr3是一个二维实型数组,有是一个二维实型数组,有2*3即即6个元素。个元素。arr4是一个一维布尔数组,其下标是是一个一维布尔数组,其下标是枚举元素枚举元素a1,b1,c1,有,有3个元素。个元素。数组类型常量的定义:数组类型常量的定义:Consta:array1.2,1.3ofinteger=(1,2,3),(2,3,2);相当于说明了数组变量相当于说明了数组变量avara:array1.2,1.3ofinteger;且给变量且给变量a赋了值。赋了值。a1,1:=1;a1,2:=2;a1,3:=3;a2,1:=2;a2,2:=3;a2,3:=2;Constm:array1.6ofinteger=(2,1,5,7,9,6)相当于定义数组元素:相当于定义数组元素:m1:=2;m2:=1;m3:=5;m4:=7;m5:=9;m6:=6.7.1.1: 一维数组一维数组是指只有一个下标的数组,适用于处理一行数据或一列数据。一维数组是指只有一个下标的数组,适用于处理一行数据或一列数据。一维数组是指只有一个下标的数组,适用于处理一行数据或一列数据。一维数组是指只有一个下标的数组,适用于处理一行数据或一列数据。一维数组的定义形式:一维数组的定义形式:一维数组的定义形式:一维数组的定义形式:TypeType类型标识符类型标识符类型标识符类型标识符=array=array下标类型下标类型下标类型下标类型ofof元素类型;元素类型;元素类型;元素类型;VarVar数组名:类型标识符;数组名:类型标识符;数组名:类型标识符;数组名:类型标识符;或:或:或:或:varvar数组名:数组名:数组名:数组名:arrayarray下标类型下标类型下标类型下标类型ofof元素类型;元素类型;元素类型;元素类型;注意:下标类型的正确选择很重要!注意:下标类型的正确选择很重要!注意:下标类型的正确选择很重要!注意:下标类型的正确选择很重要!例例例例T7_2:T7_2:对下列问题定义数组:对下列问题定义数组:对下列问题定义数组:对下列问题定义数组:(1 1)100100名学生的数学成绩。名学生的数学成绩。名学生的数学成绩。名学生的数学成绩。(2 2)表示)表示)表示)表示5050名学生的及格或不及格的情况。名学生的及格或不及格的情况。名学生的及格或不及格的情况。名学生的及格或不及格的情况。(3 3)统计周一至周五的学生出勤情况。)统计周一至周五的学生出勤情况。)统计周一至周五的学生出勤情况。)统计周一至周五的学生出勤情况。解解解解:(1)varmath:array1.100ofreal;:(1)varmath:array1.100ofreal;(2)varjg(2)varjg: array1.50ofboolean;array1.50ofboolean;(3)typeday=(mon,tue,wed,thu,fri);(3)typeday=(mon,tue,wed,thu,fri);枚举类型说明枚举类型说明枚举类型说明枚举类型说明cq=arraydayofinteger;cq=arraydayofinteger;varm:cq;varm:cq;一维数组的应用例例T7_3:利用一维数据,生成菲波利用一维数据,生成菲波那契数列的前那契数列的前50项。项。1,1,2,3,5,8,13,分析:分析:a1=1;a2=1;an=an-1+an-2(当当n3时)。时)。ProgramT7_3;Vara:array1.50ofint64;i:integer;Begina1:=1;a2:=1;fori:=3to50doai:=ai-1+ai-2;fori:=1to50dowrite(ai,);End.例例T7_4:(排序法)随机产生(排序法)随机产生8个两位整个两位整数,从小到大排序。数,从小到大排序。ProgramT7_4;Constn=8;Vara:array1.nofinteger;I,j,t:integer;Beginrandomize;初始化随机发生器初始化随机发生器fori:=1tondoai:=random(90)+10;fori:=1tondowrite(ai:4);writeln;冒泡程序排序冒泡程序排序fori:=1ton-1doforj:=i+1tondoifaiajthenbegint:=ai;ai:=aj;aj:=t;交换交换end;Fori:=1tondowrite(ai:4);Writeln;Readln;等待输入一个回车键等待输入一个回车键End.例 T7_5: 计算灯的开关状态。有N个灯放在一排,从1到N依次顺序编号。有N 个人也从1到N依次编号。1号将灯全部关闭,2号将凡是2的倍数的灯打开;3号将凡是3的倍数灯相反处理(该灯如为打开的,则将它关闭;如关闭,则将它打开)。以后的人都和3号一样,将凡是自己编号倍数的灯作相反处理。试计算第N个人操作后,哪几只灯是亮的?(0表示打开,1-表示关闭)题解:题解:设布尔数组设布尔数组a为为n只灯的状态。只灯的状态。初始时,所有的初始时,所有的灯打开,即灯打开,即a数组数组的每一个元素设的每一个元素设为为false。然后依。然后依次将每只灯序号次将每只灯序号的倍数作取反处的倍数作取反处理,由此得出的理,由此得出的a数组元素的序数数组元素的序数值即为最后的灯值即为最后的灯状态。状态。ProgramT7_5;Vark,n,I,j:integer;a:array1.100ofboolean;Beginreadln(n);fori:=1tondoai:=false;fori:=1tondobeginj:=I;whilej、=、=、=、。比较方法按比较方法按ASCII码一个字符一个字码一个字符一个字符比较。符比较。7.3.1: 字符串函数(1)字符串测长函数)字符串测长函数格式:格式:length(s)功能:求字符串功能:求字符串S的长度,结果为整型。的长度,结果为整型。(2)求子串函数求子串函数格式:格式:copy(s,n,1);功能:在功能:在S串的第串的第N位开始截取位开始截取1位字符串。位字符串。(3)查找子串函数查找子串函数格式:格式:pos(b,s);功能:求子串功能:求子串b在在s中出现的起始位置,结果为整型,若未找到显示中出现的起始位置,结果为整型,若未找到显示0。(4)插入过程)插入过程格式:格式:insert(s1,s2,i);功能:将功能:将s1插入插入s2中的第中的第i个字符位置,若结果超出个字符位置,若结果超出s2的最大长度,则超出的部分被截掉。的最大长度,则超出的部分被截掉。(5)删除过程)删除过程格式:格式:delete(s,I,n);功能:删除功能:删除s中第中第i个字符位置开始的个字符位置开始的n个字符。个字符。(6)数值转换为字符串过程)数值转换为字符串过程格式:格式:str(v,s);功能:将数值功能:将数值V转换成字符串,存放在字符串变量转换成字符串,存放在字符串变量s中。中。(7)字符串转换为数值过程)字符串转换为数值过程格式:格式:val(s,v,c);功能:将数字串功能:将数字串s转换成数值转换成数值v,变量变量C记录检测出错的第一个字符的位置,当未出错时,记录检测出错的第一个字符的位置,当未出错时,C为为0。例例7_10:统计一篇不超过统计一篇不超过500字的英语日记中数字字的英语日记中数字1、2、3出出现的次数。最后输入现的次数。最后输入!表示输入结束。表示输入结束。ProgramT7_10;Vara:array1.500ofstring;n:char;j,len.one,two,thr:integer;Beginread(n);len:=0;one:=0;two:=0;thr:=0;whilen!dobeginlen:=len+1;alen:=n;read(n)end;forj:=1tolendoforj:=1tolendobeginbeginIfaj=1thenone:=one+1;Ifaj=2thentwo:=two+1;Ifaj=3thenthr:=thr+1;End;Writeln(1degeshu=,one);Writeln(2degeshu=,two);Writeln(3degeshu=,thr);end.main例T7_11: 输入25个英文单词,将它们按词典次序排序。ProgramT7_11;Typezf=string20;定义字符串定义字符串Varm:array1.25ofzf;n:zf;i,j:integer;Beginfori:=1to25doreadln(mi);读入读入25个单词个单词Fori:=1to24doforj:=i+1to25doifmimjthenbeginn:=mi;mi:=mj;mj:=n;end;fori:=1to25dowriteln(mi);End.第8课: 函数与过程1、定义新函数、定义新函数function函数名(形式参数表)函数名(形式参数表):函数类型;:函数类型;var变量说明部分变量说明部分begin函数体函数体end;2、函数的调用、函数的调用函数名(实在参数表)函数名(实在参数表)例例T8_1:定义一个计算阶乘的函数。定义一个计算阶乘的函数。Functionf(n:integer):real;Vari:integer;s:real;Begins:=1;fori:=1tondos:=s*I;f:=s;End;思考题:思考题:思考题:思考题:(T8_2)1(T8_2)1、 求求求求P=P=(a+b)!(aa+b)!(a!+b!)+b!)的值。的值。的值。的值。(T8_3)2(T8_3)2、定义一个函数、定义一个函数、定义一个函数、定义一个函数C C(n,k)=n!/(k!*(n-k)!),n13n,k)=n!/(k!*(n-k)!),n=ythenm:=xelsem:=y;ifzmthenm:=zEnd;2. 过程的调用函数的调用不能作为单独的语句出现,而函数的调用不能作为单独的语句出现,而过程的调用必须是一个单独的语句。过程的调用必须是一个单独的语句。格式:格式:过程名(程名(实在参数表);在参数表);例例T8_4:求求s=3!+6!+8!程序如下:程序如下:ProgramT8_4;varx,s:real;procedurefa(n:integer;vart:real);vark:integer;begint:=1;Fork:=1tondot:=t*k;end;Begins:=0;fa(3,x);s:=s+x;fa(6,x);s:=s+x;fa(8,x);s:=s+x;writeln(s:8:2);End.main注释:注释:实在参数与形式参数必须一实在参数与形式参数必须一一对应,参数之间用逗号隔开。一对应,参数之间用逗号隔开。实在参数可以是常量、变量实在参数可以是常量、变量或表达式。如或表达式。如fa(6,x)与与fa(2+4,x)效果一样。效果一样。调用过程中,值形参只给过调用过程中,值形参只给过程提供数据,但不能带回结果。程提供数据,但不能带回结果。变量形参即给过程提供数据,变量形参即给过程提供数据,也将结果带回调用的程序也将结果带回调用的程序8.3: 局部变量与全程变量局部变量的作用域是它所在的过程局部变量的作用域是它所在的过程或函数。或函数。全程变量的作用域分为两种情况。全程变量的作用域分为两种情况。例例T8_5:通过以下程序的运行,体会全程通过以下程序的运行,体会全程变量的作用域。变量的作用域。(1)全程变量在过程中改变值时,新的全程变量在过程中改变值时,新的值回到主程序后有效。值回到主程序后有效。ProgramT8_5;varm:integer;m为全程变量为全程变量Proceduretest1;beginm:=100;m在过程中改变值在过程中改变值end;Beginm:=5;writeln(before,m);test1;writeln(after,m);End.运行结果:运行结果:Before5After100这个例子中这个例子中M是全程变量,它是全程变量,它在整个程序中都有意义。在整个程序中都有意义。M先先赋值为赋值为5,调用,调用test1后,后,M被被新赋值为新赋值为100,由于,由于M为全程变为全程变量,所以量,所以M值被带回主程序。值被带回主程序。(2)全程变量和局部变量同名时,全程变量的作用域是包含同名局部变量的过程或函数以外的程序部分。Program T8_6; var m: integer; m为全程变量Procedure test1; Var m:integer;局部变量,与全局变量同名 begin m:=100; m在过程中改变值 end;Begin m:=5; writeln(before,m); test1; writeln(after,m);End.运行结果:运行结果:Before5Before5After5After5 本程序中全程变本程序中全程变量和局部变量名量和局部变量名都是都是m,m,由于局部由于局部变量只在子程序变量只在子程序中有效,所以在中有效,所以在调用过程调用过程test1test1后,后,主程序中的主程序中的mm值值不变。不变。 利用全程变量,我们可以对T8_4程序进行优化,修改如下:Program T8_7;Var t: integer; 将t定义为全程变量 s:real; procedure fa(n:integer); 定义过程时不再使用变量形参 var k:integer; begin t:=1; For k:=1 to n do t:=t*k; end; Begin; s:=0; fa(3); 第一次调用过程 s:=s+t; fa(6); 第二次调用过程 s:=s+t; fa(8); 第三次调用过程 s:=s+t; writeln(s,8,2); end. main 由此可见,合理使用全程变量与局部变量可以使程序及子程序的调用变量简单。8.4:嵌套与递归一、嵌套一、嵌套一个函数或过程可能要求调用另一个一个函数或过程可能要求调用另一个函数或过程,称为函数与过程的嵌函数或过程,称为函数与过程的嵌套。套。(1)内、外层子程充不得相互交叉,)内、外层子程充不得相互交叉,内层必须完全嵌套在外层中;内层必须完全嵌套在外层中;(2)调用原则)调用原则外层程序可以调用与它相邻的内层外层程序可以调用与它相邻的内层程序,反之不行。程序,反之不行。同层程序处于后面的可以直接调用同层程序处于后面的可以直接调用前面的前面的如果如果tu1想调用想调用tu2必须作如下处理:必须作如下处理:proceduretu2;新增加的行,使新增加的行,使tu2的首部提前的首部提前forward;向前引用说明向前引用说明主程序过程SUB过程TU1过程TU2例T8_8: 已知 ,ProgramT8_8;Functionfac(x:integer):longint:Vari:integer;Beginfac:=1;fori:=1toxdofac:=fac*I;End;Functionc(a,b:integer):real;beginC:=fac(a)/fac(b)/fac(a-b);end;Beginwriteln(c(9,3)=,c(9,3):0:0);writeln(c(8,5)=,c(8,5):0:0);End.求:二、递归函数或过程调用它本身,成为递归。递函数或过程调用它本身,成为递归。递函数或过程调用它本身,成为递归。递函数或过程调用它本身,成为递归。递归在解决某些程序设计问题中是一个十归在解决某些程序设计问题中是一个十归在解决某些程序设计问题中是一个十归在解决某些程序设计问题中是一个十分有用的方法。它可以将某些看起来不分有用的方法。它可以将某些看起来不分有用的方法。它可以将某些看起来不分有用的方法。它可以将某些看起来不容易解决的问题变得容易解决,写出的容易解决的问题变得容易解决,写出的容易解决的问题变得容易解决,写出的容易解决的问题变得容易解决,写出的程序较简洁。程序较简洁。程序较简洁。程序较简洁。例例例例 T8_9:T8_9:递归计算递归计算递归计算递归计算 n!n!。分析:分析:分析:分析:n!n!可以由下列公式计算:可以由下列公式计算:可以由下列公式计算:可以由下列公式计算:n!=n!=因为(因为(因为(因为(n-1)!n-1)!乘乘乘乘n n等于等于等于等于n!,n!,所以求所以求所以求所以求n!n!的问题可的问题可的问题可的问题可以转化为求(以转化为求(以转化为求(以转化为求(n-1)!n-1)!的问题,同理可以转的问题,同理可以转的问题,同理可以转的问题,同理可以转化为(化为(化为(化为(n-2)!n-2)!的问题的问题的问题的问题,最后归结为最后归结为最后归结为最后归结为0 0!,!,!,!,而而而而0 0!已经定义!已经定义!已经定义!已经定义1 1。由。由。由。由0 0!一步步返上去!一步步返上去!一步步返上去!一步步返上去求出求出求出求出1!,2!,1!,2!,直到求出直到求出直到求出直到求出n!n!。1 n=0n(n-1)! n 0ProgramT8_9;ProgramT8_9;VarVarn:integer;n:integer;y:real;y:real;Functionfac(n:integer):real;Functionfac(n:integer):real;beginbeginifn=0thenfac:=1ifn=0thenfac:=1elsefac:=n*fac(n-1);elsefac:=n*fac(n-1);end;end;BeginBeginreadln(n);readln(n);y:=fac(n);y:=fac(n);writeln(n,!=,y:10:0);writeln(n,!=,y:10:0);End.End.本程序本程序本程序本程序N=170,N1thenIfn1thenifodd(n)thenQ(n)elseP(n);ifodd(n)thenQ(n)elseP(n);End;End;ProcedureQ(varm:integer);ProcedureQ(varm:integer);BeginBeginm:=m*3+1;write(m:3);m:=m*3+1;write(m:3);P(m);P(m);End;End;BeginBeginreadln(i);readln(i);Ifodd(i)thenQ(i)elseP(i);Ifodd(i)thenQ(i)elseP(i);Readln;Readln;end.end.例例T8_11:骨牌辅法。有骨牌辅法。有1n的一个长方的一个长方形,用一个形,用一个11、12和和13的骨牌的骨牌铺满方格。例如铺满方格。例如n=3时为时为13的方格。的方格。此时用此时用11、12和和13的骨牌辅满的骨牌辅满方格,共有四种辅法。方格,共有四种辅法。输入输入n(0n30),输出铺法总数。输出铺法总数。分析:将分析:将n格分成格分成n-x格和格和x格。格。N-1格N-2格N-2格N-3格N-3格N-3格N-3格F(1)=1F(2)=2F(3)=4F(n)=f(n-1)+f(n-2)+f(n-3)(当当n4)ProgramT8_11;Varn:integer;Functionf(i:integer):longint;Beginifiin1.2Thenf:=ielseifi=3thenf:=4elsef:=f(i-1)+f(i-2)+f(i-3);End;fBeginreadln(n);输入格子数输入格子数Writeln(f(n);计算和返回总数计算和返回总数End.main第9课 文件当一个程序需要输入大量的数据,由键盘当一个程序需要输入大量的数据,由键盘输入数据是很麻烦的。我们引入用户自输入数据是很麻烦的。我们引入用户自定义的文件,常用于人与计算机,或者定义的文件,常用于人与计算机,或者计算机与各类设备之间进行数据传递。计算机与各类设备之间进行数据传递。文件可以存储在磁盘、光盘等外部设备文件可以存储在磁盘、光盘等外部设备上,故通常称为外部文件。上,故通常称为外部文件。9.1:文件的类型文件的类型Freepascal语言中的文件可以从不同的角度语言中的文件可以从不同的角度进行分类。从文件的内容来区分,分为进行分类。从文件的内容来区分,分为两种类型:程序文件和数据文件。两种类型:程序文件和数据文件。从文件的结构来区分,一般分为文本文件和从文件的结构来区分,一般分为文本文件和随机文件两种类型。随机文件两种类型。(1)文件文件。具有行结构的字符文件。)文件文件。具有行结构的字符文件。(2)随机文件。是以二进制形式存储在磁盘)随机文件。是以二进制形式存储在磁盘上的,不具有行结构。上的,不具有行结构。目前,在青少年信息学奥林匹克竞赛(目前,在青少年信息学奥林匹克竞赛(NOI)和分区联赛(和分区联赛(NOIP)复赛中,输入数据)复赛中,输入数据和输出数据都要求采用文本文件形式。和输出数据都要求采用文本文件形式。9.2:文本文件的概念文本文件的概念一、文件名一、文件名Freepascal语言规定文件名由语言规定文件名由主文件名和扩展名两部分组成,主文件名和扩展名两部分组成,中间用中间用“.”分隔。分隔。主文件名主文件名.扩展名展名主文件名由主文件名由13个字符组成,个字符组成,扩展名由最多扩展名由最多3个字符。扩展名个字符。扩展名可以省略。在信息学竞赛中,常可以省略。在信息学竞赛中,常用用.in作为输入文件的扩展名,作为输入文件的扩展名,.out作为输出文件的扩展名。作为输出文件的扩展名。二、文件的指针二、文件的指针文本文件是顺序存取文件。对于文本文件是顺序存取文件。对于某个文件只能从中读取或写入数某个文件只能从中读取或写入数据,不能同时即读又写。为方便据,不能同时即读又写。为方便读取,对每个文件设置一个指针,读取,对每个文件设置一个指针,指向读写的位置。指向读写的位置。9.3: 文件的基本操作1、链接文件、链接文件Assign(文件变量,文件变量,文件名文件名););例如:例如:assign(t,d:fpf1.dat);在在freepascal语言中链接文件是建立、打开文件进行读写数据的关键步骤。语言中链接文件是建立、打开文件进行读写数据的关键步骤。2、建立文件、建立文件(1)Program程序名(程序名(input,output,文件名);文件名);(2)var说明文件变量的类型。说明文件变量的类型。文件变量:文件变量:text;(3)assign(文件变量,文件变量,文件名文件名););(4)rewrite(文件变量);(文件变量);对文件初始化,使该文件为空白文件,准备写入数据。文件指针指向文件之首。对文件初始化,使该文件为空白文件,准备写入数据。文件指针指向文件之首。(5)write(文件变量,变量);文件变量,变量);作用是将变量的值写入指针所指的文件变量的当前位置中。作用是将变量的值写入指针所指的文件变量的当前位置中。例T9_1: 将1,2,3,,9,10这10 个数写入到文本文件f1.dat中。要求相邻两数用一个空格分隔。ProgramT9_1(input,output,f1);Vart:text;i:integer;Beginassign(t,f1.dat);rewrite(t);fori:=1to10dobeginwrite(t,i);write(t,);end;Colse(t);End.例例T9_2:产生产生6个个0到到100之间的随机整之间的随机整数,写入到文本文件数,写入到文本文件sj.in中。要求每中。要求每行行3个数,两数之间用一个空格分隔。个数,两数之间用一个空格分隔。ProgramT9_2;Varf:text;I,x:integer;Beginrandomize;assign(f,sj.in);rewrite(f);Fori:=1to6dobeginx:=random(100);write(f,x);ifImod3=0thenwriteln(f)elsewrite(f,);End;close(f);End.3、打开文件当程序需要对文件中的数据进行读取操作当程序需要对文件中的数据进行读取操作之前,要打开保存在磁盘上的文件。之前,要打开保存在磁盘上的文件。打开文件读取数据的操作步骤为:打开文件读取数据的操作步骤为:(1)program程序名;程序名;(2)var文件变量:文件变量:text;(3)assign(文件变量,文件变量,文件名文件名););(4)reset(文件变量);文件变量);reset语句的作用将文件指针指向文件语句的作用将文件指针指向文件之首,准备从文件的第一个分量开始之首,准备从文件的第一个分量开始读数。读数。(5)用)用read语句由文件中读取数据。语句由文件中读取数据。read(文件变量,变量);文件变量,变量);例例T9_3:从例从例T9_1建立的文建立的文本文件本文件f1.dat中读取数据,中读取数据,并在显示器上输出数据。计并在显示器上输出数据。计算这算这10个数据的和并输出。个数据的和并输出。ProgramT9_3;Vart:text;I,x,s:integer;Beginassign(t,f1.dat);reset(t);s:=0;fori;:=1to10dobeginread(t,x);write(x,);s:=s+x;end;4、关闭文件、关闭文件: Close (文件变量);(文件变量); 5、文件修改、文件修改: append(文件变量);(文件变量);如果需要,在原有的文本文件最后写入新数据,如果需要,在原有的文本文件最后写入新数据,append语句可以完成语句可以完成这项任务。这项任务。 6、读取数据:、读取数据: read(文件变量,变量表);(文件变量,变量表); readln(文件变量,变量表);(文件变量,变量表); 这二个语句的执行结果是将文件中的数据依次读入到变量表中的各个这二个语句的执行结果是将文件中的数据依次读入到变量表中的各个变量之中。变量之中。Read语句与语句与readln语句的区另主要表现在对程序中下语句的区另主要表现在对程序中下一个输入语句的执行上,当使用一个输入语句的执行上,当使用read语句时,程序中的下一个语句时,程序中的下一个read语句执行时,将在本次指针位置后读入数据;如果使用语句执行时,将在本次指针位置后读入数据;如果使用readln语句,则执行下一个语句,则执行下一个read语句时,将换行从下一行的行首语句时,将换行从下一行的行首位置向后读入数据。位置向后读入数据。 如果通过键盘输入数据的如果通过键盘输入数据的read语句写完整的话,其格式为:语句写完整的话,其格式为: read(input,变量表);其中变量表);其中input可以省略可以省略,写成:写成: read (变量表)变量表);7、写入数据:、写入数据:write(文件变量,数据表);文件变量,数据表);或:或:writeln(文件变量,数据表);文件变量,数据表);区别在于使用区别在于使用write语句时,程序中下一个语句时,程序中下一个Write将在本次指针位将在本次指针位置向后输出数据;如果使用置向后输出数据;如果使用writeln语句时,将换行从下一行的语句时,将换行从下一行的行首位置向后输出数据。行首位置向后输出数据。其中,文件变量同前所述,数据表是一个表达式表,可以有多个其中,文件变量同前所述,数据表是一个表达式表,可以有多个表达式,不同表达式之间用表达式,不同表达式之间用“,”分隔。分隔。例如:例如:write(t,x,y);将表达式将表达式x,y的值依次写入到文件的值依次写入到文件t中。中。如果要在显示器上输出运行结果,其格式为:如果要在显示器上输出运行结果,其格式为:write(output,数据表);数据表);其中的其中的output表示系统的标准输出设备,即显示器,故可省略。表示系统的标准输出设备,即显示器,故可省略。设设x为实数为实数123.456,在不同语句设置中执行情况如下:,在不同语句设置中执行情况如下:执行执行writeln(t,x);语句时,将在文件变量语句时,将在文件变量t链接的文本文件中写入:链接的文本文件中写入:1.2345600000E+02执行执行writeln(t,x:10:4);语句时,在文件中写入:语句时,在文件中写入:123.4560执行执行writeln(t,x:10:2);语句时,在文件中写入:语句时,在文件中写入:123.469.4:文本文件的操作函数1、eoln函数函数格式:格式:eoln(文件变文件变量)量)功能:检测文本文件功能:检测文本文件当前行是否结束。当前行是否结束。如果文件当前指如果文件当前指针的下一个字符针的下一个字符为行结束或文件为行结束或文件结束符,函数返结束符,函数返回值为回值为true,否则否则为为false。2、eof函数函数格式:格式:eof(文件变量)文件变量)功能:检测文件是否功能:检测文件是否结束。若是则为结束。若是则为true,否则为否则为false。例例T9_4:在例在例T9_2建立的文本文件建立的文本文件sj.in中存有中存有2组组数,每组数,每组3个整数,求每组数的和。个整数,求每组数的和。输入格式:文本文件输入格式:文本文件sj.in存有存有6个数据,分为个数据,分为2行,行,每行每行3个数,有空格分隔。个数,有空格分隔。输出格式:结果输出到文本文件输出格式:结果输出到文本文件h.out,每行每行1个数。个数。ProgramT9_4;Vart,m:text;I,x,y,z,w:integer;Beginassign(t,sj.in);reset(t);将指针指向将指针指向t文件首文件首assign(m,h.out);rewrite(m);使使m为空白文件为空白文件whilenoteof(t)do当当sj文件未结束时执行循环文件未结束时执行循环Beginreadln(t,x,y,z);w:=x+y+z;writeln(m,w);End;Close(t);Close(m);End.文本文件的基本操作步骤文本文件的基本操作步骤操作步骤操作步骤语句语句功能功能定义文件定义文件变量类型变量类型文件变量:文件变量:text说明文件变量类型说明文件变量类型链接文件链接文件Assign(文件变量,文件名);文件变量,文件名);链接程序中的文件变量和要访问的磁盘链接程序中的文件变量和要访问的磁盘文件文件建立文件建立文件Rewrite(文件变量);文件变量);初始化文件,使该文件为空白文件,准初始化文件,使该文件为空白文件,准备写入数据备写入数据打开文件打开文件Reset(文件变量);文件变量);初始化文件,准备读取数据初始化文件,准备读取数据关闭文件关闭文件Close(文件变量文件变量);关闭文件,结束文件变量与磁盘文件的关闭文件,结束文件变量与磁盘文件的链接链接文件修改文件修改Append(文件变量文件变量);在原有的文本文件最后写入新数据在原有的文本文件最后写入新数据读取数据读取数据Read(文件变量文件变量,变量);变量);由文件中读取数据由文件中读取数据写入数据写入数据Write(文件变量文件变量);向文件写入数据向文件写入数据第10课 集合和记录10.1.1、集合类型 集合是具有共同性质的一组数据构成的整体,集合中的数据叫做集合元素,简称元素。例如10以内的质数构成一个集合,它包括2、3、5、7共4个元素,PASCAL中用2,3,5,7表示。不包括任何元素的集合叫做空集,用表示。 集合具有如下性质:(1)元素唯一性;(2)元素无序性。 PASCAL语言提供一种自定义数据类型-集合类型,可以用来表示集合。但有以下限制(区别于纯数学理论的集合概念):集合元素必须是有序类型的数据(数学集合元素可以是实数)。集合的元素数目不能超过256个(数学集合元素个数可以是任意个)。10.1.2 集合的定义定义集合类型格式:定义集合类型格式:定义集合类型格式:定义集合类型格式: typetype集合类型名集合类型名集合类型名集合类型名=setof=setof基类型;基类型;基类型;基类型;说明:说明:说明:说明: 类型名应该是一个合法的标识符;基类型名应该是一个合法的标识符;基类型名应该是一个合法的标识符;基类型名应该是一个合法的标识符;基类型是集合中元素的类型,它必须类型是集合中元素的类型,它必须类型是集合中元素的类型,它必须类型是集合中元素的类型,它必须是有序的类型,元素的序号范围必是有序的类型,元素的序号范围必是有序的类型,元素的序号范围必是有序的类型,元素的序号范围必须在须在须在须在0 0到到到到255255之间。之间。之间。之间。定义集合变量格式:定义集合变量格式:定义集合变量格式:定义集合变量格式: varvar变量名:集合类型名;变量名:集合类型名;变量名:集合类型名;变量名:集合类型名;这样定义的变量就是一个集合变量,在这样定义的变量就是一个集合变量,在这样定义的变量就是一个集合变量,在这样定义的变量就是一个集合变量,在程序中表示一个集合。程序中表示一个集合。程序中表示一个集合。程序中表示一个集合。允许集合类型描述和变量定义合并在一允许集合类型描述和变量定义合并在一允许集合类型描述和变量定义合并在一允许集合类型描述和变量定义合并在一起,共格式为:起,共格式为:起,共格式为:起,共格式为: varvar变量名:变量名:变量名:变量名:setofsetof基类型;基类型;基类型;基类型;例:下面集合定义是正确的:例:下面集合定义是正确的:例:下面集合定义是正确的:例:下面集合定义是正确的: typetypeT1=setof1.5;T1=setof1.5;T2=setofchar;T2=setofchar;T3=setof(while,read,blue);T3=setof(while,read,blue);下面集合定义是错误的:下面集合定义是错误的:下面集合定义是错误的:下面集合定义是错误的: typetypeT1=setofinteger;T1=setofinteger;T2=setof-30.-20;T2=setof-30.-20;T3=setofreal;T3=setofreal;T4=setof200.300;T4=setof200.300;10.1.3 集合的操作(1)赋值运算:)赋值运算:vara:setof0.255;begina;=2,3,5,7;(2)集合元素不能用集合元素不能用read和和wrte语句直接输语句直接输入和输出。如果需要输入和输出集合元入和输出。如果需要输入和输出集合元素,必须借助集合的运算来实现。素,必须借助集合的运算来实现。ProgramT10_1;vars:setof0.255;i:integer;a,b:0.255;begins:=;fori:=1to10dobeginread(a);s:=s+a;end;Forb:=0to255doifbinsthenwrite(b,);end.(3)元素与集合可以进行元素与集合可以进行属于属于运算。运算。例:例:1in1,2,3为为true,1in2,3,4为为fluse.in相当于数学里集合运算符相当于数学里集合运算符。(4)集合之间可以进行集合之间可以进行并并、差差、交交三种集合运算。三种集合运算。并运算符为并运算符为“+”,所得集合叫做,所得集合叫做并集。例并集。例1,2+1,2,3,4=1,2,3,4差运算符为差运算符为“-”,所得集合为属于,所得集合为属于A且不属于且不属于B的全部元素。的全部元素。例:例:1,2,3-2=1,31,2,3-4=1,2,3交运算符为交运算符为“*”,其元素为属于,其元素为属于A且属于且属于B的全部元素。的全部元素。例:例:1,2,3*2,3,4=2,31,2,3*4,5=(空集)(空集)(5)集合之间可以进行)集合之间可以进行“相等相等”和和“包含包含”两种运算,运算结果为布尔两种运算,运算结果为布尔值。值。相等(运算符为相等(运算符为“=”)表达式表达式1,2=1,2为为true,表达式表达式1,3=1,2为为fluse.包含(运算符为包含(运算符为“=”和和“=”表达式表达式1,2,3=1,2为为true,表达式表达式1,3=1,2,3为为fluse.相当于数学中集合运算相当于数学中集合运算“”、和、和“”。例例10_2:设集合设集合a=2,3,5,7,8,b=1.5,c=3,4,5,7,9,求求a*b-c.解:解:a*b=2,3,5a*b-c=2,3,5-3,4,5,7,9=2例例11_3:用筛选法求用筛选法求200以内的质数。以内的质数。分析:筛选法的基本思想是:分析:筛选法的基本思想是:(1)设立一个)设立一个2到到n之间的全体整数之间的全体整数的集合的集合S;(2)设立一个集合设立一个集合S1,用于存放筛,用于存放筛选出的质数;选出的质数; (3)i从集合从集合S中最小的质数中最小的质数2开始;开始;(4)先将)先将i添加到添加到S1中,然后将中,然后将i的的所有整数倍(包括所有整数倍(包括i本身)从本身)从s中删除,中删除,此时剩下的最小元素此时剩下的最小元素x一定是与一定是与i紧邻紧邻的质数;的质数;(5)通过循环累加的方法,将)通过循环累加的方法,将i更新更新为为x;(6)重复执行第)重复执行第4、5步,直到步,直到S中己中己没有元素为止。此时没有元素为止。此时S1中存放的就是中存放的就是筛选出来的筛选出来的2到到n之间的全体质数。之间的全体质数。Program T10_3; var s,s1:set of 2.200; i,j:2.200; begin s:=2.200; s最初是2到200之间的全体整数 s1:=; i:=2; repeat if i in s then begin s1:=s1+i; for j:=i to 200 do if j mod i =0 then s:= s-j; end; i:= i +1;Until s= ;For i:=2 to 200 do if i in s1 then write(i:4);End. 10.2 记 录如图书馆的图书卡片:如图书馆的图书卡片:书名:书名:PASCAL语言语言作者:张文双、吴树娟作者:张文双、吴树娟定价:定价:30.00元元页数:页数:242页页为了表示这样的数据,为了表示这样的数据,可以使用可以使用PASCAL语言语言提供的记录类型。记提供的记录类型。记录(录(record)是由一组是由一组不同类型的数据项构不同类型的数据项构成,记录中的数据项成,记录中的数据项叫做记录的域(叫做记录的域(field)。域也叫做字段。域也叫做字段。10.2.1记录的定义记录的定义1、记录类型的定义、记录类型的定义type类型名类型名=record域名域名1:类型:类型1;域名域名2:类型:类型2;域名域名3:类型:类型3;End;2、记录变量的定义、记录变量的定义var变量名:记录类型名;变量名:记录类型名;也可以将类型描述也可以将类型描述与变量定义合并一与变量定义合并一起,其格式为:起,其格式为:var变量名:变量名:record域名域名1:类型:类型1;域名域名2:类型:类型2;域名域名3:类型:类型3;end;10.2.2 记录的运用例例10_4:编写一个通讯录,从键盘接收编写一个通讯录,从键盘接收10个人的资料,个人的资料,然后显示出来。然后显示出来。程序为:程序为:programT10_4;constn=10;typeTDirrec=recordnum:integer;name:string10;Tele:string20;addr:string50;end;TDir=array1.nofTDirrec;序号姓名电话号码家庭地址1张三*2李四*3王五*4赵六*Var Dir:TDir; i :integer;Begin for i :=1 to n do begin Diri.num:=i; write(input name:); readln(Diri.name); write(input telephone:); readln(Diri.Tele); write(input address:); readln(Diri.addr); end; for i:=1 to n do begin writeln(No.,Diri.num); writeln(Diri.name); writeln(Diri.Tele); writeln(Diri.addr); end; End. 10.2.3 开域语句(with语句)在程序中,我们经常集中使用同一个记录的在程序中,我们经常集中使用同一个记录的各个域。例如:各个域。例如:card1.Title:=PASCAL语言语言;card1.Author:=张文双、吴树娟张文双、吴树娟;card1.Price:=30.00;card1.Page:=242;这时,就要将记录的名字重复书写多次。这时,就要将记录的名字重复书写多次。PASCAL语言提供了语言提供了“开域语句开域语句”。格式如下:格式如下:with记录记录do语句;语句;其中,其中,with后面指定了一个确定的记录,后面指定了一个确定的记录,do后面的语句可以直接引用该记录中的域,后面的语句可以直接引用该记录中的域,无须再指明记录。无须再指明记录。do后面的语句可以是简后面的语句可以是简单语句,也可以是复合语句。单语句,也可以是复合语句。上述语句改写为:上述语句改写为:withcard1dobeginTitle:=PASCAL语言语言;Author:=张文双、吴树娟张文双、吴树娟;Price:=30.00;Page:=242;End;第11课 指针数据结构分为两类:数据结构分为两类:-静态数据结构和动态数据静态数据结构和动态数据结构。结构。前面介绍的数组、记录和集前面介绍的数组、记录和集合都属于静态数据结构。合都属于静态数据结构。其特点是:变量定义后,其特点是:变量定义后,PASCAL系统自动为变量系统自动为变量分配内存空间。当需要分配内存空间。当需要对己赋值数组的某个位对己赋值数组的某个位置插入置插入(或删除或删除)一个数据一个数据时,会造成众多数据的时,会造成众多数据的后移(或)前移,算法后移(或)前移,算法会很复杂。会很复杂。为了弥补静态数据结构的上为了弥补静态数据结构的上述不足,述不足,PASCAL系统引系统引入指针变量。入指针变量。12.1指针变量指针变量例如:变量例如:变量P是一个存储地址的变量,其是一个存储地址的变量,其自身的地址是自身的地址是100;变量;变量q是一个存储整是一个存储整数数30的变量,其地址是的变量,其地址是150,从,从P的内部的内部画一个箭头指向画一个箭头指向q,如图所示:,如图所示:100150pq30P称为指针变量,指针变量存放的是变量称为指针变量,指针变量存放的是变量q地址,通过这个地址可以找到地址,通过这个地址可以找到q中的数中的数据据30。指针箭头所指变量存储的数据类型。指针箭头所指变量存储的数据类型称为指针变量的基类型。指针变量的基类称为指针变量的基类型。指针变量的基类型可以是除文件类型以外的其他数据类型。型可以是除文件类型以外的其他数据类型。11.1.1 指针变量的定义格式格式1:type指针类型标识符指针类型标识符=基类型标识符;基类型标识符;var指针变量名:指针类型标识符;指针变量名:指针类型标识符;例如:例如:typeP=integer;varp1,p2:P;先定义了一个指针变量先定义了一个指针变量P,指向整型变,指向整型变量。然后定义了两个类型的变量量。然后定义了两个类型的变量P1和和P2,它们的值分别是存储单元的,它们的值分别是存储单元的地址,而存储单元恰好能存放一个地址,而存储单元恰好能存放一个整型数据。整型数据。格式格式2:Var指针变量名:指针变量名:基类型标识符;基类型标识符;例:上例也可表示成:例:上例也可表示成:varp1,p2:integer;11.1. 2 指针变量的基本操作1、新建存储地址、新建存储地址格式:格式:new(指针变量);指针变量);例如:例如:new(p);功能:分配一个存放数据的存储单功能:分配一个存放数据的存储单元,并把该存储单元的地址赋给元,并把该存储单元的地址赋给指针变量指针变量p。注意:一个指针变量只能存放一个注意:一个指针变量只能存放一个地址。如果程序再次执行地址。如果程序再次执行new(p)语句,将在内存中开辟另外一个语句,将在内存中开辟另外一个新的存储单元,并将其地址放在新的存储单元,并将其地址放在p中,从而丢失了原存储单元的中,从而丢失了原存储单元的地址。地址。2、释放存储单元、释放存储单元为了节省内存空间,系统通过标准为了节省内存空间,系统通过标准过程过程dispose释放不再使用的存释放不再使用的存储单元。储单元。格式:格式:dispose(指针变量);指针变量);例如:例如:dispose(p);功能:释放指针变量功能:释放指针变量p所指向的存所指向的存储单元,使指针变量的值取储单元,使指针变量的值取nil(空指针值),即指针不指(空指针值),即指针不指向任何变量。向任何变量。3. 指针变量的引用利用利用new过程可以将一个存储过程可以将一个存储单元的地址值赋给一个指针单元的地址值赋给一个指针变量,通常我们并不需要了变量,通常我们并不需要了解这个地址值,而真正关心解这个地址值,而真正关心的上该指针变量所指向的存的上该指针变量所指向的存储单元的数据。储单元的数据。Pascal用用q来表示指针变量来表示指针变量q所指所指向的存储单元的内容。对于向的存储单元的内容。对于q和和q我们都可以用赋值语句我们都可以用赋值语句赋值,只是效果大不相同。赋值,只是效果大不相同。前者赋给的是地址值,可以前者赋给的是地址值,可以改变改变q的指向;后者赋给的是的指向;后者赋给的是数据内容,改变的是数据内容,改变的是q所指向所指向的存储单元的内容。的存储单元的内容。格式:(指针变量)格式:(指针变量):=数据;数据;例如:例如:q:=2;功能:在指针变量功能:在指针变量q所指向的存所指向的存储单元中,存储的数据是储单元中,存储的数据是2。例:执行语句例:执行语句p:=q;是将是将q的值的值(q所指向存储单元的地址)所指向存储单元的地址)赋给变量赋给变量p,这样这样p与与q都同时指都同时指向向q所指向的存储单元。所指向的存储单元。例:执行语句例:执行语句p:=q;是将是将q所指所指向的存储单元的数据存放到向的存储单元的数据存放到p所指向的存储单元中。这样所指向的存储单元中。这样p和和q虽然指向不同的存储单元,虽然指向不同的存储单元,但两个存储单元的数据是相同但两个存储单元的数据是相同的。的。11.2 链表设有一批整数(设有一批整数(66,92,49,86,75,),如何存放呢?当然我们可以选择学过),如何存放呢?当然我们可以选择学过的数组类型。但是,如果事先不能确定整数的个数,就要定义一个中够大的数的数组类型。但是,如果事先不能确定整数的个数,就要定义一个中够大的数组,这种做法处理问题,就会浪费内存,这就是静态存储结构的局限性。组,这种做法处理问题,就会浪费内存,这就是静态存储结构的局限性。我们利用前面介绍的指针变量可以构造一个简单而实用的动态数据结构我们利用前面介绍的指针变量可以构造一个简单而实用的动态数据结构-链表。链表。如图所示是一个简单链表结构示意图:如图所示是一个简单链表结构示意图:head20201324336028955102202066924986751324336028955102nil在这个链表中,每个框表示链表的一个元素,称为结点。框顶端的数字表示该存储在这个链表中,每个框表示链表的一个元素,称为结点。框顶端的数字表示该存储单元的地址(这里的地址是假设的)。第单元的地址(这里的地址是假设的)。第1个结点称为表头个结点称为表头head,框内的数字,框内的数字202表示表头的地址。后面的每个结点有两个域。第一个域是数字域(存放数据),第表示表头的地址。后面的每个结点有两个域。第一个域是数字域(存放数据),第二个域是指针域(存放下一个结点的地址)。表尾结点的指针域值为空(二个域是指针域(存放下一个结点的地址)。表尾结点的指针域值为空(nil),),用来表示表的结束。用来表示表的结束。指向表头的指针(指向表头的指针(head)称为头指针,当头指针称为头指针,当头指针head为为nil时,称为空链表。时,称为空链表。链表作表头与表尾外,每一个结点都有一个直接的前趋结点和一个后继结点。相邻链表作表头与表尾外,每一个结点都有一个直接的前趋结点和一个后继结点。相邻结点的地址可以互不连续,它们靠指针域相互联系。结点的地址可以互不连续,它们靠指针域相互联系。11.2.1 链表的定义要定义一个链表,每个结点要定要定义一个链表,每个结点要定义成记录型,而且其中有一个义成记录型,而且其中有一个域为指针。例如:域为指针。例如:typept=node;node=recorddata:integer;next:ptend;varp1,p2:pt;说明:上面定义了两个指针变量:说明:上面定义了两个指针变量:p1和和p2,其基类型为其基类型为node。Node是一个自定义记录类型,是一个自定义记录类型,有两个域:数据域有两个域:数据域data,类型为类型为整型;指针域为整型;指针域为next,类型为,类型为pt型。在这种定义中,指针中型。在这种定义中,指针中有记录,记录中有指针,形成有记录,记录中有指针,形成一种递归关系。一种递归关系。如果在上述结点定义后,程序中出现如果在上述结点定义后,程序中出现如下语句:如下语句:New(p1);new(p2);新建两个存储单元新建两个存储单元p1.data:=100;指针变量指针变量p1所指的存储单元的数据所指的存储单元的数据域赋值为域赋值为100P1.next:=p2;将指针变量将指针变量p2所指存储单元的地所指存储单元的地址赋值给址赋值给p1的指针域的指针域这样就将两个独立的存储单元通过指这样就将两个独立的存储单元通过指针域连接起来,此时链表中这两个结针域连接起来,此时链表中这两个结点的状态如图所示:点的状态如图所示:201 412p1p210041211.2.2 建立链表一个链表的建立步骤为:一个链表的建立步骤为:1、申请新结点;、申请新结点;2、为结点的数据域和指、为结点的数据域和指针域赋值;针域赋值;3、将结点链接到表中的、将结点链接到表中的某一位置。某一位置。例例12_1:建立一个有建立一个有10个个结点的链表,最后输结点的链表,最后输出该链表。出该链表。分析:首先应定义指针类分析:首先应定义指针类型、结点类型和指针型、结点类型和指针变量。从表头开始建变量。从表头开始建立链表。先用指针立链表。先用指针p1构造头结点,为头结构造头结点,为头结点申请存储单元后,点申请存储单元后,为其数据域赋值,令为其数据域赋值,令头指针头指针h指向结点的指指向结点的指针域。针域。Program T11_1; type pt=node; node=record data:string5; next:pt end; var p1,p2,h:pt; i:integer; Begin new(p1); writeln(input data1:); readln(p1.data); h:=p1;For i:=1 to 9 do begin new(p2); writeln(input data:); readln(p2.data); p1.next=p2; p1:=p2; end; p2.next:=nil; p1:=h; while p1nil do begin write(p1.data,); p1:=p1.next end;End.链表的举例1、队(先进先出)。此种链表按照输入数据的顺序建立。先输入位于表、队(先进先出)。此种链表按照输入数据的顺序建立。先输入位于表首,后输入的数据位于其后。输出时按从表首到表尾的顺序进行,正首,后输入的数据位于其后。输出时按从表首到表尾的顺序进行,正好与输入顺序一致,所以称为先进先出链表。好与输入顺序一致,所以称为先进先出链表。heada1a2an-2an-1an2、栈(先进后出)。此种表后输入的数据放在先一个输入的数据之前。、栈(先进后出)。此种表后输入的数据放在先一个输入的数据之前。这样,最先输入的数据位于表尾,最后输入的数据位于表首。输出时这样,最先输入的数据位于表尾,最后输入的数据位于表首。输出时按从表首与表尾的顺序正好与输入顺序相反,所以称先进后出表。按从表首与表尾的顺序正好与输入顺序相反,所以称先进后出表。headanan-1a3a2a1hilhil例T11_2: 读入一组非负整数,以负数为输入结束标志,建立先进先出的链表并输出。(建队)ProgramT11_2;typept=node;node=recorddata:integer;next:ptend;varh,p1,p2:pt;x:integer;beginh:=nil;read(x);whilex=0dobeginifh=nilthenbeginnew(p1);p1.data:=x;p1.next:=nil;p2:=p1;指针指针p2指向当前链表(即指向当前链表(即p1所指)的尾结点所指)的尾结点h:=p1指针指针h指向当前链表的指向当前链表的尾结点尾结点endelsebeginnew(p1);p1.data:=x;p1.next:=nil;p2.next:=p1;p2:=p1end;read(x);end;p1:=h;whilep1nildobeginwrite(p1.data:5);p1:=p1.nextend;writeln;End.例T11_3: 读入一组实数,以负数为输入结束标志,建立先进后出的链表并输出。(建栈)ProgramT11_3;typept=node;node=recorddata:real;next:ptend;varh,p:pt;x:real;beginp:=nil;初始准备初始准备read(x);whilex=0dobeginnew(h);h.data:=x;h.next:=p;链接到当前链表的表链接到当前链表的表首首p:=h;调整指针调整指针p指向当前链指向当前链表的表首表的表首read(x);end;输出链表输出链表whilepnildobeginwrite(p.data:5:1);p:=p.nextend;writeln;End.hphilx11.2.3 插入结点要往数组里插入一个元素比较困难,首先要确定插入位置,然后将从该位置要往数组里插入一个元素比较困难,首先要确定插入位置,然后将从该位置以后的所有元素依次后移一个位置,以便空出一个位置插入新元素。而采用链表以后的所有元素依次后移一个位置,以便空出一个位置插入新元素。而采用链表插入比较简单。在确定插入位置后,不必移动链表中的元素,只需给相应的指针插入比较简单。在确定插入位置后,不必移动链表中的元素,只需给相应的指针重新赋值就可以了。我们分三种情况进行分析:重新赋值就可以了。我们分三种情况进行分析:1、插入表头:、插入表头:hhilhilhqq.next:=h;h:=q;q为表头,所以调整为表头,所以调整头指针头指针h,指向指向q2、插入表中:、插入表中:p1.next:=q;q.next:=p2;p1p2hilhp1p2hqq.next:=h;h:=q;q为表头,所以调整为表头,所以调整头指针头指针h,指向指向qq3、插入表尾插入表尾只需执插入表尾只需执行下列语句:行下列语句:p2.next:=q;q.next:=nil;hhilhhilp2q例例T11_4:在一个有序链表中插入一个新的结在一个有序链表中插入一个新的结点,仍为有序链表。点,仍为有序链表。Procedureinsert(x:real;varh:point);Varq,p1,p2:point;Beginnew(q);q.data:=x;ifxp2.data)and(p2.nextnil)dobeginp1:=p2;p2:=p2.nextend;Ifx=p2.datathenbeginp1.next:=q;q.next:=p2;end;elsebeginp2.next:=q;qnext:=nilendendEnd;11.2.4 删除一个结点要从一个链表中删除一要从一个链表中删除一个结点,首先在链表中个结点,首先在链表中找到该结点,然后将其找到该结点,然后将其前趋结点的指针域指向前趋结点的指针域指向其后继结点即可。如图其后继结点即可。如图要删除要删除p2结点,只需执结点,只需执行语句:行语句:p1.next:=p2.next;就可以了。就可以了。p1p2p1p2被删除结点所占用的存储被删除结点所占用的存储空间,可以通过空间,可以通过dispose(p2)释放。释放。例T11_5: 编写一个过程,将链表中值为x的第一个结点删除。分析:有三种情况存在,头结点数据值为分析:有三种情况存在,头结点数据值为x;除头结点外的某个结点数据域的值为除头结点外的某个结点数据域的值为x;没有数据域值为没有数据域值为x的结点。的结点。算法分两步完成:查找、删除。算法分两步完成:查找、删除。(1)查找。从头开始遍历表,直到找到目标或到达表尾为止。)查找。从头开始遍历表,直到找到目标或到达表尾为止。(2)删除。如果目标找到,将其删除,设置标志()删除。如果目标找到,将其删除,设置标志(delete)为真,否则设置为假。为真,否则设置为假。Proceduredelete(x:real;varh:pointer;vardelete:boolean);删除结点的过程删除结点的过程Varp1,p2:pointer;beginp2:=h;while(p2.datax)and(p2.nextnil)do遍历表直到找到目标或到达表尾遍历表直到找到目标或到达表尾beginp1:=p2;p2:=p2.nextend;Ifp2.data=xthenbegindelete:=true;ifp2=hthenh:=h.nextelsep1.next:=p2.nextendelsedelete:=flaseend;11.2.5 循环链表前面所介绍的链表尾结点的指针域为空(前面所介绍的链表尾结点的指针域为空(nil),称为单向链表。如果让表尾结),称为单向链表。如果让表尾结点的指针域指向表头结点,就使整个链表形成一个环形。这种首尾相接的链表称为点的指针域指向表头结点,就使整个链表形成一个环形。这种首尾相接的链表称为循环链表。在循环链表中,从任意一个结点出发都可以找到表中的其他结点。如图循环链表。在循环链表中,从任意一个结点出发都可以找到表中的其他结点。如图所示就是一个单循环链表。所示就是一个单循环链表。h单循环链表的操作和单向链表的基本一致,只是在循环终止条件上有所不同:单循环链表的操作和单向链表的基本一致,只是在循环终止条件上有所不同:前者是指针变量再一次指向表头结点;后者是指针变量的指针域为空(前者是指针变量再一次指向表头结点;后者是指针变量的指针域为空(nil)。例例T11_6:(约瑟夫问题)旅行社要从(约瑟夫问题)旅行社要从n名旅客名旅客中选出一名幸运旅客,为他提供免费服务。方中选出一名幸运旅客,为他提供免费服务。方法是,大家站成一圈,然后指定一个数法是,大家站成一圈,然后指定一个数m。从。从第第1个人开始报数个人开始报数1,2,3,报到,报到m的人的人退出圈外,然后从下一个人开始重新从退出圈外,然后从下一个人开始重新从1报数,报数,重复这个过程,直到只剩下一个人时,此人就重复这个过程,直到只剩下一个人时,此人就是幸运之星。请由键盘输入是幸运之星。请由键盘输入n,m,输出退出圈输出退出圈外客人的序号,选出幸运之星。外客人的序号,选出幸运之星。分析:因为分析:因为n个人是围成一个人是围成一个圈的,所以第个圈的,所以第n个人后面个人后面的应该是第的应该是第1个人,这就形个人,这就形成了一个环。利用单循环成了一个环。利用单循环链表求解,将客人的编号链表求解,将客人的编号作为结点数据域的值,将作为结点数据域的值,将指向下一个人的地址作为指向下一个人的地址作为结点的指针域值。结点的指针域值。ProgramT11_6;Typept=node;node=recorddata:integer;next:ptEnd;Varm,n,i:integer;p1,p2,h:pt;Beginwrite(inputn,m:);readln(n,m);new(p1);p1.data:=1;h:=p1;Fori:=2tondobeginnew(p2);p2.data:=i;结点数据域赋值结点数据域赋值p1.next:=p2;结点指针域赋值结点指针域赋值p1:=p2End;P1.next:=h;链表首尾相接链表首尾相接i:=1;P1:=h;Repeatp2:=p1.next;i:=i+1;ifimodm=0thenbeginp1.next:=p2.next;删除结点删除结点write(p2.data:8);退出客人的序号退出客人的序号p2.next:=nil;dispose(p2)endelsep1:=p2Untilp2.next=p2;Writeln;Writeln(theluckstarisno:,p2.data)输出幸运之星输出幸运之星End.解法二:用数组方法分析:算法步骤如下:分析:算法步骤如下:1、由于对于每个人只有出圈或不出圈两种状态,因此设置标志数组存放游戏过程中、由于对于每个人只有出圈或不出圈两种状态,因此设置标志数组存放游戏过程中每个人的状态。不妨用每个人的状态。不妨用1表示出圈,表示出圈,0表示不出圈。表示不出圈。2、给标志数组赋初值为、给标志数组赋初值为0。3、模拟报数游戏全过程。、模拟报数游戏全过程。T从从1变化到变化到N控制报数游戏的每节循环,它实际上是一个控制报数游戏的每节循环,它实际上是一个指针变量,依次指向当前报数的位置;用指针变量,依次指向当前报数的位置;用S累计每节报数的数值;用累计每节报数的数值;用F统计出圈的统计出圈的总人数;因此总人数;因此F=N时游戏结束。时游戏结束。Program T11_6_2;Var n,m,s,f,t:integer; a:array1.100 of 0.1;Begin write(Input n,m=); readln(n,m); for t:=1 to n do at:=0; f:=0;t:=0;s:=0; write(coming out is:); Repeat t:=t+1; if t=n+1 then t:=1; if at=0 then s:=s+1; if s=m then begin s:=0; write(t:5); at:=1; f:=f+1; end;Until f=n;Readln;End.第12课: 编程训练例例T12_1:如果一个自然数除了如果一个自然数除了1和本身和本身,还有别的数能够整除它还有别的数能够整除它,这样的自然数就是合数。例如这样的自然数就是合数。例如15,除了除了1和和15,还有还有3和和5能够能够整除整除,所以所以15是合数。是合数。14,15,16是三个连续的合数是三个连续的合数,试求连续试求连续十个最小的合数。十个最小的合数。解:从解:从14,15,16三个连续合数中可看出三个连续合数中可看出,它们正好是两个相邻它们正好是两个相邻素数素数13和和17之间的连续自然数之间的连续自然数,所以求连续合数问题可以转所以求连续合数问题可以转化为求有一定跨度的相邻两个素数的问题。因此,求连续化为求有一定跨度的相邻两个素数的问题。因此,求连续十个最小的合数可用如下方法:十个最小的合数可用如下方法:从最小的素数开始,先确定第一个素数从最小的素数开始,先确定第一个素数A;再确定与再确定与A相邻的后面那个素数相邻的后面那个素数B;(作为第二个素数作为第二个素数);检查检查A,B的跨度是度否在的跨度是度否在10以上以上,如果跨度小于如果跨度小于10,就把就把B作为新的第一个素数作为新的第一个素数A,重复作步骤重复作步骤;如果如果A、B跨度大于或等于跨度大于或等于10,就打印,就打印A、B之间的连续之间的连续10个自然数,即输出个自然数,即输出A+1,A+2,A+3,A+10。Pascal 程序:ProgramT12_1;ProgramT12_1;vara,b,s,n:integer;vara,b,s,n:integer;yes:boolean;yes:boolean;proceduresub(x:integer;varyy:boolean);proceduresub(x:integer;varyy:boolean);过程:求过程:求过程:求过程:求x x是否为素数是否为素数是否为素数是否为素数 vark,m:integer;vark,m:integer;用用用用yyyy逻辑值转出逻辑值转出逻辑值转出逻辑值转出 beginbegink:=trunc(sqrt(x);k:=trunc(sqrt(x);form:=2tokdoform:=2tokdoifxmodm=0thenyy:=false;ifxmodm=0thenyy:=false;end;end;beginbegin主程序主程序主程序主程序 b:=3;b:=3;repeatrepeata:=b;aa:=b;a为第一个素数为第一个素数为第一个素数为第一个素数 repeatrepeatyes:=true;yes:=true;inc(b,2);binc(b,2);b是是是是a a后面待求的素数后面待求的素数后面待求的素数后面待求的素数, ,相当于执行了相当于执行了相当于执行了相当于执行了b:=b+2b:=b+2sub(b,yes);sub(b,yes);调用调用调用调用SUBSUB过程来确认过程来确认过程来确认过程来确认b b是否为素数是否为素数是否为素数是否为素数 ifyesthens:=b-a;ifyesthens:=b-a;如果如果如果如果b b是素数,则求出跨度是素数,则求出跨度是素数,则求出跨度是素数,则求出跨度ssuntilyes;untilyes;untils=10;untils=10;forn:=a+1toa+10doforn:=a+1toa+10dowrite(n:6);write(n:6);writeln;writeln;readlnreadlnend.end.例例T12_2:将合数将合数483的各位数字相加(的各位数字相加(4+8+3)=15,如果将,如果将483分解成质因数相乘:分解成质因数相乘:483=3*7*23,把这些质因数各,把这些质因数各位数字相加(位数字相加(3+7+2+3),其和也为),其和也为15。即某合数的。即某合数的各位数字之和等于它所有质因数的各数字之和。求各位数字之和等于它所有质因数的各数字之和。求500以内具有上述特点的所有合数。以内具有上述特点的所有合数。解:解:设设n为所要求的合数,让为所要求的合数,让n在在1500间循环做以间循环做以下步骤;下步骤;用用t1,t2分别累计合数分别累计合数n及及n的质因数的各位数字的质因数的各位数字之和,初值均为之和,初值均为0;调用过程调用过程SUB3进行非素数判定,以布尔变量进行非素数判定,以布尔变量yes的真假值判定是否,的真假值判定是否,yes的初值为的初值为true,如果为,如果为(nottrue)非素数,就做步骤非素数,就做步骤,;否则取;否则取新的新的n值,重复步骤值,重复步骤;调用调用SUB1,求,求n的各数字之和,传送给的各数字之和,传送给t1;调用调用SUB2,求,求n的各质因数,对于每个质因素都的各质因数,对于每个质因素都通过通过SUB1求它各位数字之和,将所有各质因数字传求它各位数字之和,将所有各质因数字传送给送给t2。如果如果t1=t2(各位数字之和等于它所有质因数的各(各位数字之和等于它所有质因数的各数字之和),则输出此数字之和),则输出此n。Pascal Pascal 程序:程序:programT12_2;varn,t1,t2,tatol:integer;yes:boolean;proceduresub1(x:integer;vart:integer);过程过程:分离分离x的各位数字的各位数字begin并并求各位数字之和求各位数字之和repeatt:=t+xmod10;x:=xdiv10;untilx=0end;proceduresub2(x:integer;vart:integer)proceduresub2(x:integer;vart:integer);过程:分解质因数过程:分解质因数过程:分解质因数过程:分解质因数 varxx,tt:integer;varxx,tt:integer;beginbeginxx:=2;xx:=2;whilex1dowhilex1doifxmodxx=0thenifxmodxx=0thenbeginbegintt:=0;tt:=0;sub1(xx,tt);sub1(xx,tt);t:=t+tt;t:=t+tt;x:=xdivxx;x:=xdivxx;endendelseinc(xx)elseinc(xx)end;end;proceduresub3(x:integer;varyy:boolean);proceduresub3(x:integer;varyy:boolean);过程:判断过程:判断过程:判断过程:判断x x是否为素数是否为素数是否为素数是否为素数 vark,m:integer;vark,m:integer;beginbegink:=trunc(sqrt(x);k:=trunc(sqrt(x);form:=2tokdoform:=2tokdoifxmodm=0thenyy:=false;ifxmodm=0thenyy:=false;end;end;beginbegin主程序主程序主程序主程序 forn:=1to500doforn:=1to500dobeginbegint1:=0;t2:=0;t1:=0;t2:=0;yes:=true;yes:=true;sub3(n,yes);sub3(n,yes);调用过程求素数调用过程求素数调用过程求素数调用过程求素数 ifnotyesthenifnotyesthen如果非素数就如果非素数就如果非素数就如果非素数就beginbeginsub1(n,t1);sub1(n,t1);调用过程求调用过程求调用过程求调用过程求n n的各位数字之和的各位数字之和的各位数字之和的各位数字之和 sub2(n,t2);sub2(n,t2);调用过程求调用过程求调用过程求调用过程求n n的各质因数的数字之和的各质因数的数字之和的各质因数的数字之和的各质因数的数字之和 ift1=t2thenwrite(n:6);ift1=t2thenwrite(n:6);打印合格的合数打印合格的合数打印合格的合数打印合格的合数 endendend;end;readlnreadlnend.end.例:例:T12_3汉诺塔游戏汉诺塔游戏约在十九世纪末,欧洲出现了一约在十九世纪末,欧洲出现了一种称为汉诺塔(种称为汉诺塔(TowerofHanoi)的)的游戏。据说这种游戏最早来源于布游戏。据说这种游戏最早来源于布拉玛神庙(拉玛神庙(TempleofBramach)里)里的教士。游戏的装置是一块铜板,的教士。游戏的装置是一块铜板,上面有三根金刚石的针,针上放着上面有三根金刚石的针,针上放着从大到小的从大到小的64个盘子。游戏的目标个盘子。游戏的目标是把所有的盘子从一根针上移到另是把所有的盘子从一根针上移到另一根针上,还有一个针作为中间过一根针上,还有一个针作为中间过渡。游戏规定每次只能移动一个盘渡。游戏规定每次只能移动一个盘子,并且大盘子不能压在小盘子上子,并且大盘子不能压在小盘子上面。由于需要移动的次数太多,该面。由于需要移动的次数太多,该游戏的结束将标志着世界末日的到游戏的结束将标志着世界末日的到来。来。通过计算,对于通过计算,对于64个盘子至少需个盘子至少需要移动要移动264-1=1.81019次。若每秒钟次。若每秒钟移动一次,需一万亿年,而太阳原移动一次,需一万亿年,而太阳原子燃料大约只能维持子燃料大约只能维持150亿年。若亿年。若用现代电子计算机,一微秒移动一用现代电子计算机,一微秒移动一次,也需要一百万年。次,也需要一百万年。下面以三个盘子为例。要从源下面以三个盘子为例。要从源1移动到目移动到目标标3,需要借助中间,需要借助中间2来过渡。一个可来过渡。一个可行的移动方案是:行的移动方案是:13(表示将第(表示将第1根针上的一个盘子移动根针上的一个盘子移动到第到第3根针上,下面各行以此类推)根针上,下面各行以此类推)123213212313此时共移动此时共移动7次,完成了三个盘子从源次,完成了三个盘子从源1到到目标目标3的移动。的移动。考虑一般情形,为了将考虑一般情形,为了将n个盘子从个盘子从a经过经过b移动到移动到c。可以先将。可以先将n-1个盘子从个盘子从a经过经过c移动到移动到b,然后将,然后将a中剩下的一个盘子中剩下的一个盘子移动到移动到c,最后再将,最后再将n-1个盘子从个盘子从b经过经过a移动到移动到c。这样我们就将原来与。这样我们就将原来与n有关有关的问题变成了与的问题变成了与n-1有关的问题。重复有关的问题。重复这个过程,每次这个过程,每次n减减1。最后当。最后当n=1时,时,直接移动该盘子就可以了。直接移动该盘子就可以了。定义过程定义过程move。为了将。为了将n个盘子从个盘子从a经过经过b移动到移动到c,可调用过程如下:,可调用过程如下:move(n,a,b,c)根据上面的讨论,可以根据上面的讨论,可以分解成下面的分解成下面的3个步骤:个步骤:move(n-1,a,c,b)acmove(n-1,b,a,c)PROGRAMT12_3;VARtotal:integer;PROCEDUREmove(n,a,b,c:integer);BEGINIFn=1THENwriteln(a,-,c)ELSEBEGINmove(n-1,a,c,b);writeln(a,-,c);move(n-1,b,a,c)ENDelseEND;moveBEGINread(total);move(total,1,2,3);END.例T12_4: 数字三角形问题描述如下所示为一个问题描述如下所示为一个数字三角形:数字三角形:738810274445265请编一个程序计算从顶至底请编一个程序计算从顶至底的某处的一条路径,使的某处的一条路径,使该路径所经过的数字的该路径所经过的数字的总和最大。总和最大。每一步可沿直线向下或每一步可沿直线向下或右斜线向下走;右斜线向下走;1三角形行数三角形行数100;三角形中的数字为整数三角形中的数字为整数0,1,2,99问题分析假设从顶至数字三角形的某问题分析假设从顶至数字三角形的某一位置的所有路径中,所经过的数字总和一位置的所有路径中,所经过的数字总和最大的那条路径我们称之为该位置的最大最大的那条路径我们称之为该位置的最大路径。由于题目规定每一步只能沿直线或路径。由于题目规定每一步只能沿直线或右斜线向下走,若要走到某一位置,则其右斜线向下走,若要走到某一位置,则其前一位置必为其左上方或正上方两个位置前一位置必为其左上方或正上方两个位置之一。由此可知,当前位置的最优路径必之一。由此可知,当前位置的最优路径必定与其左上方或正上方两个位置的最优路定与其左上方或正上方两个位置的最优路径有关,且来自其中更优的一个。径有关,且来自其中更优的一个。我们可以用一个两维数组我们可以用一个两维数组a记录数字记录数字三角形中的数,三角形中的数,aI,j表示数字三角形中第表示数字三角形中第i行第行第j列的数,再用一个两维数组列的数,再用一个两维数组max记记录每个位置的最优路径的数字总和。计算录每个位置的最优路径的数字总和。计算max数组可以像计算杨辉三角形一样用逐数组可以像计算杨辉三角形一样用逐行递推的方法实现,具体看程序清单:行递推的方法实现,具体看程序清单:ProgramT12_4;Constmaxline=100;Vari,j,t,line:integer;a,max:array1.maxline,1.maxlineofinteger;Beginrandomize;write(inputnumberofline(=maxi-1,j-1thenmaxi,j:=ai,j+maxi-1,jelsemaxi,j:=ai,j+maxi-1,j-1;maxI,i:=maxi-1,i-1+ai,iend;End;t:=0;Fori:=1tolinedoiftmax(i+1,j+1)thenmaxsum:=maxsum(i+1,j)+ai,jelsemaxsum:=maxsum(i+1,j+1)+ai,jEnd;Beginrandomize;write(inputnumberofline(100);readln(line);fori:=1tolinedobeginforj:=1toidobeginai,j:=trunc(random(99);write(ai,j:4);end;writeln;end;writeln;Writeln(maxsum=,maxsum(1,1);Readln;End.
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号