当前位置:文档之家› Object Pascal语言开发基础

Object Pascal语言开发基础

Object Pascal语言开发基础
Object Pascal语言开发基础

1、Object Pascal 语言

本章内容:

? 注解

? 新的过程和函数特征

? 变量

? 常量

? 运算符

? Object Pascal 类型

? 用户自定义类型

? 强制类型转换和类型约定

? 字符串资源

? 测试条件

? 循环

? 过程和函数

? 作用域

? 单元

? 包

? 面向对象编程

? 使用D e l p h i 对象

? 方法

? 结构化的异常处理

? 运行期类型信息

这一章把D e l p h i 的可视化元素放在一边,主要是为了向读者介绍D e l p h i 使用的语言—O b j e c t

P a s c a l 语言。首先介绍Object Pascal 的基础,例如语言规则和结构;稍后介绍一些Object Pascal 的高级 技术,例如类和异常处理。因为这本书不是针对入门者的书,它假定读者有使用其他高级计算机语言 例如C 、C + +或Visual Basic 的经验,最后将学习编程的概念,例如变量、类型、运算符、循环、条件、 异常和对象,并跟C + +和Visual Basic 进行比较。

即使有使用P a s c a l 的经验,你仍将发现这一章有用,因为通过这一章会学到P a s c a l 语法和语义的内 在本质。

2.1 注解

作为起点,应该知道在P a s c a l 代码中怎样写注解。Object Pascal 支持三种类型的注解:花括号注解、 圆括号/星号注解和C + +风格的双斜杠注解。下面是每种类型的例子:

{使用花括号注解}

( *使用圆括号/星号注解* )

/ / C + +风格的注解

1、Object Pascal Object Pascal语言语言语言1 71 71 7

前两种注解在本质上是相同的,编译器把在注解限定符头和注解限定符尾中间的内容当作注解。

对于C + +风格的注解来说,双斜杠后面到行尾的内容被认为是注解。

注意相同类型的注解不能嵌套。虽然不同类型的注解进行嵌套在语法上是合法的,但我们不

建议这样做。这里是一些例子:

{ ( *这是合法的* ) }

( * {这是合法的} * )

( * ( *这是非法的* ) * )

{ {这是非法的} }

些新的或鲜为人知的特性。

2.2.1 圆括号

虽然不是在Delphi 5.0才有的,但Object Pascal 中一个鲜为人知的特性是,当调用一个过程或函数

时,如果被调用的过程和函数没有参数,圆括号是可以省略的。因此下面两个例子在语法上都是合法

的:

当然,这个特性看上去作用不是很大,但是它对于那些同时使用C + +或J a v a (需要圆括号)的程序员

来说特别有用。假如不能把时间全都花在D e l p h i 上,这个特性使你没必要记住在不同语言之间不同的

函数调用规则。

2.2.2 重载

D e l p h i 4引进了函数重载的概念(多个过程和函数有相同的名字,但有不同的参数列表)。所有需要

重载的方法都需要声明,并用o v e r l o a d 来指示,示例如下:

要注意的是,一个类的方法的重载稍微有点不同,在后面的2 . 1 8 . 1节中介绍。虽然这是自D e l p h i

1 . 0以来开发人员一直期望有的一个重要特性,但要记住小心使用它。有多个相同名字的过程和函数使

得控制程序的执行和调试程序更加困难,正因为这样,对于使用重载这个特性,既不要回避,也不要

滥用。

2.2.3 缺省值参数

缺省值参数是在Delphi 4中被引进的(当调用有缺省值参数的过程和函数时,可以不提供参数)。为

了声明一个有缺省值参数的过程或函数,在参数类型后跟一个等号和缺省值,示例如下:

H a s D e f Va l ( )过程能用下列两种方式调用。

第一种方式,两个参数都指定:

第二种方式,指定一个参数S ,对I 则用缺省值:

H a s D e f Val('hello'); //对于I ,使用缺省值

在使用缺省值参数时要遵循下列几条规则:

? 有缺省值的参数必须在参数列表的最后。在一个过程或函数的参数列表中,没有缺省值的参数

不能在有缺省值的参数的后面。

? 有缺省值的参数必须是有序类型、指针类型或集合类型。

? 有缺省值的参数必须是数值参数或常量参数,不能是引用( o u t )参数或无类型参数。

有缺省值参数的最大好处是,在向一个已存在的过程和函数增加功能时,不必关心向后兼容的问

题,例如,假定在一个单元中有一个函数为A d d I n t s ( ),它将两个数相加。

如果想修改这个函数的功能使它能实现三个数相加,可能感到麻烦,因为增加一个参数将导致已

经调用该函数的代码不能编译。由于有了有缺省值的参数,能扩展A d d I n i t s ( )函数的功能而不必担心它

的兼容性,示例如下:

2.3 变量

你可能已经养成随时声明变量的习惯,“我需要另一个整数,所以我就在代码块的中间声明它”。

如果这是你的习惯,在Object Pascal 中使用变量时将不得不对自己有所限制。Object Pascal 要求在一个

过程、函数或程序前在变量声明段中声明它们。你可能过去习惯写这样的代码:

在Object Pascal 中,任何这样的代码要被整理成如下:

注意Object Pascal —像Visual Basic ,但不像C 和C++,是大小写不敏感的。采用大小写只是

为了可读性好,所以就像本书所用的风格,能根据自己的需要使用大小写。如果一个名字是几

个单词连在一起的,记住用大写来区分它们,例如,下列名字不清晰并很难读:

然而,这样就好多了:

1 8 1 8 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

对本书的代码风格的完整介绍,请看第6章_______“代码标准文档”。

你可能奇怪这样的结构化有什么好处,然而,你将看到Object Pascal 的结构风格导致它的代码的

可读性好、维护性好并比C + +或Visual Basic 减少了错误的可能性。

要跟变量声明分开。

在Delphi 2 中进入了一个新的语言特性,能在v a r 块中对全局变量赋初值,这里有一些例子演示:

注意能赋初值的变量仅是全局变量,不是那些在过程或函数中局部变量。

提示Delphi 编译器自动对全局变量赋初值。当程序开始时,所有的整型数赋为0,浮点数赋为

0.0,指针为null ,字符串为空等等,因此,在源代码中不必对全局变量赋零初值。

2.4 常量

在P a s c a l 中用c o n s t 关键字来声明常量,就像在C 语言中c o n s t 关键字一样,这里有三个在C 语言中定

义的常量:

C 语言跟Object Pascal 语言声明常量的主要差别是,在Object Pascal 语言中不需要在对常量赋值时

声明常量的类型,跟Visual Basic 一样,编译器能根据常量的值自动判断常量的类型并分配内存;对于

整型常量,编译器在运行时跟踪它的值,并不对它分配内存,例如:

注意编译器根据如下规则来对常量分配内存:整型数被认为是最小的Integer 类型(10被认为是

S h o r t I n t ,3 2 0 0 0被认为是S m a l l I n t 等等);字符串值被认为是char 类型或s t r i n g 类型(通过$ H 定

义);浮点值被认为是e x t e n d e d 数据类型,除非小数点位数小于4位(这种情况被当作c o m p 类

型);Integer 和Char 的集合类型被存储为它们自己。

当然,在声明变量时可以指定变量的类型,这样就能完全控制编译器对常量的处理,

Object Pascal 允许在c o n s t 和v a r 声明时用编译期间的函数,这些函数包括O r d ( )、C h r ( )、Tr u n c ( )、

R o u n d ( )、H i g h ( )、L o w ( )和S i z e o f ( )。例如,下列所有代码都是合法的:

1、Object Pascal Object Pascal语言语言语言1 91 91 9

警告在3 2位D e l p h i 中常量的类型定义是与在1 6位D e l p h i 中常量的类型定义不同的。在1 6位的

Delphi 1.0中,这种指定了类型的常量不是当作常量,而是被当作赋初值的变量或类型常量

(typed constant);然而,在Delphi 2.0以后指定了类型的常量才真正被当作是常量。D e l p h i 在

P r o j e c t 菜单的O p t i o n s 对话框中的C o m p i l e r 页上提供了向后兼容;或者可以用$ J 编译开关来控

制,缺省情况下,该开关是开的,向后兼容D e l p h i 1 . 0,但是最好不要用这个方法,因为O b j e c t

Pascal 以后可能不再支持它。

如果程序试图改变常量的值, D e l p h i 编译器就会有一个警告,认为程序违反了规则,因为常量值

是只读的。Object Pascal 通过在应用程序的代码页存贮常量来优化数据空间,如果对代码页和数据页

的概念不清楚,请看第3章“Win32 API ”。

注意跟C 和C + +不一样,Object Pascal 没有预编译。在Object Pascal 中没有宏的概念,因此

Object Pascal 没有跟C 一样的# d e f i n e 常量声明。虽然在Object Pascal 中用$ d e f i n e 进行条件编译,

但不能用它来定义常量。在C 或C + +中用# d e f i n e 定义常量的地方在Object Pascal 中用c o n s t 来定

义。

2.5 运算符

运算符是在代码中对各种数据类型进行运算的符号。例如,有能进行加、减、乘、除的运算符,

有能访问一个数组的某个单元地址的运算符。本节将介绍各种P a s i c a l 运算以及这些运算符跟C 和Vi s u a l

B a s i c 运算符的区别。

2.5.1 赋值运算符

如果你是P a s i c a l 的新手, D e l p h i 的赋值运算符可能是你最不习惯的事情之一。为了给一个变量赋

值,用:=运算符,而不像在C 或Visual Basic 中用= 运算符。P a s c a l 程序员称它为获得运算符或赋值运

算符,下列表达式:

可以读成N u m b e r 1获得值5,或N u m b e r 1被赋值为5。

2.5.2 比较运算符

如果你用Visual Basic 编过程序,可能对D e l p h i 的比较运算符感到很熟悉,因为它们在本质上是相

同的,比较运算符在所有程序语言中基本相同,所以本节只是简单介绍。

Object Pascal 用=运算符对两个表达式或两个值进行逻辑比较运算, Object Pascal 中的=运算符跟

2 0 2 0 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

D e l p h i 的不等于运算符是< >,相当于C 语言中的!=运算符,为了判断两个表达式是否不等,用下

列代码:

2.5.3 逻辑表达式

P a s c a l 用单词and 和o r 作为逻辑与和逻辑或运算符,而C 语言使用& &和作为逻辑与和或的运算符。 与和或最常用的是作为i f 语句或循环语句的一部分,就像下面两个例子演示的:

P a s c a l 的逻辑非的运算符是n o t ,它是用来对一个布尔表达式取反,相当与C 语言中的!运算符,

它同样也经常作为i f 语句的一部分,示例如下:

if not ( c o n d i t i o n ) then (do something ); //如果条件错则. . .

表2 - 1是一个简明参考表,列出了Object Pascal 、C / C + +和Visual Basic 的运算符。

表2-1 赋值、比较和逻辑运算符

运算符P a s c a l C / C + + Visual Basic

赋值: = = =

比较= = = =或I s ①

不等于< > ! = < >

小于< < <

大于> > >

小于等于< = < = < =

大于等于> = > = > =

逻辑与a n d & & A n d

逻辑或o r | | O r

逻辑非n o t ! N o t

① I s 比较符是用在对象之间,而=用于其他类型之间。

2.5.4 算术运算符

你应该对Object Pascal 的大多数算术运算符很熟悉,因为它们跟在C / C + +和Visual Basic 中的大致

相同,表2 - 2列出了所有Object Pascal 算术运算符以及跟C 、Visual Basic 的对照。

表2-2 算术运算符

运算符P a s c a l C / C + + Visual Basic

加+ + +

减- - -

乘* * *

浮点数除/ / /

整数除d i v / /

取模m o d % M o d

指数无无^

1、Object Pascal Object Pascal语言语言语言2 1 2 1 2 1

你可能注意到了P a s c a l 和Visual Basic 对浮点数和整型数除法运算用了不同的除法运算符,这点不

像在C / C + +语言中。在两个整数相除时,d i v 运算符自动截取余数取整。

注意对不同类型的表达式相除要选用不同的除法运算符,如果用div 运算符对两个浮点数或

用/运算符对两个整型数进行除法运算,Object Pascal 编译器将提示出错了,请看下面的代码:

许多其他语言不区分浮点数和整数相除,而是进行浮点数相除,然后根据需要将结果转化为整型

数,从性能上看,这可能开销要大一些,而P a s c a l 的d i v 运算符更快、更有效。

2.5.5 按位运算符

按位运算符能修改一个变量的单独各位。最常用的按位运算符能把一个数左移或右移,或对两个

表2-3 按位运算符

运算符P a s c a l C / C + + Visual Basic

与a n d & A n d

取反n o t ~ N o t

或o r O r

异或x o r ^ X o r

左移s h l < < 无

右移s h r > > 无

2.5.6 加减运算过程

加减运算过程用来对一个给定的整型数执行加1或减1运算,这是经过优化的代码, P a s c a l 不提供

像C + +中的+ +和- -等类似的运算符,但Pascal 提供了I n c ( )和D e c ( )来执行相同的功能。

用一个或两个参数来调用I n c ( )或D e c ( ),例如,下面的代码分别对v a r i a b l e 执行加1和减1 操作:

同上面相比较,用I n c ( )和D e c ( )分别对变量执行加3和减3操作:

表2 - 4列出了在不同语言中执行加减运算的运算符。

表2-4 加减运算符

运算符P a s c a l C Visual Basic

加I n c ( ) + + 无

减D e c ( ) - - 无

注意如果允许编译优化,Inc()和Dec()过程就产生如下的机器码语法:variable:=variable+1;

2 2 2 2 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

这将引起编译错误

这将引起编译错误

|

用这样的方法对变量进行加减运算,可能感到更方便。

2.6 Object Pascal 类型

Object Pascal 的最大特点是,它的数据类型特别严谨,这表示传递给过程或函数的实参必须和定

义过程或函数时的形参的类型相同。不可能在P a s c a l 中看到一些著名编译器例如C 编译器所提示的可疑

的指针转换等编译警告信息。这是因为Object Pascal 编译器不允许用一种类型的指针去调用形参为另

一种类型的函数(无类型的指针除外)。

2.6.1 类型的比较

D e l p h i 的基本数据类型跟C 和Visual Basic 的相同,表2 - 5对照列出了Object Pascal 的基本数据类型

以及C / C + +和Visual Basic 的基本数据类型。你可能想把这一页折起来,因为这张表提供了当在D e l p h i

中调用不是D e l p h i 的动态连接库( D L L )或目标文件( O B J )中的函数时用于匹配类型的最好的参考。

表2-5 Pascal 、C / C + +、Visual Basic 数据类型的对照

变量类型P a s c a l C / C + + Visual Basic

8位有符号整数S h o r t I n t c h a r 无

8位无符号整数B y t e B Y T E ,unsigned short B y t e

1 6位有符号整数S m a l l I n t s h o r t S h o r t

1 6位无符号整数Wo r d unsigned short 无

3 2位有符号整数I n t e g e r ,L o n g i n t i n t ,l o n g Integer Long

3 2位无符号整数C a r d i n a l ,L o n g Wo r d unsigned long 无

6 4位有符号整数I n t 6 4 _ i n t 6 4 无

4字节浮点数S i n g l e f l o a t S i n g l e

6字节浮点数R e a l 4 8 无无

8字节浮点数D o u b l e d o u b l e D o u b l e

8字节日期/时间T D a t e Ti m e 无D a t e

1 6字节v a r i a n t Va r i a n t ,O l e Va r i a n t , VARIANT Va r i a n t ①, Va r i a n t (缺省)

T Va r D a t a O l e Va r i a n t ①

1字节字符C h a r c h a r 无

2字节字符Wi d e C h a r W C H A R

固定长度字节的字符串S h o r t S t r i n g 无无

动态字符串A n s i S t r i n g A n s i S t r i n g ① S t r i n g

以N u l l 结束的字符串P C h a r c h a r * 无

以N u l l 结束的宽字符串P Wi d e C h a r L P C W S T R 无

动态2字节字符串Wi d e S t r i n g Wi d e S t r i n g ① 无

1字节布尔值B o o l e a n ,B y t e B o o l (任何1字节数) 无

2字节布尔值Wo r d B o o l (任何2字节数) B o o l e a n

4字节布尔值B O O L ,L o n g B o o l B O O L 无

① 模拟对应的Object Pasacl 类型的Borland C++ Builder 类。

注意如果要移植Delphi 1.0 的16位代码,请记住,无论是Integer 还是Cardinal 类型都已经从16

位扩展到3 2位。更准确地说,在Delphi 2和Delphi 3中,C a r d i n a l 被看作是3 1位的无符号整数,

在Delphi 4以后,Cardinal 才真正成为32位的无符号整数。

1、Object Pascal Object Pascal语言语言语言2 3 2 3 2 3

警告在Delphi 1、2和3中,R e a l 是6字节的浮点数,这是P a s c a l 特有的数据类型,和其他的语

言不兼容。在Delphi 4中,Real 是Double 类型的别名,6字节的浮点数仍然有,但现在是Real48。

通过编译开关{$REALCOMPATIBILITY ON}可以使Real 仍然代表6字节的浮点数。

2.6.2 字符

D e l p h i 有三种类型的字符:

? AnsiChar 这是标准的1字节的A N S I 字符,程序员都对它比较熟悉。

? WideChar 这是2字节的U n i c o d e 字符。

? Char 在目前相当于A n s i C h a r , 但在D e l p h i 以后版本中相当于Wi d e C h a r.

记住因为一个字符在长度上并不表示一个字节,所以不能在应用程序中对字符长度进行硬编码,

而应该使用S i z e o f ( )函数。

注意Sizeof()标准函数返回类型或实例的字节长度。

2.6.3 字符串

字符串是代表一组字符的变量类型,每一种语言都有自己的字符串类型的存储和使用方法。

P a s c a l 类型有下列几种不同的字符串类型来满足程序的要求:

? AnsiString 这是P a s c a l 缺省的字符串类型,它由AnsiChar 字符组成,其长度没有限制,同时与

n u l l 结束的字符串相兼容。

? ShortString 保留该类型是为了向后兼容Delphi 1.0,它的长度限制在2 5 5个字符内。

? WideString 功能上类似于A n s i S t r i n g ,但它是由Wi d e C h a r 字符组成的。

? PChar 指向n u l l 结束的C h a r 字符串的指针,类似于C 的char * 或l p s t r 类型。

? PAnsiChar 指向n u l l 结束的A n s i C h a r 字符串的指针。

? PWideChar 指向n u l l 结束的Wi d e C h a r 字符串的指针。

缺省情况下,如果用如下的代码来定义字符串,编译器认为是AnsiString 字符串:

v a r

S:string; //编译器认为S 的类型是A n s i S t r i n g

当然,能用编译开关$ H 来将s t r i n g 类型定义为S h o r t S t r i n g ,当$ H 编译开关的值为负时, s t r i n g 变量

是S h o r t S t r i n g 类型;当$ H 编译开关的值为正时(缺省情况),字符串变量是A n s i S t r i n g 类型。下面的代码 演示了这种情况:

S1:string; //S1是S h o r t S t r i n g 类型

{ $ H + }

S2:string; //S2是A n s i S t r i n g 类型

使用$ H 规则的一个例外是,如果在定义时特地指定了长度(最大在2 5 5个字符内),那么总是

S h o r t S t r i n g :

v a r

S: string[63]; //63个字符的S h o r t S t r i n g 字符串

1. AnsiString 类型

A n s i S t r i n g (或长字符串)类型是在Delphi 2.0开始引入的,因为Delphi 1.0的用户特别需要一个容易

使用而且没有2 5 5个字符限制的字符串类型,而A n s i S t r i n g 正好能满足这些要求。

2 4 2 4 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

1、Object Pascal Object Pascal语言语言语言2 52 52 5

虽然A n s i S t r i n g 在外表上跟以前的字符串类型几乎相同,但它是动态分配的并有自动回收功能,正

是因为这个功能A n s i S t r i n g 有时被称为生存期自管理类型。Object Pascal 能根据需要为字符串分配空间,

所以不用像在C / C + +中所担心的为中间结果分配缓冲区。另外, A n s i S t r i n g 字符串总是以n u l l 字符结束

的,这使得A n s i S t r i n g 字符串能与Win32 API 中的字符串兼容。实际上,A n s i S t r i n g 类型是一个指向在堆 栈中的字符串结构的指针。

警告Borland 没有将长字符串类型的内部结构写到文档中,并保留了在Delphi 后续版本中修改

长字符串内部格式的权利。在这里介绍的情况主要是帮助你理解A n s i S t r i n g 类型是怎样工作的

并且在程序中要避免直接依赖于AnisString 结构的代码。

程序员如果在Delphi 1.0中避免了使用字符串的内部结构,则把代码移植到Delphi 2.0没有

任何问题。而依赖于字符串内部结构写代码的程序在移植到Delphi 2.0时必须修改。

正如图2 - 1演示的,A n s i S t r i n g 字符串类型有引用计数的功能,这表示几个字符串都能指向相同的

物理地址。因此,复制字符串因为仅仅是复制了指针而不是复制实际的字符串而变得非常快。

图2-1 显示了AnsiString 在内存中分配的情况

当两个或更多的A n s i S t r i n g 类型共享一个指向相同物理地址的引用时, D e l p h i 内存管理使用了

c o p y - o n - w r i t e 技术,一个字符串要等到修改结束,才释放一个引用并分配一个物理字符串。下面的例

子显示了这些概念:

v a r

S 1 , S 2 : s t r i n g ;

b e g i n

/ /给S 1赋值,S 1的引用计数为1

S1:='And now for something...';

S2:=S1; //现在S 2与S 1指向同一个字符串, S 1的引用计数为2

/ / S 2现在改变了,所以它被复制到自己的物理空间,并且S 1的引用计数减1

S2:=S2+'completely diff e r e n t 1 ' ;

e n d ;

生存期自管理类型

除了A n s i S t r i n g 以外, D e l p h i 还提供了其他几种生存期自管理类型,这些类型包括:

Wi d e S t r i n g 、Va r i a n t 、O l e Va r i a n t 、i n t e r f a c e 、d i s p i n t e r f a c e 和动态数组,这些类型在本章稍后有 介绍,现在,我们重点讨论究竟什么是生存期自管理,以及它们是如何工作的。

生存期自管理类型,又被称为自动回收类型,是指那些在被使用时就占用一定的特殊资

源,而在它离开作用域时自动释放资源的类型。当然不同的类型使用不同的资源,例如,

A n s i S t r i n g 类型在被使用时就为字符串占用内存,当它超出作用域时就释放被字符串占用的内

插入代码来清除每一个生存期自管理类型的全局变量。因为在应用程序在被装入时,全局变量

都被初始化为0,每一个全局变量将用初始化时的0、空或其他值来指示它还没有被使用,基于

这种方法,终止代码只清除那些确实在应用程序中被使用的全局变量。

对于局部变量来讲,这种情况稍微有的复杂:首先,在过程或函数开始运行时,编译器

插入的代码保证初始化这些局部变量,接着,编译器产生一个t r y. . . f i n a l l y 的异常处理块,它包

分配的大小引用计数长度

下载

容整个函数体,最后,编译器在f i n a l l y 块插入代码来清除生存期自管理变量(异常处理块在2 . 1 9

节“结构化异常处理”中介绍),为了能记住这些,请看下面的代码:

procedure Foo;

v a r

S : s t r i n g ;

b e g i n

/ /过程体

/ /在这里用S

e n d ;

虽然这个过程看起来简单,如果考虑进由编译器插入的代码,它看起来像下面的代码:

procedure Foo;

v a r

S : s t r i n g ;

b e g i n

S:=' ';

t r y

/ /过程体

/ /在这里用S

f i n a l l y

/ /在这里清除S

e n d ;

e n d ;

(1) 字符串运算符

能用+运算符或C o n c a t ( )函数来连接两个字符串,推荐使用+运算符,因为C o n c a t ( )函数主要用来向

后兼容,下面代码演示了+运算符和C o n c a t ( )函数的用法:

注意在Object Pascal 中,通常用一对单引号来把字符串括起来,例如'A String'。

提示C o n c a t ( )是众多“编译器魔术”过程和函数中的一个,其他还有R e a d L n ( )、Wr i t e L n ( ) .、

它们没有Object Pascal 的定义。这些函数接收不确定个数的参数或可选的参数,它们不能根据

Object Pascal 语言来定义,正因为这样,编译器为每一个这样的函数提供了特殊的条件,并产

生一个对堆栈函数的调用,这些堆栈函数定义在S y s t e m 单元中,它们为了越过P a s c a l 的语言规

则,通常是用汇编语言实现的。

2 6 2 6 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

{用+运算符}

{ 用Concat() }

除了“编译器魔术”字符串函数和过程外,在S y s U t i l 单元中有许多函数和过程用来使字

符串更易使用,请查阅Delphi 的联机帮助“字符串处理例程”。

此外,可以在本书附带的C D - R O M 的\ S o u r c e \ U t i l s 目录中的S t r U t i l s 单元中找到更多用来处

第一次声明A n s i S t r i n g 时,它是没有长度的,因此在字符串中就没有为字符分配空间。为了对字符

串分配空间,用一行字母或另一个字符串对它进行赋值,或者用S e t L e n g t h ( )过程,就像下面所列出来

的:

v a r

S:string ; // 字符初始化时,没有长度

b e g i n

S : = ' D o h ! ' ; / /为字符串的字母分配足够的空间

{或者}

S : = O t h e r S t r i n g ; / /增加O t h e r S t r i n g 的引用计数,

/ / {假定O t h e r S t r i n g 指向一个合法的字符串}

{或者}

S e t L e n g t h ( S , 4 ) ; / /分配4个字符的空间

e n d ;

能像数组一样对字符串进行索引,但注意索引不要超出字符串的长度,例如,下面的代码会引起

一个错误:

v a r

S : s t r i n g ;

b e g i n

S[1]:='a'; //不能工作,因为S 没有被分配空间

e n d ;

然而,代码改成如下,就能正常工作了:

v a r

S : s t r i n g ;

b e g i n

S e t L e n g t h ( S , 1 ) ;

S[1]:='a'; //现在S 有足够空间来容纳字符

e n d ;

(3) Wi n 3 2的兼容

正如前面所提到,A n s i S t r i n g 字符串总是null 结束的。因此,它能跟以n u l l 结尾的字符串兼容,这

就使得调用Win32 API 函数或其他需要P C h a r 型字符串的函数变得容易了。只要把一个字符类型强制转

换为P C h a r 类型(在2 . 8节“强制类型转换和类型约定”中将介绍强制类型转换)。下面的代码演示了怎

样调用Wi n 3 2的G e t Wi n d o w s D i r e c t o r y ( )函数,这个函数需要一个P C h a r 类型的参数:

v a r

S : S t r i n g ;

b e g i n

SetLength(S,256); //重要!首先给字符串分配空间

/ /调用A P I 函数,S 现在包含目录字符串

G e t Wi n d o w s D i r e c t o r y ( P C h a r ( S ) , 2 5 6 ) ;

如果使用了将A n s i S t r i n g 字符串强制转换为P C h a r 类型的函数和过程,在使用结束后,要手工把它

1、Object Pascal Object Pascal语言语言语言2 72 7

的长度恢复为原来以n u l l 结束的长度。S T R U T I L S 单元中的R e a l i z e L e n g h t ( )函数可以实现这一点: procedure RealizeLength(var S:string);

b e g i n

S e t L e n g t h ( S , S t r L e n ( P C h a r ( S ) ) ) ;

e n d ;

S : s t r i n g ;

b e g i n

SetLength(S,256); //重要!首先给字符串分配空间

/ /调用函数,S 现在包含目录字符串

G e t Wi n d o w D i r e c t o r y ( P C h a r ( S ) , 2 5 6 ) ;

RealizeLength(S); //设置S 的长度为n u l l 结束的长度

e n d ;

注意在练习将一个字符串转换为P C h a r 类型时要小心,因为字符串在超出其作用范围时有自

动回收的功能,因此当进行P:=PChar(Str)的赋值时,P 的作用域(生存期)应当大于Str 的作用域。

(4) 移植性问题

当要移植Delphi 1.0 的应用程序时,一定要注意几个关于A n s i S t r i n g 的问题:

? 在使用P S t r i n g (指向S h o r t S t r i n g 字符串的指针)的地方,应当替换成s t r i n g 类型。记住:A n s i S t r i n g 已经是一个指向字符串的指针。

? 不能再通过字符串的第0个元素来设置或得到字符串的长度,只能通过L e n g t h ( )函数来得到字符

串的长度,通过S e t L e n g t h ( )过程来设置字符串的长度。

? 不再需要通过调用S t r P a s ( )和S t r P C o p y ( )来进行字符串与P C h a r 之间的转换,正如上面所提到的,

可以把AnsiString 强制类型转换为P C h a r 。如果要把P C h a r 的内容复制到A n s i S t r i n g ,直接用赋值

语句:

S t r i n g Var: =PCharVa r ;

警告对长字符串设置长度时,必须用SetLength()过程,过去那种通过直接访问字符串第0个元

素来设置长度的方法,在应用程序从16位的Delphi 1.0升级到32位时会出现问题。

2. ShortString 类型

如果你是一个D e l p h i 的老手,应该知道S h o r t S t r i n g 类型是Delphi 1.0中字符串的类型, S h o r t S t r i n g

类型有时又被称为Psacal 字符串(Psacal string)或长度-字节字符串(length-byte string)。请记住,$H 编

译开关的值用来决定当变量声明为字符串时,它是被当作A n s i S t r i n g 类型还是被当作S h o r t S t r i n g 类型。 在内存中,字符串就像是一个字符数组,在字符串的第0个元素中存放了字符串的长度,紧跟在

后的字符就是字符串本身。S h o r t S t r i n g 缺省的最大长度为2 5 6个字节,这表示在S h o r t S t r i n g 中不能有大 于2 5 5个字符( 2 5 5个字符+ 1个长度字节= 2 5 6 )。相对于A n s i S t r i n g 来说,用S h o r t S t r i n g

是相当随意的,因为编译器会根据需要为它分配空间,所以不用担心中间结果是不是

要预先分配内存。图2 - 2演示了P a s c a l 字符串在内存中的分配方式。

一个S h o r t S t r i n g 变量用下面的代码声明和初始化:

2 8 2 8 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

图2-2

当然,能用s h o r t 类型限定符和一个长度限制来为S h o r t S t r i n g 分配小于2 5 6个字节的空间,示例如

下:

如上代码,这个字符串肯定是S h o r t S t r i n g ,而不再受$ H 编译开关的影响,能指定的短字符串的最

大长度是2 5 5个字符。

不要存放比分配给字符串的空间长度更长的字符,如果声明了一个变量是s t r i n g [ 8 ],并试图对这

个变量赋值为‘a p r e t t y d a r n l o n g s t r i n g ’,这个字符串将被截取为仅有8个字符,就要丢失数据。

当用数组的下标来访问S h o r t S t r i n g 中的一个特定字符时,如果下标的索引值大于声明时S h o r t S t r i n g

的长度,则会得到假的结果或造成内存混乱。例如,假定像下面那样声明了一个变量:

v a r

S t r : s t r i n g [ 8 ] ;

如果试图写这个字符串的第1 0个元素,则有可能使其他变量的内存混乱。

v a r

b e g i n

i : = 1 0 ;

Str[i]:='s'; //内存混乱

可以在Project Options 对话框中选中Range Checking 复选框,这样编译器会自动加上特殊的逻辑在

运行时捕捉此类错误。

提示虽然在程序中包括范围检查能发现字符串错误,但范围检查多少都影响应用程序的性能。

通常使用的方法是在开发程序或调试程序的阶段用范围检查,而在确信程序稳定时,去掉范围

检查。

跟A n s i S t r i n g 类型字符串不一样, S h o r t S t r i n g 跟以n u l l 结尾的字符串不兼容,正因为这样,用

S h o r t S t r i n g 调用Wi n 3 2函数时,要做一些工作。下面这个S h o r t S t r i n g A s P C h a r ( )函数是在S T R U T I L S . PA S

单元中定义的。

func function ShortStringAsPChar(var S:ShortString):PChar;

{这函数能使一个字符串以n u l l 结尾,这样就能传递给需要P C h a r 类型参数的Win32 API 函数,如果字符串超过

2 5 4个字符,多出的部分将被截掉}

b e g i n

if Length(S)=High(S) then Dec(S[0]); { 如果S 太长,就截取一部分}

S[Ord(Length(S))+1]:=#0; { 把n u l l 加到字符串的最后}

Result:=@S[1]; { 返回P C h a r 化的字符串}

e n d ;

警告Win32 API 函数需要以n u l l 结尾的字符串,不要把S h o r t S t r i n g 字符串传递给A P I 函数,因

为编译器将报错,长字符串可以传递给Win32 API 函数。

2. Wi d e S t r i n g 类型

Wi d e S t r i n g 类型像A n s i S t r i n g 一样是生存期自管理类型,它们都能动态分配、自动回收并且彼此能

相互兼容,不过Wi d e S t r i n g 和A n s i S t r i n g 的不同主要在三个方面:

1、Object Pascal Object Pascal语言语言语言2 92 92 9

一个4 5个字符的S h o r t S t r i n g 字符串

? Wi d e S t r i n g 由Wi d e C h a r 字符组成,而不是由A n s i C h a r 字符组成的,它们跟U n i c o d e 字符串兼容。 ? Wi d e S t r i n g 用S y s A l l o c S t r L e n ( ) A P I 函数进行分配,它们跟O L E 的B S T R 字符串相兼容。

? Wi d e S t r i n g 没有引用计数,所以将一个Wi d e S t r i n g 字符串赋值给另一个Wi d e S t r i n g 字符串时,就

需要从内存中的一个位置复制到另一个位置。这使得Wi d e S t r i n g 在速度和内存的利用上不如

A n s i S t r i n g 有效。

就像上面所提到的,编译器自动在A n s i S t r i n g 类型和Wi d e S t r i n g 类型的变量间进行转换。示例如

下:

v a r

W: w i d e S t r i n g ;

S : s t r i n g ;

b e g i n

W: = ' M a r g a r i t a v i l l e ' ;

S : = W; // wideString 转换成A n s i S t r i n g

S:='Come Monday';

W:=S; // AnsiString 转换成Wi d e S t r i n g

e n d ;

为了能灵活地运用Wi d e S t r i n g 类型, Object Pascal 重载了C o n c a t ( )、C o p y 、I n s e r t ( )、L e n g t h ( )、 P o s ( )和S e t L e n g t h ( )等例程以及+、=和< >等运算符。下面的代码在语法上是正确的:

P : I n t e g e r ;

b e g i n

W 1 : = ' E n f i e l d ' ;

W 2 : = ' f i e l d ' ;

If W1<>W2 then

P : = P o s ( W 1 , W 2 ) ;

e n d ;

就像A n s i S t r i n g 和S h o r t S t r i n g 类型一样,能用数组的下标来访问Wi d e S t r i n g 中一个特定的字符:

v a r

W: Wi d e S t r i n g ;

C : Wi d e C h a r ;

b e g i n

W:='Ebony and Ivory living in prefect harmony';

C:=W[Length(W)]; //C 包含W 字符串的最后一个字符

e n d ;

4. 以n u l l 结束的字符串

正如前面所提到的, D e l p h i 有三种不同的以n u l l 结束的字符串类型: P C h a r 、PA n s i C h a r 和

P Wi d e C h a r 。它们都是由D e l p h i 的三种不同字符组成的。这三种类型在总体上跟P C h a r 是一致的。

P C h a r 之所以保留是为了跟Delphi 1.0和Win32 API 兼容,而它们需要使用以n u l l 结束的字符串,P C h a r

被定义成一个指向以n u l l (零)结束的字符串指针(如果对指针的概念不熟悉,

请继续读下去,在本章的后面要详细地介绍)。与A n s i S t r i n g 和Wi d e S t r i n g 类

型不同,P C h a r 的内存不是由Object Pascal 自动产生和管理的,要用O b j e c t

P a s c a l 的内存管理函数来为P C h a r 所指向的内存进行分配。P C h a r 字符串的

理论最大长度是4 G B ,P C h a r 变量在内存中的分布见图2 - 3。

3 0 3 0 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

图2-3 PChar 的内存分布

提示在大多数情况下,AnsiString 类型能被用成PChar ,应该尽可能地使用AnsiString ,因为它

对字符串内存的管理是自动,极大地减少了应用程序中内存混乱的错误代码,因此,要尽可能

地避免用PChar 类型以及对它相应进行人工分配内存。

正如在前面所提到的, P C h a r 变量需要人工分配和释放存放字符串的内存。通常,用S t r A l l o c ( )函

数为P C h a r 缓冲区分配内存,但是其他几种函数也能用来为P C h a r 类型分配函数,包括A l l o c M e m ( )、

G e t M e m ( )、S t r N e w ( )和VirtualAlloc() API 函数。这些函数有相应的释放内存的函数。表2 - 6列出了几个 分配内存的函数以及它们相应的释放内存的函数。

表2-6 内存分配和释放函数

内存分配函数内存释放函数

A l l o c M e m ( ) F r e e M e m ( )

G l o b a l A l l o c ( ) G l o b a l F r e e ( )

G e t M e m ( ) F r e e M e m ( )

N e w ( ) D i s p o s e ( )

S t r A l l o c ( ) S t r D i s p o s e ( )

S t r N e w ( ) S t r D i s p o s e ( )

Vi r t u a l A l l o c ( ) Vi r t u a l F r e e ( )

下面的例子演示了使用P C h a r 和s t r i n g 类型时的内存分配技术:

v a r

P 1 , P 2 : P C h a r ;

P 1 : = S t r A l l o c ( 6 4 * S i z e O f ( C h a r ) ) ; / / P 1指向一个分配了6 3个字符的缓冲区

StrPCopy(P1,'Delphi 5'); / /复制一组字母到P 1

S1:='Developer's Guide'; / /在S 1中放几个字母

P 2 : = S t r N e w ( P C h a r ( S 1 ) ) ; / / P 2指向S 1的备份

S t r C a t ( P 1 , P 2 ) ; / /连接P 1和P2

S2:=P1; //S2现在为'Delphi 5 Developer's Guide ’

S t r D i s p o s e ( P 1 ) ; / /清除P 1和P 2的缓冲区。

S t r D i s p o s e ( P 2 ) ;

e n d .

首先注意到,在为P 1分配内存时S t r A l l o c ( )中用到的S i z e O f ( c h a r )。要记住在以后D e l p h i 版本中一个 字符的长度要从一个字节变成两个字节,因此,不能假定一个字符的长度为一个字节, Sizeof() 就保

证了不管字符长度是多少都能正确地分配内存。

S t r C a t ( )用来连接两个P C h a r 字符串。注意,这里不能像对长字符串和S h o r t S t r i n g 类型那样用+运算

符来连接两个字符串。

S t r N e w ( )函数用来把字符串S 1中的值拷贝到P 2中,使用这个函数要小心,要避免出现内存被覆盖

的错误,因为S t r N e w ( )函数只为字符串分配足够但不浪费的内存,请看下面的例子:

v a r

P 1 , P 2 : P C h a r ;

b e g i n

P 1 : = S t r N e w (‘H e l l o ’) ; / /只分配够P 1用的内存

P 2 : = S t r N e w (‘Wo r l d ’) ; / /只分配够P 2用的内存

S t r C a t ( P 1 , P 2 ) ; / /小心:内存出现混乱了!

1、Object Pascal Object Pascal语言语言语言3 13 1

.e n d ; 提示和其他字符串类型一样,Object Pascal 也为操作P C h a r 类型提供了一些操作函数和过程,

请在Delphi 的联机帮助“String-handing routines(null-terminated)”。

另外,还可以在本书附带的C D - R O M 的\ S o u r c e \ U t i l s 目录中的S t r U t i l s 中找到更多的针对以n u l l 结束 的字符串的过程和函数。

2.6.4 变体类型

Delphi 2.0引进了一个功能强大的数据类型,称为变体类型( Va r i a n t ),主要是为了支持O L E 自动化

操作。实际上, D e l p h i 的Va r i a n t 封装了O L E 使用的Va r i a n t ,但D e l p h i 的Va r i a n t 在D e l p h i 程__________序的其他领域

也很有用。正如不久就要学到的, Object Pascal 是唯一能在运行期间和编译期间识别Variant 的语言。

Delphi 3引进了一个新的被称为O l e Variant 类型,它跟Va r i a n t 基本一致,但是它只能表达与OLE 自

动化操作相兼容的数据类型。本节介绍Va r i a n t ,然后介绍O l e Va r i a n t ,并对两者进行比较。

1. Va r i a n t 能动态改变类型

有时候变量的类型在编译期间是不确定的,而Va r i a n t 能够在运行期间动态地改变类型,这就是引

入Variant 类型目的。例如,下面的代码在编译期间和运行期间都是正确的:

v a r

V: Va r i a n t ;

b e g i n

V:='Delphi is Great!'; //Variant 此时是一个字符串

V: = 1 ; / / Variant 此时是一个整数

V: = 1 2 3 . 3 4 ; / / Variant 此时是一个浮点数

V: = Tr u e ; / / Variant 此时是一个布尔值

Va r i a n t 能支持所有简单的数据类型,例如整型、浮点型、字符串、布尔型、日期和时间、货币以

及O L E 自动化对象等。注意Va r i a n t 不能表达Object Pascal 对象。Va r i a n t 可以表达不均匀的数组(数组的

长度是可变的,它的数据元素能表达前面介绍过的任何一种类型,也可包括另一个Va r i a n t 数组)。

2. Va r i a n t 的结构

Va r i a n t 类型的数据结构是在S y s t e m 单元中定义的,如下所示:

3 2 3 2 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

1、Object Pascal Object Pascal语言语言语言3 33 33 3

T Va r D a t a 结构占用1 6个字节的内存,T Va r D a t a 结构的头两个字节中的值用于指示v a r i a n t 代表的数

据类型,下面的代码显示了可能出现在T Va r D a t a 结构中V Ty p e 域中的各种值。紧接的6个字节是保留的, 剩下的8个字节包含实际的数值或一个指向由Va r i a n t 表示的数据的指针。另外,这个结构直接映射了

O L E 的Va r i a n t 类型的实现。

注意在上面的列表代码中你可能发现,Variant 不能代表指针和类。

可能在T Va r D a t a 列表中注意到, T Va r D a t a 记录是一个可变记录。不要把它跟Va r i a n t 类型相混淆,

虽然可变记录和Va r i a n t 类型在英文中的名字相同,但它们代表了两个完全不同的概念。可变记录允许

多个数据域重叠在相同的内存(像C / C + +中的联合类型),这将在本章的2 . 7 . 3节“记录”中详细介绍。

在T Va r D a t a 可变记录中的c a s e 语句指示了v a r i a n t 类型所代表的数据的类型,例如:如果V Ty p e 域包含的

值为Va r I n t e g e r ,T Va r D a t a 记录的8个字节中的4个字节用来存放一个整型值;如果V Ty p e 的值为Va r B y t e , 8个字节中仅有1个字节存放数据。

你可能注意到了V Ty p e 的值可以为Va r S t r i n g ,这时8个字节并不存放真正的字符串,它存放指向字

符串的指针,这是很重要的一点,因为它能直接访问一个Va r i a n t 的域,示例如下:

{ Va r i a n t 类型代码}

3 4 3 4 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

你必须明白,在某些情况下这是个危险的操作,因为它可能导致对字符串或其他生存期自管理类

型的引用丢失,这将引起应用程序内存错误。在下面一节你就会明白“自动回收”的含义。

3. Va r i a n t 是生存期自管理的

D e l p h i 自动分配和释放Va r i a n t 类型所需的内存,请看下面的例子,对一个Va r i a n t 变量赋了字符串:

在本章的前面讨论了生存期自管理类型,有几种情况没有讲清楚,现在继续。首先D e l p h i 将

Va r i a n t 初始化为一个不确定的值。在赋值期间,它把V Ty p e 域设为Va r S t r i n g ,并把字符串指针拷贝到 它的V S t r i n g 域,然后增加字符串S 的引用计数。当这个Va r i a n t 类型的变量离开其作用域时(过程结束或

调用了返回代码),它被清除并减少S 的引用计数,D e l p h i 是通过插入t r y. . . f i n a l l y 代码块来隐式实现这个 过程的,示例如下:

当另一种类型的数据赋值给v a r i a n t 变量时,也会隐式地释放资源,请看下面的代码:

这段代码是下列伪代码的具体体现:

如果理解了上面的代码,就明白为什么不建议你直接对T Va r D a t a 记录的域进行操作,请看下面的

例子:

// 将v a r i a n t 初始化为“空”

// 现在清除和v a r i a n t 有关的资源

清除变量V ,确保它初始化为“空”;

清除变量V ,释放对字符串S 的引用

清除与变量V 有关的资源

虽然这段代码看起来很安全,但它可能引起内存错误。作为一条普遍的规则,请不要直接访问

能显式地把一个表达式强制类型转换成Va r i a n t 类型,例如,表达式:

使得Va r i a n t 中的类型代码跟表达式x 的结果的数据类型一致, x 的结果的数据类型必须是整数、实

数、货币型、字符串、字符或布尔型。

也可以把Va r i a n t 类型的表达式强制类型转换为简单类型,例如:

其中,V 是一个Va r i a n t 类型的变量,下面的代码对变量V 进行转换:

S:=String(V); / / S 现在是字符串1 . 6

I : = I n t e g e r ( V ) ; / / I 现在取整为整数2

B:=Boolean(V); / /如果V 的值为0,则B 为F a l s e ,否则为Tr u e ;

D:=Double(V); / / D 现在为浮点数1 . 6

这是根据类型转换规则将Va r i a n t 类型转换成简单类型的结果,关于类型转换规则的详细细节在

D e l p h i 的Object Pascal Language Guide 中。

顺便说一下,在上面的例子中没有必要通过强制类型转换,只要用赋值语句就能实现,下面的代

码是正确的:

在这里转换成目标数据类型是隐式发生的。不过,由于转换是在运行期间进行的,编译器会对这

段程序附加许多代码。如果确切地知道Va r i a n t 所包含数据的类型,最好用显式地强制类型转换,以加

快速度,尤其当Va r i a n t 出现在表达式中时。关于这一点将在后面讨论。

5. 表达式中的Va r i a n t

能在表达式中用Va r i a n t ,并通过=、*、/、d i v 、m o d 、s h l 、s h r 、a n d 、o r 、x o r 、n o t 、: =、< >、<、 >、< =和> =进行运算。

当Va r i a n t 变量出现在表达式中时, D e l p h i 知道怎样基于Va r i a n t 中的内容进行运算,例如,如果有

V 1和V 2两个Va r i a n t 类型的变量,它们都包含整型数,那么表达式V 1 + V 2的结果是两个整型数的和;然

而,如果V 1和V 2是两个字符串,那么结果是两个字符串的连接。那么,如果V 1和V 2中包含不同类型

的数据那又怎样呢? D e l p h i 为了能执行运算用了更复杂的规则,例如,如果V 1包含字符串‘ 4 . 5’,而

V 2包含一个浮点数,那么V 1将被转换成一个浮点数并加上V 2的值,下面的代码演示了这样的规则:

var

V 1 , V 2 , V 3 : Va r i a n t ;

b e g i n

1、Object Pascal Object Pascal语言语言语言3 53 5

V 1 : = ' 1 0 0 ' ; / / V 1包含一个字符串类型

V2:='50'; / / V 2包含一个字符串类型

V 3 : = 2 0 0 ; / / V 3包含一个整型数

V 1 : = V 1 + V 2 + V 3 ;

e n d ; 基于上面所提到的复杂的规则,这段代码的结果乍一看是整型数3 5 0;然而,如果你仔细看,就

发现情况并非如此。因为代码的执行顺序是从左向右,首先是执行V 1 + V 2,因为两个v a r i a n t 变量都包

含了字符串,所以执行字符串连接运算,结果为字符串‘ 1 0 0 5 0’;然后这个结果再加上在V 3中包含的

整型数,因为V 3包含的是整型数,所以字符串‘ 1 0 0 5 0’转换成一个整型数并加上2 0 0,这样最后结果

是1 0 2 5 0。

为了能顺利地计算,在等式中, D e l p h i 尽量把Va r i a n t 转换成有利于运算的类型,如果D e l p h i 碰到

了搞不清的表达式,就会触发一个“Invalid variant type conversion ”异常,示例如下:

正如上面所提到的,如果知道在表达式中要进行运算的数据的类型,最好把Va r i a n t 变量显式地转

换,看下面的例子:

在这个等式的最后结果出来以前,会有一个运行期的函数对这个表达式中的各个操作数进行兼容

性检查,然后进行必要的转换。这将导致额外的开销。一种最好的解决方法是不要用Va r i a n t 类型,如

果确实要用,最好显式地对Va r i a n t 变量进行类型转换,这样有关数据类型的转换在编译期间就能完成,

6. 空和n u l l

在这里简单介绍Va r i a n t 变量中V Ty p e 的两个特殊的值,第一个是v a r E m p t y ,这表示这个Va r i a n t 还

没有赋值,这是当这个变量进入作用域时由编译器给它指定的初始值。另一个是v a r N u l l ,它跟

v a r E m p t y 最大的区别是,它确实代表了一个数值n u l l ,而不是没有值。没有值和值为n u l l 在涉及到数据 库表的字段值运算时显得尤其重要。在第2 8章“编写桌面数据库应用程序”中,会看到在数据库应用

程序中Va r i a n t 变量是怎样被应用的。

另一个不同的地方是,在执行有Va r i a n t 变量的等式而Va r i a n t 变量的V Ty p e 值为v a r E m p t y 时,会产

生“invalid variant operation ”异常。如果V Ty p e 的值为v a r N u l l ,就不会有这种情况。如果一个表达式

中包含值为n u l l 的Va r i a n t 变量,则整个表达式的结果为n u l l 。

如果想用v a r E m p t y 或Va r N u l l 对一个Va r i a n t 变量进行赋值或比较,在S y s t e m 单元中提供了两个特殊 的值U n a s s i g n e d 和n u l l ,它们的V Ty p e 值分别为v a r E m p t y 和v a r N u l l 。

警告由于Va r i a n t 类型提供了更灵活的机制,你可能想用Va r i a n t 类型来代替传统的数据类型。然

而,这将增加程序代码长度,并使得程序运行起来很慢。另外它也使得程序代码很难维护。在

有些情况下Va r i a n t 特别有用。事实上,V C L 中有好几个地方都用到了v a r i a n t ,尤其是在A c t i v e X

和数据库领域。因为这些地方需要复杂的数据类型。一般来说,应当使用传统的数据类型,除

非对灵活性的要求超过了对程序性能的要求。不确定的数据类型会产生不确定的缺陷。

3 6 3 6 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

// 产生异常

7. Va r i a n t 数组

前面曾经提到过,v a r i a n t 能表达不均匀的数组,下面的代码在语法上是合法的:

请记住,虽然上面的代码在编译时能通过,但在运行时会得到一个异常。因为V 不是一个Va r i a n t

类型的数组,Object Pascal 提供了若干支持Va r i a n t 数组的函数,允许建立Va r i a n t 数组,下面就有两个:

Va r A r r a y C r e a t e ( )和Va r A r r a y O f ( )。

(1) Va r A r r a y C r e a t e ( )函数

Va r A r r a y C r e a t e ( )函数在S y s t e m 单元中是这样定义的:

为了用Va r A r r a y C r e a t e ( )函数,必须传递想要建立数组的边界和数组中每个元素的类型代码(第一

个参数是开放数组,关于它将在本章的2 . 1 2节详细介绍),下面的代码创建一个元素为整型的Va r i a n t 数

组,并对每一个元素赋值:

如果知道了怎样用简单的数据类型创建v a r i a n t 数组,就能把v a r Va r i a n t 作为建立v a r i a n t 数组的类型

代码传递给函数。这样在数组中的每一个数据都可以有不同的类型。同时能通过传递附加的边界来创

建一个多维数组,下面的例子创建了一个边界为[1..4, 1..5]的数组:

(2) Va r A r r a y O f ( )

Va r A r r a y O f ( )函数在S y s t e m 单元中是这样定义的:

这个函数创建一个一维数组,它的元素由Va l u e s 参数指定,下面的例子创建了一个数组,它的三

个元素分别为整型、字符串型和浮点数型:

(3) 与Va r i a n t 数组相关的函数和过程

除了Va r A r r a y C r e a t e ( )和Va r A r r a y O f ( ) ,在S y s t e m 单元中定义了多个支持Va r i a n t 数组的函数和过程, 列表如下:

1、Object Pascal Object Pascal语言语言语言3 73 7

// 创建一个4个元素的数组 Va r A r r a y R e d i m ( )函数能修改v a r i a n t 数组的最高限。Va r A r r a y D i m C o u n t ( )函数返回Va r i a n t 数组的维 数,Va r A r r a y L o w B o u n d ( )和Va r A r r a y H i g h B o u n d ( )函数分别返回Va r i a n t 数组的下边界和上边界。 Va r A r r a y L o c k ( )和Va r A r r a y U n l o c k ( )函数比较特殊,将在下一节介绍。

Va r A r r a y R e f ( )主要用来解决向O L E 服务器传送Va r i a n t 数组时要出现的问题。当向自动化服务器的

如果自动化服务器希望接收一个v a r i a n t 数组而不是指向它的一个引用,如果用上面的语法来调用自动

化的方法,就会产生一个错误。在这种情况下就要用Va r A r r a y R e f ( ),示例如下:

Va r I s A r r a y ( )函数是一个简单的布尔检查函数,如果传递给它的参数是一个Va r i a n t 数组则返回Tr u e , 否则返回F a l s e .

(4) 用Va r A r r a y L o c k ( )和Va r A r r a y U n l o c k ( )初始化一个大数组

Va r i a n t 数组在O L E 自动化技术中尤其重要,因为它提供了向O L E 服务器传送二进制数据的唯一的

方法(就像你在第2 3章“C O M 和A c t i v e X ”要学到的,这时指针不再有效)。然而,如果用得不正确,它

也会产生负作用。请看如下代码:

它创建一个有10 000字节的Va r i a n t 数组。假定有另一个相同长度的非Va r i a n t 类型的数组,并且想

把非v a r i a n t 类型的数组复制到v a r i a n t 类型的数组中去。通常这都是通过用循环语句对v a r i a n t 数组的单 元进行赋值实现的。示例如下:

上面这段代码的主要问题在于,大量的时间花费在对Variant 数组的初始化上,因为在对每一个元

素进行赋值时,都要通过运行时逻辑来检查并判断数据类型的兼容性、每个元素的位置等等。为了避

免运行时检查,要用Va r A r r a y L o c k ( )函数和Va r A r r a y U n l o c k ( )过程。

Va r A r r a y L o c k ( )函数在内存中锁定数组,使数组不再移动和改变大小,并能返回一个指向数组数

据的指针。而Va r A r r a y U n l o c k ( )过程用来对Va r A r r a y L o c k ( )函数锁定的数组进行解锁,使数组能重新移 动或改变大小。在锁定数组后,能用更有效的方法对数组进行初始化,例如用指向数组数据的指针调

用M o v e ( )过程,下面的代码也对Va r i a n t 数组进行初始化,但它更有效:

8. 其他支持Va r i a n t 的函数

还有其他一些函数支持Va r i a n t ,它们都定义在S y s t e m 单元中,下面是这些函数:

3 8 3 8 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

Va r C l e a r ( )过程清除Va r i a n t 变量并将V Ty p e 域的值设为v a r E m p t y.

Va r C o p y ( )将S o u r c e 复制到D e s t 。

Va r C a s t ( )将一个Va r i a n t 转换成指定的类型并存储在另一个Va r i a n t 变量中。

Va r Ty p e ( )返回指定Va r i a n t 的v a r X X X 类型代码。

Va r A s Ty p e ( )跟Va r C a s t ( )的功能一样。

Va r I s E m p t y ( )如果一个Va r i a n t 变量的类型代码是varEmpty 则返回Tr u e 。

VarIsNull() 判断Va r i a n t 变量是否包含n u l l 值。

Va r To S t r ( )将一个Va r i a n t 变量转换成字符串表达式(如果Va r i a n t 为v a r E m p t y 或v a r N U l l 则为空字符 串)。

Va r F r o m D a t e Time() 返回一个Va r i a n t 变量,它存放着指定的T D a t e Ti m e 类型的值。

Va r To D a t e Time() 返回在Va r i a n t 中的T D a t e Ti m e 类型的值。

9. OleVa r i a n t

O l e Va r i a n t 与Va r i a n t 很相像,两者的差别在于O l e Va r i a n t 仅支持跟自动化相兼容的类型。目前,不

能跟自动化相兼容的V Ty p e 是Va r S t r i n g ,即A n s i S t r i n g 类型。当试图把A n s i S t r i n g 字符串赋值给一个 O l e Va r i a n t 变量时,A n s i S t r i n g 自动转化为OLE BSTR 类型并作为v a r O l e S t r 存储在Va r a i n t 变量中。

2.6.5 Currency

在Delphi 2.0中引进了一种新的数据类型C u r r e n c y 。它的主要目的是用来进行财经计算,它不同于

能在数字间移动小数点的浮点数,它的小数点是固定的,在小数前有1 5位数字,在小数点后有4位数字。

当移值Delphi 1.0的程序并涉及到货币时,最好用C u r r e n c y 来代替S i n g l e 、r e a l 、D o u b l e 和E x t e n d e d 。

2.7 用户自定义类型

整型、字符串型和浮点数型不能足够地表达在现实世界中的情况,而这些情况往往是需要程序来

解决的。为了弥补这种不足,必须建立新的数据类型来表示现实问题中的变量。在P a s c a l 中,这种用

户自定义类型用记录( r e c o r d )或对象( o b j e c t )来表示。

2.7.1 数组

它相当于C 语言中的:

另外,它相当于Visual Basic 中的

Object Pascal 的数组有一个不同于其他语言的特性,它们的下标不必以某个数为基准。像下面的

1、Object Object Pascal Pascal Pascal语言语言语言3 93 93 9

例子,能从2 8开始定义一个有3个元素的数组:

因为Object Pascal 的下标不是必须从0或1开始的,在f o r 循环中使用数组时一定要小心。在编译器

中有两个内置的函数High() 和L o w ( ),它们分别返回一个数组变量或数组类型的上边界和下边界。在

for 循环中用这两个语句能使程序更加稳定和易于维护,示例如下:

提示字符的数组通常以0为基准,它能用来传递给需要PChar 类型变量的函数,这是编译器特

别允许的。

为了定义多维数组,用逗号开,示例如下:

为了访问多维数组,在方括号中用逗号隔开每一维:

2.7.2 动态数组

动态数组是在编译时不知道维数,在运行时动态分配的数组。为了声明一个动态数组,只要在声

明时不要指定维数,就像这样:

在用动态数组前,用S e t L e n g t h ( )过程为数组分配内存:

一旦空间被分配了,你就能像访问普通数组一样访问动态数组:

注意动态数组通常是以0为基准的。

动态数组是生存期自管理的,所以在用完它们以后没有必要释放,因为在离开作用域时它们会被

释放。然而,可能在离开作用域前,就需要删除动态数组(例如它用了很多内存)。要这么做,仅需要

把n i l 赋值给动态数组:

SA:=nil; //释放S A

利用引用对动态数组进行操作,在语义上类似于A n s i S t r i n g 类型,而不像普通的数组。这里有一个

小实验:在下面的代码运行结束后A 1 [ 0 ]的值是多少?

4 0 4 0 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

// 不要把在循环中硬编码!

// 整型的二维数组

// 字符串的动态数组

// 为3 3个元素分配空间

正确答案是2 6!,因为赋值语句A 2 : = A 1并不创建新的数组,仅将A 1数组的引用赋给A 2,因此对

A 2数组的任何操作都影响到A 1。如果想用A 1的完全拷贝赋值给A 2,用标准过程C o p y ( ) :

当这行代码运行结束, A 1和A 2是两个独立的数组,但它们的初始值是相同的,改变其中的一个

不会影响到另一个。在调用C o p y ( )时,能任意指定起始单元和要复制的元素个数,例如:

/ /从元素1开始,复制2个元素

A2:=Copy(A1,1,2);

动态数组也能定义为多维的。为了定义多维数组,在声明时对每一维用一个a r r a y 关键字:

在为了给动态数组分配空间调用S e t L e n g t h ( )时,也要将另一维的长度传递过去:

访问多维动态数组跟访问多维普通数组一样,在方括号中每一个元素用逗号隔开:

2.7.3 记录

在Object Pascal 中用户自定义的结构被称为记录。它相当于C 语言中s t r u c t ,Visual Basic 中的Ty p e 。

下面的例子对三者进行了比较:

当使用记录时,用小圆点来访问它的域,下面是例子:

Object Pascal 也支持可变记录,它允许在记录中不同的数据共同覆盖相同的内存。不要跟Va r i a n t

1、Object Pasca Object Pascal l 语言语言4 14 1

// IA 是一个5×5的整型数组

数据类型相混淆,可变记录允许彼此覆盖的数据能被单独访问。如果对C / C + +语言很熟悉,你一眼就

能看出来它跟C / C + +中的u n i o n 概念一样。下面的例子演示了一个可变记录,其中D o u b l e 、I n t e g e r 和

c h a r 共同占用了相同的内存:

注意Object Pascal 规则声明:一个记录的可变部分不能是生存期自管理的类型。

如果在C 语言中就是这样定义的:

2.7.4 集合

集合是P a s c a l 特有的数据类型,在Visual Basic 、C 或C + +都没有(虽然C++ Builder 提供了一种模板

类称为集合,它模仿P a s c a l 集合的行为)。集合用一种有效的手段来表示一组有序数、字符和枚举值。

声明一个集合用关键字set of ,并在其后跟上有序类型或一个集合可能值的有限子集。示例如下:

t y p e

TCharSet=set of char; // 可能的值:# 0 - # 2 5 5

T E n u m = ( M o n d a y, Tu e s d a y, We d n e s d a y, T h u r s d a y, F r i d y ) ;

TEnumSet=set of TEnum; // 包含了T E n u m 值的任何组合

TSubrangeSet=set of 1..10; // 可能的值:1 - 1 0

TAlphaSet=Set of 'A'..'z'; // 可能的值:' A ' - ' z '

注意,一个集合最多只能有2 5 5个元素。另外,只有有序的类型才能跟关键字set of ,因此下列的

代码是非法的:

t y p e

TIntSet=set of Integer; // 非法:太多的元素

TStrSet=set of string; // 非法:不是有序的类型

集合在内部以位的形式存储它的元素,这使得在速度和内存利用上更有效。集合如果少于3 2个元

素,它就存储在C P U 的寄存器中,这样效率就更高了,为了用集合类型得到更高的效率。记住,集合

的基本类型的元素数目要小于3 2。

1. 使用集合

当使用集合的元素时,使用方括号。下面代码表明如何使用集合类型的变量并给它赋值。

4 2 4 2 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

2. 集合操作符

Object Pascal 提供了几个用于集合的运算符,用这些运算符可以判断集合和集合之间的关系,对

集合增删元素,对集合进行求交集运算。

(1) 关系运算

用i n 运算符来判断一个给定的元素是否在一个集合中,下面的代码判断在前面所定义的集合

C h a r S e t 中是否有字母‘S ’:

if 'S' in CharSet then

/ /继续运行

下面的代码判断在E n u m S e t 中是否没有M o n d a y :

if not (Monday in EnumSet) then

/ /继续运行

(2) 增删元素

用+、-运算符或I n c l u d e ( )和E x c l u d e ( )过程,能对一个集合变量增删元素:

Include(CharSet, 'a'); / /在集合中增加' a ' ;

C h a r S e t : = C h a r S e t + [ ' b ' ] ; / /在集合中增加' b ' ;

Exclude(CharSet, 'x'); / /在集合中删除' x ' ;

CharSet:=CharSet-['y', 'z']; / /在集合中删除' y '和' z ' ;

提示尽可能地用Include()和Exclude()来增删元素,尽可能地少用+、-运算符。因为Include()和

用*运算符来计算两个集合的交集,表达式S e t 1 * S e t 2的结果是产生的集合的元素在S e t 1和S e t 2集合

中都存在,下面的例子用来判断在一个给定的集合中是否有某几个元素:

if {'a', 'b', 'c'}*CharSet={'a', 'b', 'c'} then

/ /继续程序

2.7.5 对象

可以将对象类型当作是记录类型,只是它还包括了函数和过程。D e l p h i 的对象模型在后面2 . 1 7节

“使用D e l p h i 的对象”中详细介绍。所以这一节主要介绍Object Pascal 对象的基本语法。一个对象被定

义成这样:

1、Object Pascal Object Pascal语言语言语言4 3 4 3

虽然D e l p h i 的对象和C + +中的对象不完全一样,但上面的代码大致和在C + +中的定义相同:

要定义一个方法,类似于定义函数和过程(在2 . 1 2节“过程和函数”中讨论),只是要加上对象名

字和小圆点. :

Object Pascal 中的小圆点. 在功能上类似于Visual Basic 中的. 运算符和C + +的: :运算符。虽然三种

语言都允许使用类,但只有Object Pascal 和C + +允许以完全面向对象的方法定义新类,关于这一点在

2 . 1 6节“面向对象编程”中详细介绍。

注意Object Pascal 的对象和C + +的对象在内存中的布局不一样。因此,在D e l p h i 中不能用C + +

的对象,反过来也是一样,不过,第13章“核心技术”将介绍在Delphi 和C++中如何共享对象。

一个例外的情况是,在Borland C++ Builder 中创建的新类,用_ d e c l s p e c ( d e l p h i c l a s s )指令可

以直接映射为Object Pascal 类。但这样的类与普通C++对象不兼容。

2.7.6 指针

一个指针变量指示了内存的位置,在本章介绍P C h a r 类型时,就有使用指针的例子, P s a c a l 通用指

针类型的名称是P o i n t e r 。P o i n t e r 有时又被称为无类型指针,因为它只指向内存地址,但编译器并不管

指针所指向的数据,这一点与P a s c a l 严谨的风格似乎不相称,所以建议你在大部分情况下用有类型的

指针。

注意指针是一种高级技术,对于编写程序来说不是必须的,当你对它运用熟练以后,它会成

为你写程序的好工具。

有类型指针在你的应用程序的Ty p e 部分用^ (或p o i n t e r )运算符声明。对于有类型指针来说,编译器

能准确地跟踪指针所指内容的数据类型,这样用指针变量,编译器就能跟踪正在进行的工作。以下是

声明指针的例子。

Ty p e

P I n t = ^ I n t e g e r ; // PInt 现在是指向I n t e g e r 的指针

F o o = r e c o r d // 一个记录类型

GobbledyGook: string;

S n a r f : R e a l ;

e n d ;

PFoo=^Foo; // PFoo 是一个指向f o o 类型的指针

v a r

P:Pointer; // 一个无类型的指针

P2:PFoo; // PFoo 的实例

注意C 语言的程序员可能注意到了,Object Pascal 的^运算符与C 语言中*运算符相似,P a s c a l

4 4 4 4 第一部分快速开开的基础第一部分快速开开的基础第一部分快速开开的基础

{ 过程体}

的Pointer 类型对应与C 的void *类型。

要记住一个指针变量仅仅是存储一个内存的地址,为指针所指向的内容分配空间是程序员要干的

Pascal语言精要

Pascal 语言精要 基本概念:标识符、保留字、常量、变量、运算符、表达式、标准数据类型 Pascal 数 据 类 型 简单类型 标准类型 整型 integer -32768~32767 shortint -128~127 longint -2147483648~2147483647 byte 0~255 word 0~65535 实型 real 绝对值在1E-38~1E38间 singel (单精度型) double (双精度型) extended (扩展型) comp (装配十进制型) 字符型 char (字符) string (字符串) boolean 只有两个值true 和false 用户自定义类型 枚举型 子界型 构造类型 数组类型 记录类型 集合类型 文件类型 指针类型 PASCAL 标准数据类型一共有4个:整型、实型、字符型、布尔型,分别用保留字integer 、real 、char 、boolean 来标记它们。其取值范围和运算如下: 整型(integer):范围 -32768—32767(16位运算);运算 + - * / mod div 实型(real): 范围 运算 + - * / 字符型(char): 范围 可显示的ASCII 字符 布尔型(boolean):范围 true false ;运算 and or not 1.整型 类型 数值范围 占字节数 格式 shortint -128..128 1 带符号8位 integer -32768..32767 2 带符号16位 longint -2147483648..2147483647 4 带符号32位 byte 0..255 1 带符号8位 word 0..65535 2 带符号16位 Pascal 规定了两个预定义整型常量标识符maxint 和maxlongint ,他们各表示确定的常数值,maxint 为32767, maxlongint 为2147483647,他们的类型分别是integer 和longint 2.实型 Pascal 支持五种预定义实型,它们是real (基本实型)、 single (单精度实型)、double (双精度实型)、extended (扩展实型)、comp (装配实型),Pascal 分别用不相同的名字

Pascal语言编程基础程序

Pascal语言编程基础程序 (常州市) 十进制转二进制 var i,n,j:longint; a:array[1..100] of longint; begin readln(n); i:=1; while n<>0 do begin a[i]:=n mod 2; i:=i+1; n:=n div 2; end; write('Bin:'); for j:= i-1 downto 1 do write(a[j]) end. 数组元素删除 var a:array[1..10]of longint; i,t,x:longint; begin read(x); for i:=1 to 10 do a[i]:=2*i-1; t:=a[x]; for i:=x+1 to 10 do a[i-1]:=a[i]; for i:=1 to 9 do write(a[i]:4); end. 数组元素删除2 var a:array[1..11]of longint; i:longint; begin for i:=1 to 10 do a[i]:=i; a[11]:=a[1]; for i:= 1 to 10 do a[i]:=a[i+1]; for i:= 1 to 10 do write(a[i]:4); end. 数组元素的移动 var a:array[1..10] of longint; s,n,i,x,t:longint; begin readln(n); for i:=1 to n do read(a[i]); readln(x); s:=a[x]; for i:=x+1 to n do a[i-1]:=a[i]; for i:=1 to n-1 do write(a[i],' '); write(s); end. 排除所有异形基因 var a:array[1..100] of longint; n,g,j,i,wz:longint; begin readln(n); for i:=1 to n do read(a[i]); g:=0; for i:=1 to n do if sqr(a[i]) mod 7=1 then begin wz:=i; for j:=wz+1 to n do a[j-1]:=a[j]; g:=g+1 end; write(a[1]); for i:=2 to n-g do write(' ',a[i]); writeln; end. 排除第一个异形基因 var a:array[1..100] of longint; n,i,wz:longint; begin readln(n); for i:=1 to n do read(a[i]); for i:=1 to n do if sqr(a[i]) mod 7=1

PASCAL语言基础

第一章、什么是计算机语言 计算机语言是计算机软件中非常独特的一部份,它属于系统软件,但又和应用软件息息相关。它的作用是:使人类能够用某些命令、指令去让计算机为人类进行数值、逻辑运算。计算机语言中,只有一种语言是计算机能自己识别的,就是最底层、最难的机器语言,这是一般人类所无法接受的语言,所以在此基础上,人们发展出了许多高级的语言,这些语言的共同特点是:人类无需去掌握高深的机器语言,只要掌握这些更容易理解、更贴近人类的高级语言,用高级语言编出程序后,再由语言解释、编译系统去把程序解释、编译成机器语言让计算机去执行。目前最常用的高级语言大致有以下几种: BASIC语言:是一般计算机入门者的首选语言,命令少,容易掌握,从BASIC,BASICA,GWBASIC,TRUE BASIC,TURBO BASIC,QUICK BASIC等一直发展到目前的WINDOWS环境下的VB。 PASCAL语言:最适合科学计算、数据处理的语言,运行、编译速度最快,从TURBO PASCAL 5 .5, 6.0, 7.0一直到现在的WINDOWS环境下的DELPHI以及LAZARUS等面向对象的PASCAL,以及目前信息学竞赛使用的FREE PASCAL各个版本。 C语言:主要适用于应用软件的开发,是计算机人员的必修课,但在算法实现、建模方面不如PASCAL方便。从C,C++,一直到现在的WIONDOWS环境下的VC、C++等。 实际上,我们日常所用的各种软件,包括Windows,WORD、EXCEL、各种游戏等等,全部都是使用程序设计语言编写出来的软件,我们只有掌握了程序设计语言,才能进行计算机软件的开发。 在我们的信息学竞赛中,所有的题目都是非常复杂的数值与逻辑运算,所以世界上广泛采用PASCAL语言作编程工具,我们采用的是FREE PASCAL2.0版本或者相近版本。 我们学习信息学竞赛除了要掌握程序设计语言,能够使用程序设计语言编写程序外,还有一部分要掌握的更加重要的内容就是——算法设计,它能够使我们的程序运行速度更快、效率、精度更高,使我们的程序取得快人一步的优势,算法设计在本书中我们将接触一部分。 第二章、PASCAL语言入门 第一节、PASCAL语言的特点 以法国数学家命名的PASCAL语言是世界上使用最广泛,最有效的语言之一。其主要特点是:严格的结构化形式;丰富完备的数据类型;运行能力、效率高;查错能力强等等。与BASIC、C等语言相比,PASCAL语言更适合科学计算,运行速度最快,编译能力最强,编译成的可执行文件也最小。 PASCAL语言是编译执行的语言(BASIC语言是解释执行),因此在速度与效率上都比BASIC语言提高了一个档次。所谓解释执行,是在程序环境下编写好程序后,执行它时是一句一句地由语言解释器翻译成机器语言,由计算机去执行,计算机能在程序编辑时就发现程序中错误,但程序运行速度慢;而编译执行是在程序环境中编写好程序后,执行时先由编译器把整个程序编译成机器语言,然后再由计算机执行,计算机必须在编译程序时才能发现程序中的错误,但程序运行速度快。 第二节、FREE PASCAL的集成环境

PASCAL语言_复习题_FXT352064_1112

《Pascal》复习题 一、选择题 1、设有如下的过程说明 PROCEDURE wri; BEGIN Writeln(‘Welcome to use pascal!!!’); End; 则下面有关过程wri的叙述中正确的是____D_____ A)过程说明有错,因为没有形式参数 B)过程说明有错,因未说明过程的类型 C)过程说明有错,因为在过程体内没有给过程名赋值的语句 D)过程说明正确 (2章赋值语句) 2、已知变量ch是字符型变量,下面PASCAL赋值语句正确的是___D_____ A)ch:=’ab cd’; B)ch:=chr(ord(succ(‘c’)+1)); C)ch:=ord(‘b ’)+ord(‘a’); D)ch:=pred(succ(succ(‘f’))); (2章赋值语句) 3、判断以下叙述,其中正确的是___A_______ A) 在pascal程序中所用到的变量必须先说明后使用 B) 在pascal程序中,允许使用的最小值是-maxint C) 在pascal程序中,分号是语句的一部分,在每个语句中不能省略 D) 在pascal程序中,符号常数的值可根据需要随时修改 (1,2章基本知识) 4、以下不符合pascal规定的字符常量是___B_________

A)‘2’ B)‘pascal’ C)’’’’ D)‘a’ (2章标准数据类型) 5、以下属非法的pascal用户自定义标识是_____A____ A)CONST B)FORMAT C) MAX D) NEXT (1章保留字) 6、下面循环语句仅执行一次的是_____A_____ A) I:=0; B) I:=0; Repeat while (I<3) do I:=I+1; I:=I+1; Writeln(i) writeln(i); Until I<3 C)for I:=0 downto 3 do D) I:=0 I:=I+1; while (I>0) or (I<3) do Writeln(i); I:=I+1; writeln(i); (4 章循环结构) 7、下面函数首部或过程首部合法的是__B_______ A)function sum; B)procedure next; C)function s(VAR s:real):integer;

Pascal语言编译器的设计与实现

Pascal语言编译器的设计与实现我们设计的编译程序涉及到编译五个阶段中的三个,即词法分析器、语法分析器和中间代码生成器。编译程序的输出结果包括词法分析后的二元式序列、变量名表、状态栈分析过程显示及四元式序列程序,整个编译程序分为三部分: (1) 词法分析部分 (2) 语法分析处理及四元式生成部分 (3) 输出显示部分 一.词法分析器设计 由于我们规定的程序语句中涉及单词较少,故在词法分析阶段忽略了单词输入错误的检查,而将编译程序的重点放在中间代码生成阶段。词法分析器的功能是输入源程序,输出单词符号。我们规定输出的单词符号格式为如下的二元式:(单词种别,单词自身的值) #define ACC -2 #define sy_if 0 #define sy_then 1 #define sy_else 2 #define sy_while 3 #define sy_begin 4 #define sy_do 5 #define sy_end 6 #define a 7 #define semicolon 8 #define e 9 #define sharp 10 #define S 11 #define L 12 #define tempsy 15 #define EA 18 //E and #define EO 19 //E or #define plus 34 #define subtract 35 #define times 36 #define divide 37 #define becomes 38 #define op_and 39 #define op_or 40 #define op_not 41 #define rop 42

PASCAL语言简介

第一个程序 Pascal 语言的编译器有很多,我们这里以Dev-Pascal 为主要编程工具。该软件界面如下: 我们输入如下代码后编译运行。 如果没有输入错误的话,计算机应能在黑色背景上显示“Hello,World ”。 例:计算a+b 的值。 3.编译并运行

Pascal字符与符号 1.标识符 (1) 标识符的定义:标识符就是以字母开头的字母数字序列,有效长度为63个字符,并且大小写等效。可以用来标示常量、变量、程序、函数等。 (2) 标识符的分类: a.保留字(关键字) 所谓保留字是指在Pascal语言中具有特定的含义,你必须了解它的含义,以便于正确的使用,否则会造成错误。下面是Pascal语言的保留字: AND ARRAY BEGIN CASE CONST DIV DO DOWNTO ELSE END FILE FOR FUNTION GOTO IF IN LABEL MOD NIL NOT OF OR PACKED PROCEDURE PROGRAM RECORD REPEAT SET THEN TO TYPE UNTIL VAR WHILE WITH b.标准标识符:指Pascal语言预先定义的标识符,具有特殊含义。 以下列举了Turbo Pascal语言部分常用的标准表识符: 标准常量False Maxint True 标准类型Boolean Char Real Integer 标准函数Abs Arctan Chr Cos Eof Eoln Exp Ln Odd Ord Pred Round Sin Sqr Sqrt Succ Trunc 标准过程Dispose Get New Pack Page Put Read Readln Reset Rewrite Unpack Write Writeln 标准文件Input Output Pascal数据类型 Pascal 提供了丰富的数据类型,在这里主要介绍整型、实型、字符型和布尔型四种常用的数据类型。 1.整型 一个整型数据用来存放整数。Pascal支持五种预定义整型,它们是shortint(短整型)、integer (整型)、longint(长整型)、byte(字节型)和word(字类型)。每一种类型相应的整数取值范围以及所占用的内存字节数见下表:

pascal语言基础知识

2.1 Pascal程序基本组成 例1.1计算半径为R的圆面积S program Area; {程序首部} {已知半径求圆的面积} const pi=3.14159; {说明部分——数据描述} var s,r:real; begin{执行部分} readln(r); s:=pi*sqr(r); writeln('s=',s); end. 上述程序第一行称为程序首部。其中用花括号(注释可以用{ }或(* *)来表示)括起来的内容是注释,程序第二行就是一个注释,注释除了给人看,增加程序的可读性外,对程序编译和运行不起作用。一个程序可以包含多个出现在不同处注释,亦可无注释。程序第三行是常量说明,程序第四行是变量说明。程序从begin到end都是执行(语句)部分 (1)程序首部 例1.1的第一行称为程序首部。program是保留字,接着是程序名(由你依据“标示符”规则自行定义),最后以分号表示程序首部结束,下面是程序主体的开始。程序首部在一个Turbo Pascal(仅在Turbo Pascal中有效)程序中并非必须出现,它是可选的。写上它仅起了文档作用。因此,在时间有限的情况下,如果用Turbo Pascal编程完全可以省略程序首部。 (2)程序体 a.说明部分 说明部分用于定义和说明程序中用到的数据,由单元说明、标号说明、常量说明、类型说明、变量说明、函数或过程说明组成,并且这些数据的说明次序必须按照以上次序。但是一个简单的Turbo Pascal程序也可以不包含说明部分,也就是说说明部分是可选的。 b.执行部分

执行部分描述了程序要执行的操作。它必须以一个Turbo Pascal保留字begin开始,以保留字end后跟句点结束,其间是一些执行具体操作的语句,并且以分号作为语句之间的分隔符。begin 和end必须成对出现,这是一个Turbo Pascal程序所必须有的。紧跟end之后的句号表示执行部分的结束,也表示整个程序的结束。此后的任何语句都无效。Turbo Pascal规定紧随end之前出现的分号允许省略。 (3)一个完全的Pascal程序结构 program 程序名; uses 已知单元说明; label 标号说明; const 常量说明; type 类型说明; var 变量说明; function 函数说明; procedure 过程说明; begin 语句; 语句;

1-语言基础习题

《Delphi 语言基础》习题 一、填空 1. Delphi 应用程序中项目文件的扩展名是 。 2. Delphi 中与窗体文件对应的文件是单元文件,其最常用的文件扩展名是 *. 。 3. 在Delphi 集成开发环境中,如果想要直接设置或者修改对象的属性,可以通过对象查 看器(Object Inspector )中的 窗口直接进行设置。属性 或 Properties 4. 在Delphi 中新建一个工程后,用户需要保存.pas 文件和 文件。 5. 对象查看器由对象列表、属性选项卡和 三部分组成。 6. 与数学表达式 ab y b a -++2 3)sin(对应的Object Pascal 表达式是 。 7. 与数学表达式 a xy a b a +++22)(cos 对应的Object Pascal 表达式是 。 8. 结构化程序设计的基本原则是取消goto 语句,程序中仅采用顺序、 和循环三 种控制结构。 9. 与数学表达式 ) sin()(sin 222y x y x ++对应的Object Pascal 表达式是 。 10. 结构化程序设计要求程序中仅采用顺序、分支和循环三种控制结构,其中每种结构只能 有 个入口和一个出口。 11. 与数学表达式 a x a by a ++22)(sin 对应的Object Pascal 表达式是 。 12. 与数学表达式 53)(cos 2++x b a 对应的Object Pascal 表达式是 。 13. 对于下面的条件表达式: ((3 <= x )AND (x < 0)) OR (x in [1..10]) 当x = 3 时, 该表达式的值为 。True 14. 与数学表达式 ab y b a ++3)(sin 2对应的Object Pascal 表达式是 。 15. 表达式Trunc (12345.6789*100+0.5)/100的值为 。 12345.68

Pascal程序基本组成与符号

Pascal程序基本组成与符号 hb007 发表于 2006-3-22 8:55:50 一、Pascal程序基本组成 例1计算半径为r的圆的周长C和面积S。 上述程序第一行称为程序首部。用花括号(注释可以用{ }或(* *)来表示)括起来的内容是注释,注释除了给人看,增加程序的可读性外,对程序编译和运行不起作用。一个程序可以包含多个出现在不同处注释,亦可无注释。程序第二行是变量说明。程序从begin到end都是执行(语句)部分。 (1)程序首部 例1的第一行称为程序首部。program是保留字,接着是程序名(由你依据“标示符”规则自行定义),最后以分号表示程序首部结束,下面是程序主体的开始。程序首部在一个Turbo Pascal(仅在Turbo Pasca l中有效)程序中并非必须出现,它是可选的。写上它仅起了文档作用。因此,时间有限的情况下,如果用Turbo Pascal编程完全可以省略程序首部。 (2)程序体 ①说明部分 说明部分用于定义和说明程序中用到的数据,由单元说明、标号说明、常量说明、类型说明、变量说明、函数或过程说明组成,并且这些数据的说明次序必须按照以上次序。但是一个简单的Turbo Pascal程序也可以不包含说明部分,也就是说说明部分是可选的。 ②执行部分 执行部分描述了程序要执行的操作。它必须以一个Turbo Pascal保留字begin开始,以保留字end后跟句点结束,其间是一些执行具体操作的语句,并且以分号作为语句之间的分隔符。begin和end必须成对出现,这是一个Turbo Pascal程序所必须有的。紧跟end之后的句号表示执行

部分的结束,也表示整个程序的结束。此后的任何语句都无效。Turbo Pascal规定紧随end之前出现的分号允许省略。 (3)一个完全的Pascal程序结构 program 程序名; uses 已知单元说明; label 标号说明; const 常量说明; type 类型说明; var 变量说明; function 函数说明; procedure 过程说明; begin 语句; 语句; …… 语句 end. 二、Pascal字符与符号 1、保留字(关键字) 所谓保留字是指在Pascal语言中具有特定的含义,你必须了解它的含义,以便于正确的使用,否则会造成错误。Turbo Pascal语言一共有5 0多个。下面是Pascal语言的保留字:

PASCAL语法分析

Pascal语言的语法分析器 基于文档最下面词法分析器写的#include #include #include #include #include using namespace std; fstream f; char ch,ch1[100]; intcla,no,num; stringstr; //program 1 1 //var 1 2 //begin 1 3 //end 1 4 //integer 1 5 //real 1 6 //while 1 7 //if 1 8 //then 1 9 //else 1 10 //do 1 11 //";" 5,0 //"." 6,0 //":" 7,0 //"," 8,0 //":=" 9,0 //"+" 10,0; //"-" 11,0 //"*" 12,0 //"/" 13,0 //"<" 14,0 //"<=" 15,0 //"=" 16,0; //">" 17,0 //">=" 18,0 //"<>" 19,0 //"||" 20,0 //"&" 21,0 //"!" 22,0 //"(" 23,0 //")" 24,0 void scan(){

f.getline(ch1,100); stringstreamss(ch1); ss>>ch>>cla>>ch>> no >>ch>>str; } boolisprogram(); bool variable(); bool constant(); bool factor(); bool term(); bool arithmetic(); bool assignment(); bool relation(); bool condition(); bool repeat(); bool complex(); bool statement(); boolstatementlist(); bool block(); bool judge(); int main(){ f.open("out.txt",ios::in); bool flag = false; num = 0; if(judge()){ flag = true; } if(flag){//判断是不是程序 cout<< "It is a program!" <

pascal语言语法大全

第七课:pascal专题-pascal语言语法大全及应用配套视频 ★qq语音课主讲内容★: 1.pascal语法专用字符:a~z,a~z,0~9,+,-,*,/,=,<>,<=,>=,<,>,(,),[,],{,},:=,,,;,.,:,..,’,^ ; 【解说】 a~z:大写的26个英文字母; a~z:小写的26个英文字母; 0~9:10个数字; +:加法运算符; -:减法运算符; *:乘法运算符; /:除法运算符; =:比较运算符:等于; <>:比较运算符:不等于; <=:比较运算符:小于等于; >=:比较运算符:大于等于; <:比较运算符:小于; >:比较运算符:大于; (,):优先级和参数表达符:左右括号; [,]:索引号表达符:中括号; {,}:段落屏蔽和备注符:大括号; :=:赋值运算符; ,:排列式表达符:逗号; ;:代码(功能)行结束符; .:主从代码分隔符:点号; ::变量定义分隔符:冒号; ..:子界定义表达符; ’:字符串标识符:单引号; ^ :指针定义符:尖号。 2. pascal语法保留字:and,array,begin,case,const,div,do,downto,else,end,file,for,function,goto,if,in,label,mod,nil,not,of,or,packed,procedure,program,record,repeat,set,then,to,type,until,var,while,with,exports,shr,string,asm,object,unit,constructor,implementation,destructor,uses,inherited,inline,interface,library,xor,shl ; 【解说】 and:逻辑运算符:逻辑与; array:数组定义符:array of …; begin:程序“块”的开始标识符;

Pascal语言编译器的设计与实现

Pascal语言编译器的设计与实现 我们设计的编译程序涉及到编译五个阶段中的三个,即词法分析器、语法分析器和中间代码生成器。编译程序的输出结果包括词法分析后的二元式序列、变量名表、状态栈分析过程显示及四元式序列程序,整个编译程序分为三部分: (1) 词法分析部分 (2) 语法分析处理及四元式生成部分 (3) 输出显示部分 一.词法分析器设计 于我们规定的程序语句中涉及单词较少,故在词法分析阶段忽略了单词输入错误的检查,而将编译程序的重点放在中间代码生成阶段。词法分析器的功能是输入源程序,输出单词符号。我们规定输出的单词符号格式为如下的二元式:(单词种别,单词自身的值) #define ACC -2 #define sy_if 0 #define sy_then 1 #define sy_else 2 #define sy_while 3 #define sy_begin 4 #define sy_do 5 #define sy_end 6 #define a 7 #define semicolon 8 #define e 9 #define sharp 10 #define S 11 #define L 12 #define tempsy15 #define EA 18 //E and #define EO 19 //E or

#define plus 34 #define subtract 35 #define times 36 #define divide 37 #define bexxes 38 #define op_and 39 #define op_or 40 #define op_not 41 #define rop 42 #define lparent 48 #define rparent 49 #define ident 56 #define intconst 57 函数说明 1.读取函数 readline( )、readchar ( ) 词法分析包含从源文件读取字符的操作,但频繁的读文件操作会影响程序执行效率,故实际上是从源程序文件””中读取一行到输入缓冲区,而词法分析过程中每次读取一个字符时则是通过执行 readchar ( )从输入缓冲区获得的;若缓冲区已被读空,则再执行readline( )从中读取下一行至输入缓冲区。 2.扫描函数 scan( ) 扫描函数 scan( )的功能是滤除多余空格并对主要单词进行分析处理,将分析得到的二元式存入二元式结果缓冲区。 3.变量处理 find 变量处理中首先把以字母开头的字母数字串存到spelling[ ]数组中,然后进行识别。识别过程是先让它与保留关键字表中的所有关键字进行匹配,若获得成功则说明它为保留关键字,即将其内码值写入二元式结果缓冲区;否则说明其为变量,这时让它与变量名表中的变量进行匹配),如果成功,则说明该变量已存在并在二元式结果缓

Pascal基本教程

Pascal基本教程 Pascal基本教程第一章 第一章 Pascal语言概述与预备知识 1 关于Turbo Pascal Pascal是一种计算机通用的高级程序设计语言。它由瑞士Niklaus Wirth 教授于六十年代末设计并创立。 以法国数学家命名的Pascal语言现已成为使用最广泛的基于DOS的语言之一,其主要特点有:严格的结构化形式;丰富完备的数据类型;运行效率高;查错能力强。 正因为上述特点,Pascal语言可以被方便地用于描述各种算法与数据结构。尤其是对于程序设计的初学者,Pascal语言有益于培养良好的程序设计风格和习惯。IOI(国际奥林匹克信息学竞赛)把Pascal语言作为三种程序设计语言之一, NOI(全国奥林匹克信息学竞赛)把Pascal语言定为唯一提倡的程序设计语言,在大学中Pascal语言也常常被用作学习数据结构与算法的教学语言。 在Pascal问世以来的三十余年间,先后产生了适合于不同机型的各种各样版本。其中影响最大的莫过于Turbo Pascal系列软件。它是由美国Borland公司设计、研制的一种适用于微机的Pascal编译系统。该编译系统由1983年推出1.0版本发展到1992年推出的7.0版本,其版本不断更新,而功能更趋完善。 下面列出Turbo Pascal编年史 出版年代 版本名称 主要特色 1983 Turbo Pascal 1.0 Turbo Pascal 2.0 Turbo-87 Pascal 提高实数运算速度并扩大值域

1985 Turbo Pascal 3.0 增加图形功能 Turbo BCD Pascal 特别适合应用于商业 1987 Turbo Pascal 4.0 提供集成开发环境(IDE),引入单元概念 1988 Turbo Pascal 5.0 增加调试功能 1989 Turbo Pascal 5.5 支持面向对象的程序设计(OPP) 1990 Turbo Pascal 6.0 提供面向对象的应用框架和库(Turbo Vision) 1992 Turbo Pascal 7.0 面向对象的应用系统、更完善的IDE Turbo Vision 2.0 1993 Borland Pascal 7.0 开发 Object Windows库、 (For Windows) 提供对OLE多媒体应用开发的支持 1995 Delphi Visual Pascal Turbo Pascal语言是编译型程序语言,它提供了一个集成环境的工作系统,集编辑、编译、运行、调试等多功能于一体。 1.2 Turbo Pascal 或 Borland Pascal 的启动

PASCAL语言程序设计

目录 第一部分 PASCAL语言程序设计 (1) 第一章 PASCAL语言基础 (1) 第一节程序的组成与上机调试运行 (2) 第二节常量、变量与数据类型 (3) 第三节表达式与标准函数 (6) 第四节赋值语句、输入与输出语句 (9) 习题 (12) 第二章程序的三种基本结构 (15) 第一节顺序结构 (15) 第二节选择结构 (15) 第三节循环结构 (17) 习题 (20) 第三章数组 (22) 第一节一维数组 (22) 第二节二维数组及应用 (25) 习题 (26) 第四章字符与字符串操作 (29) 第一节字符和字符数组 (29) 第二节字符串变量 (29) 第三节字符串应用举例 (31) 习题 (33) 第五章函数与过程 (35) 第一节自定义函数 (35) 第二节自定义过程 (38) 第四节递归 (42) 第五节递归与回溯 (45) 习题 (50) 第一部分 PASCAL语言程序设计 第一章 PASCAL语言基础 Pascal语言是瑞士苏黎士工科大学的Niklans Wirth(沃思)1971年发表的,是为了纪念17世纪法国著名哲学和数学研究者Blaisc Pascal而将它命名为Pascal程序设计语言。Pascal语言是信息学奥赛中普遍使用的程序设计语言。

第一节程序的组成与上机调试运行 一、程序的组成 我们先看一道例题。 例1-1 输入两个整数a和b,计算a和b的和(a+b)。 【参考程序】 program a1(input,output); //程序首部 var a,b,c:integer; //程序说明部分,a,b,c被说明为整型变量 begin //程序执行部分,下面是程序的内容 write('a='); //在屏幕上输出一个字符串“a=”,输出完后不换行 read(a); //从键盘输入一个数值赋给变量a write('b='); //在屏幕上输出一个字符串“b=”,输出完后不换行 read(b); //从键盘输入一个数值赋给变量b c:=a+b; //计算a+b的和,并将这个和赋值给变量c writeln(a,'+',b,'=',c); //输出a+b=c的等式,输出完后换行 end. //程序结束 【样例输入】 a=10 b=30 【样例输出】 10+30=40 由上可以看出,一个Pascal程序由以下三部分组成: (1)由Program 引导的一行是Pascal程序的首部。 程序首部指出了源程序的名称,是由用户自己给出的,该例子称为a1。程序名后用括号括住的两个参数input与output,通常表示程序运行中的标准输入和输出文件,程序首部以分号结束。 (2)Pascal程序的第二部分是说明部分。 说明部分要求列出程序中引用的全部常量、变量、转移标号、类型、过程和函数的有关说明。若变量c在说明部分没有说明,后边的语句c:=a+b在执行时;翻译软件便能指出其错误并提醒用户加以改正,程序中每个语句都以分号表示结束。 (3)程序的第三个部分是用BEGIN和END括住的一串语句,称为程序的执行部分。有的书中将说明部分和执行部分合称为程序体。 二、PASCAL语言编辑软件的基本操作 下面我们以Free Pascal 1.10系统为例来学习一下Pascal语言编辑软件的使用。 1.Free Pascal的启动 在运行程序目录下(一般是c:\pp\bin\go32v2)运行启动程序fp.exe,即可启动系统。屏幕上出现如图1-1所示的集成环境。 图1-1 2.Free Pascal系统集成开发环境(IDE)简介 最顶上一行为主菜单,中间蓝色框内为编辑窗口,在编辑窗口内可以进行程序的编辑,最底下一行为提示行,显示出系统中常用命令的快捷键,如将当前编辑窗口中文件存盘的命令快捷键为F2,打开磁盘文件命令F3,等等。

pascal语言笔试试题答案

girl873 pascal语言笔试题及答案 楼 2013-01-21 pascal语言笔试题及答案 一、单选题(每小题2分,共60分) 1、在结构化程序设计中所说的程序的三种基本结构是指()。 a)主函数、函数、过程 b)顺序、选择、循环 c)程序首部、说明部分、语句部分 d) while、repeat、for 2、以下各组运算中运算优先级最低的一组是()。 a) +,-,or b) *, / c) div, mod, and d) >=, in 3、数学表达式sin(60o)的正确pascal表达式是 ( )。 a) sin(60) b) sin(3.14159*60) c) sin(3.14159*60/180) d) sin(60*3.14159/360) 4、下列表达式中正确的是 ( )。 a) 8/2 mod 2 b) not(1=0) and (32) c) \a\+2 d) 2+false 5、当n为任意正奇数时,值总为true的表达式是( )。 a) n mod 2=0 b) n div 2=1 c) n-(n div 2)=1 d) n-trunc(n/2)*2=1 6、表达式pred(chr(ord(\a \)+4))的值是 ( )。 a) \c \ b) \d c) 69 d) 70

7、下列表达式值为5的是( )。 a) pred(8 div 2) b) abs(round(23/4)) c) succ(trunc(22/(26 mod 7))) d) ((8 mod 5)*3+1) div 3 8、下面变量说明中错误的是()。 a) var s:set of char; b) var s:set of integer; c) var s:set of 1..100; d) var s:set of (sun,mon,tue,wed,thu,fri,sa t); 9、不能作为for语句循环控制变量的是下列哪种类型变量()。 a)整型 b) 布尔型 c) 实型 d) 字符型 10、至少被执行一次的循环语句是()。 a) for语句 b) repeat-until语句 c) while语句 d) for、repeat-until和while语句 11、下面关于for循环不正确的叙述是()。 A)在循环体中不能改变循环控制变量的值 B)在执行过程中初值和终值不会改变 c)分为递增型和递减型两种 d)循环控制变量不必在程序的说明部分说明 12、设m,n均为整数类型变量,且两者的数值均不大于1000。下面语句 m:=m+n; n:=m-n; m:=m-n;执行后,产生的结果是()。 a)m,n的值保持不变 b)m,n的值进行了交换 c)m,n的值均为原来m的值 d)m,n的值均为原来n的值

PASCAL基本程序结构和概念

要求: 1.程序的结构 2.了解:常量变量运算符表达式标准数据类型 3.学会安装TP并做简单的操作。 PASCAL基本程序结构和概念 标识符保留字常量变量运算符表达式标准数据类型 例1: 为了明显起见先举一个最简单的PASCAL程序例子: 例2: Program ex11; Begin Writeln(‘Hello World!’); ReadLn; End. [例3]已知一辆自行车的售价是300元,请编程计算a辆自行车的总价是多少? 解:若总售价用m来表示,则这个问题可分为以下几步处理: ①从键盘输入自行车的数目a; ②用公式m=300*a 计算总售价; ③输出计算结果。 Pascal程序: Program Ex12; {程序首部} Var a,m : integer; {说明部分} Begin {语句部分} Write(‘a=’); ReadLn(a); {输入自行车数目} M := 300*a; {计算总售价} Writeln(‘M=’,m);{输出总售价} ReadLn; {等待输入回车键} End.

[例4] 输出两个自然数相除的商和余数。 解:设被除数、除数、商和余数,分别为A,B,C,D,均为变量,且都是整数类型。题中未给出具体的自然数A、B,可采用键盘输入方式。 ①给出提示,从键盘输入a, b; ②显示两数相除的数学形式; ③求出a除以b的商c; ④求出a除以b的余数d; ⑤紧接等式后面输出显示商和余数。 Pascal程序: Program Ex14; Var a,b,c,d : integer; Begin Write('INPUT A,B:');{给出提示信息} Readln(a,b);{输入a,b} Writeln;{输出一空行} Write(a,'/',b,'=');{输出等式之后不换行} c:=a div b;{整除运算,取商的整数部分} d:=a mod b;{相除求余运算,取商的余数部分} Writeln(C,'…',d);{输出后自动换行} Readln {等待输入回车键} End. 例5:从键盘读入4个数据,逆序输出 program pname; const n=4; type ar=array [1..4] of integer; var i:integer; a:ar; begin for i:=1 to n do read(a[i]); readln; for i:=n downto 1 do write(a[i]:4); writeln; end. [例1.6]自然数的立方可以表示为两个整数的平方之差,比如43=102-62,请输出自然数1996的这种表示形式。(这里的43用自乘三次的形式4*4*4表示;102也用自乘二次的形式10*10表示) 解:此题没有现成的计算公式能直接利用,但可以自行推出处理方法或构建适当的运算公式,按着构想的处理方案编排出各步骤。 设这个自然数为N,两个平方数分别为X,Y,将问题表示为求N3=X2—Y2

小学组Pascal语言试题

小学组Pascal语言试题(一) 一、单项选择。(每小题1.5分,共15分) 1.下面是某同学定义的变量名,合符Pascal语法的是()。 A.integer B. x1 B. 2x D. x*y 2.假定所有变量均为实型,算式的正确Pascal表达式是()。 A.(u+a)/((b-v)/(c-w)+u*d) B. (u+a)/(b-v)/(c-w)+u*d C. u+a/b-v/c-w+u*d D. (u+a)/((b-v/c-w)+u*d) 3. 有如下的变量说明 var x,y,z:integer; a:real; 则下面的赋值语句中正确的是() A.x=y div 7; B. x:=y/z; C. a:=x*y; D. x+y:=z; 4. 设a,b,c,d均为整型变量,对于下面的程序段 a:=0; b:=0; readln(a,b); read(c); readln(d); 若从键盘输入: 1 2 3 4 5 6 7 其中,表示“回车”,则a,b,c,d中的数应为下面哪一组?() A.1,2,3,4 B.1,2,3,5 C.1,2,5,6 D.1,0,3,5 5. 设n为整型变量,且n:=1997,下面能将n的十位数字(即右边第2位数字)分离出来的语句是()。 A. d:=n mod 100 B. d:=n div 100; C. d:=n div 100 mod 10; D. d:=n mod 100 div 10 6.“判断一个整数x是另一整数y的整数倍”的pascal表达式是()。 A.x=2*y B. x/y=2 C. x mod y=0 D. x mod y=1 7. Pascal表达式“2008 div 5 mod -2”的结果是: A. 8 B. -1 C. 0 D. 1 8. 设实型变量pi已赋值为3.14159,下面不能输出3.14的语句是( )。 A. write(pi:0:2); B. writeln(pi:1:2); C. write(pi:2:2); D. writeln(pi:2); 9.下列程序段的输出结果是()。 Var x,s:integer; Begin x:=2005; s:=0; while x<>0 do begin s:=s+x mod 10; x:=x div 10;

相关主题
文本预览
相关文档 最新文档