一、枚举型和子界型

7.1.1 类型定义
  类型定义的语法格式:
  type
  <标识符1>=<类型1>
  <标识符1>=<类型1>
  ……
  <标识符n>=<类型n>

7.1.2 枚举类型
  通过预定义列出所有值的标识符来定义一个有序集合,这些值的次序和枚举类型说明中的标识符的次序是一致的。枚举类型的形式:(标识符1……,标识符n)
例如:type daystype=(sunday,monday,tuesday,wednesday,thursday,friday,saturday)
  枚举元素只能是标识符,而不能是数值常量或字符常量。例如以下的定义是错误的:
     type daystype=('sun','mon','tue','wed','thu','fri','sat')
  枚举元素是标识符,不要把作为枚举元素的标识符视作变量名,它不能被赋值。同一个枚举元素不能出现在两个或两个以上的枚举类型定义中。例如以下的定义是错误的:
    type daytype1=(monday,tuesday);
         daytype2=(monday,wednesday);
  可以将枚举类型的定义和变量的定义结合在一起。例如:var a:(monday,tuesday,sunday)
  枚举类型属于顺序类型。根据定义类型时各枚举元素的排列顺序确定它们的序列,序列号从0开始。
   
例如:已经定义daystype
       ord(sunday)=0,succ(sunday)=monday,pred(friday)=thursday
  Turbo Pascal不允许直接读写枚举值,所以枚举值的输出常用case语句间接的输出。枚举值的输入,则要一一判断读入字符是否是枚举类型的标识符。若是才能赋给枚举变量,否则就会出错。
例如:枚举值的输出
 case day of
  sunday:write('sunday');
  monday:write('monday');
  tuesday:write('tuesday');
  wednesday:write('wednesday');
  thursday:write('thursday');
  friday:write('friday');
  saturday:write('saturday');
 end;

7.1.3 子界类型
  子界类型是由整型、字符型、枚举型、布尔型的两个常量指定该类型的值域区间。

子界类型的形式:  常量..常量
  两个常量必须是同一种顺序类型。例如:a..b,要求a<=b
   
例如:
  type a=1..3;
         b='a'..'d';
  可以将子界类型的定义和变量的定义结合在一起。例如:var a:1..9
  
例 按月、日、年顺序读入一日期,输出该日期是这一年中的第几天。
 program date;
  var year:0..2010;
    month,i:1..12;
    day:1..31;
    dayth:integer;
 begin
  read(month,day,year);
  dyath:=0;
  for i:=1 to month-1 do
   case i of
    1,3,5,7,8,10,12:dayth:=dayth+31;
    2:if ((year mod 4=0)and(year mod 100<>0)or(year mod 400 =0)
     then dayth:=dayth+29
     else dayth=:=dayth+28;
    4,6,9,11:dayth:=dayth+30;
   end;
  dayth:=dayth+day;
  writeln(dayth)
 end.

二、函数和过程

7.2.1 函数
  如果一个子程序执行后能够返回其结果值,那么它就可以用于表达式中,称这种子程序为函数,这种语句序列的定义称为函数说明。函数说明形式如下:
 function 函数名(形式参数表):函数类型;
  说明部分;
 begin
  语句1;
  语句2;
  ……
  语句n
 end
  函数返回一个函数值,过程则能完成一系列各种操作。函数的调用方式出现在表达式中,而过程调用是一句独立的语句。
例:计算|X|的函数
  function zhoufei(x:real):real;
   var z:integer;
  begin
   if x>=0 then z:=x
   else z:=-x
   zhoufei:=z;
  end;
  Turbo Pascal规定一个函数只能求出一个简单值。  

7.2.2过程

给某个语句序列组成的子程序赋于一个适当的名字。程序中凡是需要出现这个语句序列的地方,可以简单的写上子程序的名字。这种完成一个操作的子程序称为过程;子程序的定义称为过程说明。
  过程说明由过程首部和过程体组成,其形式如下:
    procedure
过程名(形式参数表);-------过程首部
   
说明部分;
    begin
     
执行语句;
      ……
    end;
例 输出两个数中最大值的过程
procedure largest(a,b:integer);
begin
if a>b then writeln(a)
else writeln(b);
end.
  

三、集合与记录

7.3.1 集合
  以已知序数类型值的集合为值,所构成的类型是集合类型,称已知序数类型为基类型。集合类型的定义形式为:
      集合类型名=set of 基类型
  基类型中不能超过256个可能值,且它们的序数值应在0..255之间。
  表示一个集合值的最通用的方法是逐个枚举集合的元素。下面是集合值标记的例子:
391520  {391520组成的集合}
[ ] {空集}
'l'..'p','z' ]  {由字符l,m,n,o,p,z组成的集合}
  两个相连的集合对象之间,可以通过下列运算符进行运算
集合运算符:

+   产生一个包含两个集合元素的集合

*   产生一个只包含两个集合元素公共元素的集合

-   产生一个包含所有属于第一个集合、但不属于第二个机和的元素的集合
例如:[A,B,C]+[D]等于[A,B,C,D]
[A,B,C]*[A]
等于[A]
[A,B,C]
[A]等于[B,C]

关系运算符

=    检查两个集合所包含的元素相同

<>   检查两个集合不相等

<=   检查第一个集合中的元素都在第二个集合中出现

>=   检查第一个集合中的元素包含第二个集合中的所有元素

in   检查集合基类型的一个元素属于集合
例如:[A,B,C]=[A,B,C] 等于true
[A,B,C]<>[C,B,A]
 等于FALSE

7.3.2 记录
  记录是描述同一对象的一组类型可能不同的数据的集合。使用记录类型实现了数据逻辑关系和存放形式上的一致。定义记录类型的一般形式
  记录类型名=record
      域名1:类型1
    域名2:类型2
    ……
    域名m:类型m
   end
例如:表示学生信息的记录定义
type
  stype=record
      name:string[20];
      number:integer;
       ***:(male,female);
      
  class:1..20
          address:string
  end;
  域为记录类型的元素。记录的每个域都有名称,不同域的数据类型可以各不相同,这一点是数组所不能做到的。引用记录变量的元素采用以下标记法:
(1)
直接引用,其形式为
   记录变量名.域名
例如:var str1,str2:stype;
   则str1.name表示学生str1的姓名,str2.***表示学生str2的性别。
(2)
使用with开域语句,其形式为
   with 记录变量名 do 语句
  在with语句中,引用记录变量名不再冠以记录变量名,以简化对记录中域的引用写法。例如描述100个学生的数据信息,引入元素类型为stype的数组students
  var
   students:array[1..100]of stype;
     number_of_boy,number_of _girl,k:integer:
例如下面是一段统计一个班级中男生人数和女生人数的程序。
 begin
  number_of_boy:=0;   number_of_girl:=0;
  for k:=1 to 100 do
  with student[k] do
  if  ***=male  then  number_of_boy:=number_of_boy+1
  else  number_of_girl:=number_of_girl+1
 end;
 with语句的嵌套结构的一般形式:
  with <记录变量名1> do
   with <记录变量名2> do
    ……
     with <记录变量名n> do
      <语句>
  上面的嵌套格式也可以简写为:
  with <记录变量名1,记录变量名2……,记录变量名n> do
   <语句>;  

四、指针

741 指针的动态变量
1.
定义指针类型
  在Pascal中,指针变量中存放的某个存储单元的地址,即指针变量指向某个存储单元。一个指针变量仅能指向某一种类型的存储单元,这种数据类型是在指针类型的定义中确定的,称为指针类型的基类型。指针类型定义如下:
   类型名=^基类型名;
例如:type q=^integer;
   var a,b,c:q;
  说明q是一指向整型存储单元的指针类型,其中"^"为指针符。a,b,c均定义为指针变量,分别可以指向一个整型存储单元。
  上例也可定义为:
    var a,b,c:^integer;
  指针也可以指向有结构的存储单元。
例如:type person=record
        name:string[10];
        ***:(male,female);
        age:20..70
      end;
   var pt:^person;
  pt为指向记录类型person的指针变量。
2.
动态变量
  应用一个指针指向的动态存储单元即动态变量的形式如下:
    指针变量名^
例如:p^q^r^
  指针变量p和它所指向的动态变量^p之间有如下关系:  P>P'

以下语句把整数5存放到p所指向的动态变量p^ 中去:  p^:=5;
以下语句把p所指向的p^中的值赋给整型变量i  i:=p^;
如果指针变量p并未指向任何存储单元,则可用下列赋值语句:
p:=nil; 
其中nilTurbo Pascal保留字,表示,相当于C里面的null

7.4.2 对动态变量的操作
  在Turob Pascal程序中,动态变量不能由var直接定义而是通过调用标准过程new建立的。过程形式为:
    new (指针变量名);
  如果有下列变量定义语句:
   var p:^integer;
  仅仅说明了p是一个指向整型变量单元的指针变量,但这个整型单元并不存在,在指针变量p中还没有具体的地址值。在程序中必须通过过程调用语句:new(p);才在内存中分配了一个整型变量单元,并把这个单元的地址放在变量p中,一个指针变量只能存放一个地址。在同一时间内一个指针只能指向一个变量单元。当程序再次执行new(p)时,又在内存中新建立了一个整型变量单元,并把新单元的地址存放在p中,从而丢失了旧的变量单元的地址。
  为了节省内存空间,对于一些已经不使用的现有动态变量,应该使用标准过程dispose予以释放。过程形式为:dispose(指针变量名);为new(指针变量名)的逆过程,其作用是释放由指针变量所指向的动态变量的存储单元。例如在用了new(p)后在调用dispose(p),则指针p所指向的动态变量被撤销,内存空间还给系统,这时 p的值为 nil
例:输入两个数,要求先打印大数后打印小数的方式输出,用动态变量做。
 program dongtai;
  type intepter=^integer;
  var p1,p2:intepter;
  procedure swap(var,q1,q2:intepter);
   var p:integer;
  begin
   p:=q1;q1:=q2;q2:=p;
  end;
 begin
  new(p1);new(p2);
  writeln('input 2 data: ');readln(p1^,p2^);
  if p1^  writeln('output 2 data: ',p1^:4,p2^:$);
 end.