1.55k likes | 1.79k Views
教师 (PASCAL 串讲 ) 培训讲习. 序言:信息学奥赛的发展. 1989 年 5 月首次举办国际信息学奥林匹克竞赛,简称 IOI ,成为继数学、物理、化学之后的又一门国际(中学生)奥林匹克竞赛。 1991 年起全国青少年计算机竞赛更名为全国青少年信息学(计算机)奥林匹克竞赛,简称 NOI 。由中国科学技术协会主管,中国计算机学会主办。 全国青少年信息学奥林匹克联赛,简称为 NOIP ,参加联赛是参加 NOI 的必要条件。. 信息学奥林匹克竞赛内容.
E N D
序言:信息学奥赛的发展 • 1989年5月首次举办国际信息学奥林匹克竞赛,简称IOI,成为继数学、物理、化学之后的又一门国际(中学生)奥林匹克竞赛。 • 1991年起全国青少年计算机竞赛更名为全国青少年信息学(计算机)奥林匹克竞赛,简称NOI。由中国科学技术协会主管,中国计算机学会主办。 全国青少年信息学奥林匹克联赛,简称为NOIP,参加联赛是参加NOI的必要条件。
信息学奥林匹克竞赛内容 • 程序设计知识。熟练使用一门程序设计语言编写程序;熟悉常用的基本算法:如穷举法、排序(冒泡)法、搜索法、回溯法、递归算法,排列组合等。 • 数据结构知识。简单变量、数组、队列、栈、串、记录、指针、链表、树、图和文件。 • 调试程序技能。
第1课 认识PASCAL语言 Pascal是一种计算机通用的、编译型的高级程序设计语言。它由瑞士Niklaus Wirth教授于六十年代末设计并创立。是一种按结构化程序设计原则描述的高级语言。主要特点有:严格的结构化形式;丰富完备的数据类型;运行效率高;查错能力强。NOI(全国奥林匹克信息学竞赛)把Pascal语言定为唯一提倡的程序设计语言
第1课 认识PASCAL语言 让我们先来看一个PASCAL程序,通过这个程序了解PASCAL的规则。 例L1_1 已知半径,求圆周长和面积的程序。
程序说明: PROGRAM circle(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程序框架 • 在Free Pascal 中可省程序参数表。 • 在程序执行部分使用的标号、常量、类型、变量、记录、文件、过程和函数,都必须在说明部分进行说明。但并不是每个程序都必需的,根据需要而设。 • 程序执行部分是指Begin开始到最后一条End. 结束语句的部分,是程序的核心。它由一系列语句组成,语句之间用“;”隔开,允许一行写多个语句,也允许一个语句写成几行。一般情况下一行只写一个语句。 Program 程序名(程序参数表); Label 标号说明; Const 常量说明; Type 类型说明; Var 变量说明; Function 函数说明; procedure 过程说明; begin 程序语句; …… end.
程序的书写格式: 1、PROGRAM写在最左边顶格; 2、注释的大括号{、和CONST、VAR、BEGIN、END等语句上下对齐,且它们比PROGRAM向右移两个字符; 3、各个语句和程序语句也是上下对齐,它们比第2点中的各语句又向右移两个字符; 4、语句间多余空格与空行,编译时会忽略。
2、常用进制对照表 数制的转换 1、常用的进位计数制有:十进制、二进制、八进制、十六进制。
3、十进制与二进制的相互转换 合在一起得: (20.6875)10 =(10100.1011)2 例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 正序取整 倒序取余
例2:将(11001.0101)2转换成十进制数。 (11001.1101)2 = 1×24+1×23+0×22+0×21+1×20+1×2-1+1×2-2 +0×2-3+1×2-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,取值范围为:-32768≤n ≤32767。 • 在free pascal中,允许整数采用十六进制(前加$)或二进制(前加%)表示。 如 x := %101,相当于 x:=5 ,y:=$10, 相当于y:=16 • 整数的类型: 注意:int64不是有序类型。直接给一个 int64类型的变量赋值一个超过longint范围的整数是非法的,这是因为free pascal在表达式的计算中默认最大类型为longint。
标识符 • 标识符是以字母开头的字母、数字组合,用来表示常量、变量、类型、文件、函数、过程或程序的名字。 • 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
变量定义格式: var <变量名表> :类型标识符; 例如: var a,b :integer; x,y :real; ch :char; t: boolran; 但下列说明是非法的: 例如: var a,b =integer; ch :char; ch :boolean; a,b后面不能用=,ch不能重复定义。 变量一经说明,系统就为其分配内存。程序中使用该变量时,就要在相应的内存单元读写数据,称为对变量的访问。 常量与变量 • 常量定义格式: const <常量标识符> = <常量>; 要求如下: 1、要放在程序说明部分。 2、必须遵循先定义后使用的原则。 3、不允许重复定义,或一次定义多个常量。 例如: const a =1; a,b = 10; c = 1 or 2; d := 3;
顺序结构程序设计 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=3 x+y=5 x*y=6 write语句可以输出实型、整型、字符型、布尔型值,也可以输出字符串。若在write语句中不加场宽说明,则按标准场宽输出。在这里,场宽是指输出值的位数。
自定义场宽 (1)单场宽。用来控制整型、字符型、布尔型数据的输出格式,不能用于实数型。 格式:<输出项>:n 说明:n(正整数) 表示输出时所占的列数。单场宽一律右对齐,前用空格。 (2)双场宽。用来控制实数的输出格式。 格式: <输出项>:n1:n2 说明: ①n1表示输出总占列数,包括符号位、整数部分、小数点和小数部分;n2表示小数部分的列数。 ② 当数据突破场宽时,首先保证整数部分的有效性,小数部分按n2场宽进行四舍五入显示,但内存中仍是原来的精确度。 ③ 单场宽右对齐,双场宽向小数点看齐,多余的小数位数补零。
例T2_1:交换两个变量的值。 (2)不用中间变量,也可实现交换。 Program T2_1_2; Var a,b :integer; Begin write(‘please input a,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. (1)利用中间变量c,实现交换。 Program T2_1_1; Var a,b,c :integer; Begin write(‘please input a,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.
例T2_2:鸡兔同笼问题。已知鸡和兔的总头数是H,总腿数为F,求鸡和兔各多少只?例T2_2:鸡兔同笼问题。已知鸡和兔的总头数是H,总腿数为F,求鸡和兔各多少只? 程序为: Progrem T2_2; var h,f,c,r:real; begin readln(h,f); c:=(4*h-f)/2; r:=h-c; writeln(‘click:’,c); writeln(‘rabbit:’,r); end. 分析:设鸡为C只,兔为R只,则 C+R=H 2*C+4*R=F 解得:C=(4*H-F)/2, R=H-C 。
例T2_3: 随机产生一个三位自然数,求其百位、十位、个位上的数字。 • 程序为: • 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. 分析:要产生随机数,必然用到随机函数。 Random是随机函数能产生[0,1]之间的随机实数。 随机产生三位数的表达式为: trunc(random*900)+100 假设三位数X,百位数分另别为A,B,C,则存在如下关系: A= X DIV 100 B= (X-A*100) DIV 10 C= X MOD 10
例T2_4 已知三角形的两边及夹角,求第三边及面积。 数学建模: 设三角形的两边及夹角分别为a,b,α,第三边为c,面积为s。 则 , 若α以角度值输入,在计算sin和cos时应转换为弧度。角度转弧度的公式为: 弧度=角度× 程序: Program T2_4; const pi=3.14159; var a,b,alfa,c,s:real; begin read (a,b,alfa); alfa:=alfa*pi/180; c:=sqrt(a*a+b*b-2*a*b*cos(alfa)); s:=1/2*a*b*sin(alfa); write(‘alfa=‘,alfa,’c=‘:8,c,’s=‘:8,s); end.
例T2_5: 输入一个字符,求其序号、前导(即前一字符)、后继(即后一字符)。 Program T2_5; var ch,pch,sch:char; num:integer; begin writeln; write (‘please input a character:’); readln(ch); write(‘pch:’,pred(ch),’sch:’,succ(ch),’num:’,ord(ch)); readln(); end. 测试删除倒数第二条语句readln();后,执行情况有何不同?
例T2_6: 输入x,y。若在圆环内,输出true,若在圆环外;输出false。圆环如图所示。 程序: program T2_6; var x,y :real; bool:boolean; begin writeln; write(‘x=?’); readln(x); write(‘y=?’); readln(y); bool:=(x*x+y*y>=1) and (x*x+y*y<=4); write(bool); readln; end. 讨论:如图所示,若下式 1≤x2+y2≤4 成立则在圆环内,否则在圆环外。 设布尔变量bool,当x,y在圆环内时,让它取值为true,否则取值为false。 “(x,y)若在圆环内”的表达式:(x2+y2≥12)且(x2+y2≤22)
作业: • XT1_1 写一程序读入三角形的三个边a,b,c,计算并打印三角形的面积S。可利用下列公式计算。 其中: • XT1_2 输入一个三位整数,将它们反向输出。例如输入127,输出应为721。 • XT1_3 由键盘输入两组x,y值,由程序根据它们是否在示意图中的斜线区域内,输出不同的值。若在斜线区域内,输出true,否则输出false。
第3课 选择结构程序设计 PASCAL中有两个语句可实现选择结构: IF语句(条件语句)和CASE语句(情况语句) • 3.2.1 IF语句的两种形式 • IF语句又称如果语句(或称条件语句)。它的一般形式是 • IF (条件) • THEN (语句1) • ELSE (语句2) • 其中“条件”实际上是一个布尔表达式,它的值可以是真(true)或假(false)。在条件为真时,执行语句1,否则(条件为假)执行语句2。 • 可以利用流程图来描述选择结构。 • 在流程图中用菱形框表示要执行的判定,其余步骤用矩形框表示,箭头表示执行的顺序。
weight≤50 weight>50 例L3_1 火车托运行李,要根据行李的重量按不同标准收费。例如不超过50kg,按每公斤0.35元收费。若超过50kg,则其中50kg按每公斤0.35元收费,其余超过部分按每公斤0.50元收费。现输入托运行李重量,要求计算并输出托运费。 数学建模:设托运行李重量为weight,该问题要求根据weight是否超过50kg,按不同公式计算出托运费。设托运费为pay。weight和pay均为实型。 下面给出算法。 一级算法 1、读入weight的值。 2、根据weight的大小选择不同的公式计算pay。 3、输出pay。 其中第2步需求精。根据题意,可以写出计算pay的公式如下:
除了上面给出的IF语句形式外,PASCAL中还有另外一种IF语句形式。即除了上面给出的IF语句形式外,PASCAL中还有另外一种IF语句形式。即 IF (条件) THEN (语句) 在条件为真时,执行THEN后的语句。在条件为假时,不执行THEN后的语句,在两种情况下的后继语句都是IF语句的下一个语句。
例L3_2读入三个数,找出并打印其中的最大数。例L3_2读入三个数,找出并打印其中的最大数。 解: PROGRAM L3_2; VAR a,b,c:real; BEGIN write('a=?'); read(a); write('b=?'); read(b); write('c=?'); read(c); IF a<b THEN a:=b; IF a<c THEN a:=c; writeln('ZuiDaShu:',a) END.
3.2.2 复合语句 • 在IF语句中,跟在THEN或ELSE后的语句可能不止一个,这时要用到复合语句的概念。 • 复合语句是一个以BEGIN开始,以END结束的语句。在BEGIN与END之间可以包括若干个语句,每个语句之间以分号分开。一般形式为: BEGIN (语句1); (语句2); … (语句n) END • 一个复合语句从外部看来,相当于一个语句。
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语句可能会有两种不同的理解。 注意:在进行IF语句的嵌套时应注意IF 与 ELSE的配对关系,ELSE是不能省略的,否则将造成逻辑错误。解决的办法是写一个空语句或者采用复合语句,即增加语句括号(begin…end)。从内层开始,ELSE总是与它上面最近的(示曾配对的)IF配对。
例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 输入年、月,输出该月有几天。 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 100<>0) or (year mod 400 =0) then days:=29 else days:=28; end; writeln (year,’year’,month,’month:’,’days:’,days); End. • 讨论:每年的1、3、5、7、8、10、12月,每月有31天;4、6、9、11月,每月有30天;2月闰年有29天,平年有28天。 • 年号能被4整除,但不能被100整除,或者年号能被400整除的年均是闰年。 • 用year、month、days分别表示年、月、每月天数。它们均为整数。 • 闰年的条件可以写成如下的布尔表达式: • (year MOD 4 = 0) AND (year MOD 100 <> 0) OR (year MOD 400 = 0)
例L3_6 编制程序,根据输入的x值,计算y与z并输出。 PROGRAM L3_6; CONST PI=3.14159; VAR x,y,z:real; BEGIN write('x=?'); read(x); IF x<=2.5 THEN y:=x*x+1 ELSE y:=x*x-1; IF x<0 THEN z:=-PI/2*x+3 ELSE IF x=0 THEN z:=0 ELSE z:=PI/2*x-5; writeln('x=',x:6:2,',y=',y:6:2,', z=',z:6:2) END.
作业: • XT3_1 对一批货物征收税金,价格在1万元以上的货物征税5%,在5000元以上,1万元以下的货物征税3%,在1000元以上,5000元以下的货物征税2%,1000元以下的货物免税。编写一程序,读入货物价格,计算并输出税金。 • XT3_2 输入某学生成绩,若成绩在85分以上,输出very good,若成绩在60分到85分之间,输出good,若成绩低于60分,输出no good。 • XT3_3 输入班号,输入该班学生人数。应用CASE语句编程序。
第4课 循环结构 • 循环结构(或称重复结构)是程序中的一个基本结构,在解许多问题中是很有用的。我们知道,在许多复杂的问题中,常常需要做大量类同的计算处理。尽管计算机的运算速度很快,然而要把这些大量类同的计算处理的每一步都写成语句,并输入计算机中,其工作量是相当大的。有时是难以完成的。 • 循环结构程序设计可以帮助我们有效地解决这一难题。利用循环结构程序设计,使得我们有可能只编写少量的语句,让计算机重复执行它许多次,从而完成大量类同的计算要求。 • 在PASCAL中,实现循环程序设计的主要语句有FOR语句、WHILE语句和REPEAT语句。
一、FOR语句格式1:(递增型) FOR x:=<初值> TO <终值> DO <循环体>格式1: (递减型)FOR x:=<初值> downTO <终值> DO <循环体> FOR X:= 1 TO 10 DO FOR X:= ‘A’ TO ‘Z’ DO FOR X:=10 DOWNTO 1 DO FOR X:=’Z’ DOWNTO ‘A’ DO 控制变量 初值 控制变量≥终值 false true 执行语句 控制变量 pred(控制变量) 控制变量 初值 控制变量≤终值 false true 执行语句 控制变量 succ(控制变量)
T4_001 计算1+2+3+…+10 PROGRAM 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个任意整数,求它们的和. 例T4_003: 计算n!(n!=1×2×3×…×n) 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. 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. 注意N<8,否则会溢出。
例T4_004:任何一个 n3一定可以表示成n个连续的奇数和。输入n(n≤100),输出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 2
Program T4_004; var i,n,a:longint {循环变量,连续的奇数个数,当前项,类型 为长整型} begin readln(n); a: = n*(n-1) +1; for i:= 1 to n-1 do begin write(a,’+’); a:=a+2; end; writrln(a); readln; end 思考题:用数学方法证明上述定理。
作业: T4_005 输入10个任意整数,求它们的平均值。 T4_006 按正序和反序分别输出26个英文字母。 T4_007 输入20个整数,输出其中最大数。 T4_008 输入20个整数,统计其中正、负和零的个数。 思考题: 求值: