您好,欢迎访问三七文档
金山中学计算机竞赛班教程·Pascal6——1§6集合与记录类型§6.1集合类型§6.1.1集合类型的定义集合是同类型对象的一个汇集,它是指同类型对象汇集在一起构成的数据结构。集合的每一个对象称为集合的元素。集合元素必须是有序简单数据类型,集合元素的类型称为集合的基类型。集合的一般形式为:TYPE类型标识符=setof基类型;基类型可以是整型、字符型、布尔型、枚举型、子界型等,但不能是实型或结构类型。例如:TYPEletter=setof‘A’..‘Z’;varch1,ch2:letter;也可以直接写成:varch1,ch2:setof‘A’..‘Z’;在Pascal中集合是用一组括在方括号中的元素来表示,元素之间用逗号分隔。如:[A,B,C,D]是四个枚举量的集合[1..20]表示1到20的所有整数的集合[‘0’]是单元素集[]表示空集一个集合类型变量的取值,可以是基类型中所有元素按不同的组合而构成的子集。例如,上面说明变量ch1的类型是letter,它可以是下列的组合:[‘A’..‘Z’]全集[‘A’,‘B’,‘Q’]任一子集[‘A’..‘C’,‘X’..‘Z’][‘A’]单元素集[]空集空集与所有的集合类型都兼容。§6.1.2集合类型的运算ch1:=[[‘A’..‘C’]];是合法的集合赋值。对集合除可以进行赋值运算外,还可以进行以下运算:·交(*)运算:两集合之交S1*S2为一集合,所得元素由S1、S2中相同的元素组成。如:[0..7]*[0..4]=[0..4]·并(+)运算:两集合之并S1+S2为一集合,所得元素由S1、S2中所有相同的元素组成。如:[0..7]+[0..4]=[0..7][0,1]+[1,4,6]=[0,1,4,6]金山中学计算机竞赛班教程·Pascal6——2·差(-)运算:两集合之差S1-S2为一集合,所得元素由只存在于S1而不在S2的那些元素组成。如:[0..7]-[0..4]=[5..7]·比较运算:集合可进行“=”、“=”、“=”、“”等比较运算:等于“=”——S1=S2,若S1与S2中所有元素均相同,结果为true,否则为false。如:[0..4]=[0..4]结果为true[0..7]=[0..4]结果为false不等于“”——S1S2,S1与S2中至少有一个元素不同,如:[0..7][0..4]结果为true[0..4][0..4]结果为false包含“=”——S1=S2表示S2是S1的子集。被包含“=”——S1=S2表示S1是S2的子集。如:[0..7]=[0..4]结果为true[0..7]=[0..4]结果为false[]=[0..4]结果为true·检查(in)运算:用来检查某一元素是否属于某一集合。如:1in[0..4]结果为true5in[]结果为false‘A’in[‘A’..‘Z’]结果为true§6.1.3集合类型的表达式集合表达式是由集合常数、集合变量、集合构造符和集合运算符组成。如:k:=5;ch2:=[1,2,3,4]+[k];运行之后,ch2中就会有5个元素:1、2、3、4、5。注意:...[1......5]..与.[1,2,3,4,5]...........两种表达式是等价的。..........集合运算相当快,在程序中常用集合表达式来描述复杂的测试。例如,条件表达式:(ch=’T’)or(ch=’u’)or(ch=’R’)or(ch=’B’)可用集合表达式表示为:chin[‘T’,‘u’,‘R’,‘B’]又如:if(ch=20)and(ch=50)then语句可写成:ifchin[20..50]then语句§6.1.4注意问题集合类型是一种使用简单,节省内存而又运算速度快的数据类型,在解决某些问题时,它能使程序编写简明清晰,节省内存而又节省运行时间。但是使用集合时必须注意以下几点:①Pascal规定集合的元素个数不超过256个。当实际问题所需的元素个数大于256时,可采用布尔数组代替集合类型。所以vari:setofinteger;的说明是错误的,因为它的元素个数超过256个。金山中学计算机竞赛班教程·Pascal6——3②集合类型变量不能进行算术运算,也不允许用读/写语句直接输入/输出集合。所以集合的建立要通过赋值语句实现,或先初始化一个集合,然后通过并(+)运算向集合中逐步加入各个元素;集合的输出也必须间接地转换,如集合中的元素是数字或字母,可通过序数值的转换关系输出对应的字符。③集合的元素是无序的,所以ord,pred和succ函数不能用于集合类型的变量。【例1】用集合方法编程,实现把100以内的全部素数找出来,然后把求得的每十个素数排成一行,形成素数表。算法分析:用筛法求素数。第一步,定义一个集合类型,如sss,它包含99个元素,从2到100;第二步,定义两个集合变量,如筛集合s和素数集合p,它们是sss类型的变量;第三步,按筛法找出全部素数;第四步,间接输出素数表。算法求精如下:①把2到100逐步放入筛中,建立筛集合s;②选定筛中最小的素数——2;③把选定的素数放入素数集合P中;④检查筛集合s,从中删去选定素数和它的所有倍数;⑤重复步骤2、3、4,直到筛集合s变成空集,素数集合P完全建立;⑥间接输出集合P中的元素,且每10个一行。程序清单:programerato;constn=100;typesss=setof2..n;vars,p:sss;next,j:integer;Begins:=[2..n];{初始准备}p:=[];next:=2;repeat{建立素数表}whilenot(nextins)donext:=next+1;p:=p+[next];j:=next;whilej=ndobegin{去掉选定素数的倍数}s:=s-[j];j:=j+next;end;{while}untils=[];j:=0;金山中学计算机竞赛班教程·Pascal6——4fornext:=2tondo{输出素数集合元素}ifnextinpthenbeginwrite(next:5);j:=j+1;ifj=10then{每10个素数为一行}beginwriteln;j:=0;end;end;{if}End.§6.2记录类型记录类型数据是由固定数量,具有不同类型的成份组成。这种数据在实际问题中常遇到,如描述学生姓名、性别、年龄、班级和各科成绩的档案登记表。这种数据用数组类型是非常烦琐的,可以利用Pascal提供的记录类型。§6.2.1记录类型的数据记录是由固定数量的字段(又称域)的元素所组成的一种结构,各个字段可以具有各种不同的数据类型,每个字段都有一个名称即字段标识符。记录类型定义的一般形式:TYPE类型标识符=RECORD字段名1:类型1;┆┆字段名n:类型n;END;记录中描述对象的字段表,包括了记录的固定部分和变体部分;记录的固定部分由字段名和类型说明部分,记录的变体部分在本节的最后介绍。下面介绍如何描述记录的数据,例如:typedate=recordyear:1900..2500;month:(JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC);day:1..31;end;vardate1,date2:date;对记录类型变量的访问,不同于数组那样通过下标来访问其成份,而是通过记录变量名,句号(.),字段名来访问记录中的成份,称为记录的点记法,其形式为:记录变量名.字段名:=数据项;金山中学计算机竞赛班教程·Pascal6——5例如:date1.year:=1937;date1.month:=JUL;date1.day:=7;如果记录的某个字段是字符型数组,如student.name字段是一个由20字符组成的字符型数组,则可用循环语句读入字符:fori:=1to20doread(student.name[i]);·记录类型与数组类型相似,允许在同类型的两个记录之间进行整体赋值。如:date2:=date1;·记录可以嵌套,即记录中的字段的类型也可以是记录,嵌套的记录类型是有层次的数据类型。在同一层的标识符不能同名,但不同层的字段名可以同名。例如:varr:integer;s:recordr:real;s:recordr:char;s:boolean;end;end;对于层次记录的引用必须采用自顶向下的完全路径,如:varworker=recordage:15..70;birth:recordyear:1900..2200;month:1..12;end;end;引用记录变量worker的域,表示出生年,应写成:worker.birth.year【例2】设学生成绩登记表有下列项目:学号、姓名、年龄、班级、数学、物理、政治、英语、总分。现对学生成绩进行统计,算出各科的总分和平均分。程序清单:programstu;constn=60;typestudent=recordno:integer;name:string[16];age:6..30;金山中学计算机竞赛班教程·Pascal6——6class:string[8];math,physics,politics,english:0..100;tal:0..400;end;varst:array[1..n]ofstudent;i,j,summ,sumph,sumpl,sume:integer;Beginfori:=1tondobeginreadln(st[i].no,st[i].name);readln(st[i].age,st[i].class);readln(st[i].math,st[i].physics,st[i].politics,st[i].english);st[i].tal:=st[i].math+st[i].physics+st[i].politics+st[i].english;end;summ:=0;sumph:=0;sumpl:=0;sume:=0;fori:=1tondobeginsumm:=summ+st[i].math;sumph:=sumph+st[i].physics;sumpl:=sumpl+st[i].politics;sume:=sume+st[i].english;end;writeln('math',summ,'average',summ/n);writeln('physics',sumph,'average',sumph/n);writeln('politics',sumpl,'average',sumpl/n);writeln('english',sume,'average',sume/n);End.§6.2.2with语句从上例中可见,用点记法引用记录会使句子冗长,若能像存取简单变量一样存取记录的字段,则会使之简便得多。开域语句正好提供了这种功能,它“打开一个记录”后便可像引用变量那样使用字段名。开域语句的一般形式为:with记录变量名do语句;其中do后面的语句可以是简单语句,也可以是复合语句,在这些语句中,只要使用字段名就可以,不必再在前面写上记录变量名。例如,给记录date1赋值,不用前面的点记法,而用开域语句,则为:withdate1dobeginyear:=1937;month:=Jul;day:=7;end;金山中学计算机竞赛班教程·Pascal6——7【例3】下面是用with语句对例2的改写。programstu;……Beginfori:=1tondowithst[i]dobeginreadln(no,name);readln(age,class);readln(math,physics,politics,english);tal:=math+physics+politics+english;end;summ:=0;sumph:=0;sumpl:=0;sume:=0;fori:=1t
本文标题:Pascal第六课
链接地址:https://www.777doc.com/doc-2848816 .html