目录

Pascal - 快速指南

Pascal - Overview

Pascal是一种通用的高级语言,最初由Niklaus Wirth在20世纪70年代初开发。 它的开发是为了将编程教学作为一门系统学科,并开发可靠和有效的课程。

Pascal是基于Algol的语言,包含许多Algol构造。 Algol 60是Pascal的子集。 Pascal提供了多种数据类型和编程结构。 易于理解和维护Pascal程序。

Pascal因其各种原因在教学和学术领域越来越受欢迎:

  • Easy to learn.
  • 结构化语言。
  • 它产生透明,高效和可靠的程序。
  • 它可以在各种计算机平台上编译。

Pascal语言的特点

Pascal具有以下功能 -

  • Pascal是一种强类型语言。
  • 它提供广泛的错误检查。
  • 它提供了几种数据类型,如数组,记录,文件和集合。
  • 它提供了各种编程结构。
  • 它通过功能和程序支持结构化编程。
  • 它支持面向对象的编程。

关于Pascal的事实

  • Pascal语言以法国数学家Blaise Pascal和计算机开发先驱命名。

  • Niklaus Wirth在1970年完成了原始Pascal编程语言的开发。

  • Pascal基于Algol编程语言的块结构样式。

  • Pascal是一种适合将编程教学作为系统学科的语言,其实现既可靠又高效。

  • ISO 7185 Pascal标准最初发布于1983年。

  • Pascal是用于Apple Lisa开发的主要高级语言,也是Mac早期的高级语言。

  • 1986年,Apple Computer发布了第一个Object Pascal实现,并且在1993年,Pascal标准委员会发布了面向对象的Pascal扩展。

为什么要使用Pascal?

Pascal允许程序员定义复杂的结构化数据类型并构建动态和递归数据结构,例如列表,树和图。 Pascal提供诸如记录,枚举,子范围,动态分配的变量以及关联指针和集合等功能。

Pascal允许嵌套过程定义到任何深度级别。 这真正为学习编程提供了一个很好的编程环境,作为基于基本概念的系统学科。

Pascal最令人惊叹的实现是 -

  • Skype
  • Total Commander
  • TeX
  • Macromedia Captivate
  • Apple Lisa
  • Various PC Games
  • 嵌入式系统

Pascal - Environment Set Up

有几种Pascal编译器和解释器可供一般使用。 其中有 -

  • Turbo Pascal - 提供IDE和编译器,用于在CP/M,CP/M-86,DOS,Windows和Macintosh上运行Pascal程序。

  • Delphi - 提供运行Object Pascal的编译器,并为32位和64位Windows操作系统以及32位Mac OS X和iOS生成本机代码。 Embarcadero计划为Linux和Android操作系统构建支持。

  • Free Pascal - 它是一个用于运行Pascal和Object Pascal程序的免费编译器。 Free Pascal编译器是一个32位和64位Turbo Pascal和Delphi兼容的Pascal编译器,适用于Linux,Windows,OS/2,FreeBSD,Mac OS X,DOS和其他几个平台。

  • Turbo51 - 它是8051系列微控制器的免费Pascal编译器,具有Turbo Pascal 7语法。

  • Oxygene - 它是.NET和Mono平台的Object Pascal编译器。

  • GNU Pascal (GPC) - 它是一个Pascal编译器,由GNU Compiler Collection的前端组成。

我们将在这些教程中使用Free Pascal。 您可以从以下链接下载适用于您的操作系统的Free Pascal : 下载免费Pascal

在Linux上安装Free Pascal

Free Pascal的Linux发行版有三种形式 -

  • tar.gz版本,也可作为单独的文件提供。

  • 一个.rpm (Red Hat Package Manager)版本。

  • 一个.deb (Debian)版本。

.rpm版本的安装代码::

rpm -i fpc-X.Y.Z-N.ARCH.rpm

其中XYZ是.rpm文件的版本号,ARCH是受支持的体系结构之一(i386,x86_64等)。

Debian版本的安装代码(如Ubuntu) -

dpkg -i fpc-XXX.deb

其中XXX是.deb文件的版本号。

有关详细信息,请阅读: 免费Pascal安装指南

在Mac上安装Free Pascal

如果您使用Mac OS X,使用Free Pascal的最简单方法是从Apple的网站下载Xcode开发环境,并按照简单的安装说明进行操作。 一旦你有Xcode设置,你就可以使用Free Pascal编译器。

在Windows上安装Free Pascal

对于Windows,您将下载Windows安装程序setup.exe。 这是一个通常的安装程序。 您需要采取以下步骤进行安装 -

  • 选择一个目录。

  • 选择要安装的软件包的部分。

  • (可选)将.pp或.pas扩展名与Free Pascal IDE相关联。

有关详细信息,请阅读: 免费Pascal安装指南

文本编辑器 (Text Editor)

这将用于键入您的程序。 少数编辑器的示例包括Windows Notepad,OS Edit命令,Brief,Epsilon,EMACS和vim或vi。

文本编辑器的名称和版本可能因不同的操作系统而异。 例如,Notepad将在Windows上使用,vim或vi可用于Windows以及Linux或UNIX。

使用编辑器创建的文件称为源文件,包含程序源代码。 Pascal程序的源文件通常以扩展名.pas命名。

在开始编程之前,请确保您有一个文本编辑器,并且您有足够的经验来编写计算机程序,将其保存在文件中,编译并最终执行。

Pascal - Program Structures

在我们研究Pascal编程语言的基本构建块之前,让我们看一下最小的Pascal程序结构,以便我们在接下来的章节中将其作为参考。

Pascal程序结构

Pascal程序基本上由以下部分组成 -

  • 程序名称
  • 使用命令
  • 输入声明
  • Constant declarations
  • 变量声明
  • 函数声明
  • 程序声明
  • 主程序块
  • 每个区块内的陈述和表达
  • Comments

每个pascal程序通常都有一个标题声明,一个声明和一个严格按顺序执行的部分。 以下格式显示了Pascal程序的基本语法 -

program {name of the program}
uses {comma delimited names of libraries you use}
const {global constant declaration block}
var {global variable declaration block}
function {function declarations, if any}
{ local variables }
begin
...
end;
procedure { procedure declarations, if any}
{ local variables }
begin
...
end;
begin { main program block starts}
...
end. { the end of main program block }

Pascal Hello World示例

以下是一个简单的pascal代码,可以打印出“Hello,World!”字样。 -

program HelloWorld;
uses crt;
(* Here the main program block starts *)
begin
   writeln('Hello, World!');
   readkey;
end. 

这将产生以下结果 -

Hello, World!

让我们看看上述程序的各个部分 -

  • program HelloWorld;程序program HelloWorld;的第一行program HelloWorld; 表示程序的名称。

  • 该程序的第二行uses crt; 是一个预处理器命令,它告诉编译器在进行实际编译之前包含crt单元。

  • begin和end语句中包含的下一行是主程序块。 Pascal中的每个块都包含在begin语句和end语句中。 但是,表示主程序结束的结束语句后面是句号(。)而不是分号(;)。

  • 主程序块的begin语句是程序执行开始的地方。

  • 编译器将忽略(*...*)的行,并将其添加到程序中添加comment

  • writeln('Hello, World!');声明writeln('Hello, World!'); 使用Pascal中可用的writeln函数,它会导致消息“Hello,World!” 显示在屏幕上。

  • 声明readkey; 允许显示暂停,直到用户按下某个键。 它是crt单元的一部分。 一个单元就像Pascal中的一个库。

  • 最后一个声明end. 结束你的计划。

编译并执行Pascal程序

  • 打开文本编辑器并添加上述代码。

  • 将文件另存为hello.pas

  • 打开命令提示符并转到保存文件的目录。

  • 在命令提示符下键入fpc hello.pas,然后按Enter键编译代码。

  • 如果代码中没有错误,命令提示符将带您到下一行并生成hello可执行文件和hello.o对象文件。

  • 现在,在命令提示符下键入hello以执行您的程序。

  • 您将能够在屏幕上看到“Hello World”,并且程序会等待您按任意键。

$ fpc hello.pas
Free Pascal Compiler version 2.6.0 [2011/12/23] for x86_64
Copyright (c) 1993-2011 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling hello.pas
Linking hello
8 lines compiled, 0.1 sec
$ ./hello
Hello, World!

确保免费的pascal编译器fpc在您的路径中,并且您在包含源文件hello.pas的目录中运行它。

Pascal - Basic Syntax

您已经看到了pascal程序的基本结构,因此很容易理解pascal编程语言的其他基本构建块。

变量 (Variables)

变量定义放在以var关键字开头的块中,然后是变量的定义,如下所示:

var
A_Variable, B_Variable ... : Variable_Type;

Pascal变量在函数的代码体外声明,这意味着它们不在beginend对中声明,但它们在过程/函数的定义之后和begin关键字之前声明。 对于全局变量,它们在程序头之后定义。

Functions/Procedures

在Pascal中, procedure是要执行的指令集,没有返回值, function是具有返回值的过程。 功能/程序的定义如下 -

Function Func_Name(params...) : Return_Value;
Procedure Proc_Name(params...);

注释 (Comments)

多行注释用大括号括起来,星号用{* ... *}括起来。 Pascal允许用括号{...}括起来的单行注释。

{* This is a multi-line comments
   and it will span multiple lines. *}
{ This is a single line comment in pascal }

区分大小写 (Case Sensitivity)

Pascal是一种非敏感语言,这意味着您可以在任何一种情况下编写变量,函数和过程。 与变量A_Variable一样,a_variable和A_VARIABLE在Pascal中具有相同的含义。

Pascal声明

Pascal程序由语句组成。 每个陈述都指明了该计划的明确职责。 这些工作可以是声明,分配,读取数据,写入数据,做出逻辑决策,转移程序流程控制等。

例如 -

readln (a, b, c);
s := (a + b + c)/2.0;
area := sqrt(s * (s - a)*(s-b)*(s-c));
writeln(area);        

Pascal中的保留字

Pascal中的语句设计有一些特定的Pascal单词,称为保留单词。 例如,单词,程序,输入,输出,var,real,begin,readline,writeline和end都是保留字。

以下是Pascal中可用的保留字列表。

andarraybegincaseconst
divdodowntoelseend
fileforfunctiongotoif
inlabelmodnilnot
oforpackedprocedureprogram
recordrepeatsetthento
typeuntilvarwhilewith

Pascal中的字符集和标识符

Pascal字符集包括 -

  • 全部大写字母(AZ)

  • 全部小写字母(az)

  • 所有数字(0-9)

  • 特殊符号 - + * /:= ,. ;。 ()[] = {}`空格

Pascal程序中的实体(如变量和常量,类型,函数,过程和记录等)具有名称或标识符。 标识符是字母和数字的序列,以字母开头。 不得在标识符中使用特殊符号和空格。

Pascal - Data Types

实体的数据类型指示与其相关联的含义,约束,可能的值,操作,功能和存储模式。

整数,实数,布尔和字符类型称为标准数据类型。 数据类型可以分类为标量,指针和结构化数据类型。 标量数据类型的示例是整数,实数,布尔值,字符,子范围和枚举。 结构化数据类型由标量类型组成; 例如,数组,记录,文件和集合。 我们稍后将讨论指针数据类型。

Pascal数据类型

Pascal数据类型可以总结如下图所示 -

Pascal数据类型

键入声明

类型声明用于声明标识符的数据类型。 类型声明的语法是 -

 type-identifier-1, type-identfier-2 = type-specifier;

例如,以下声明将变量days和age定义为整数类型,yes和true定义为Boolean类型,name和city定义为字符串类型,费用和费用作为实际类型。

type
days, age = integer;
yes, true = boolean;
name, city = string;
fees, expenses = real;

整数类型 (Integer Types)

下表提供了有关标准整数类型的详细信息,其中包含Object Pascal中使用的存储大小和值范围 -

类型 最低限度 最大值 格式
Integer-21474836482147483647 签名32位
Cardinal04294967295 无符号32位
Shortint -128127 签名8位
Smallint -3276832767 签名16位
Longint -21474836482147483647 签名32位
Int64 -2^63 2 ^ 63 - 1 签名64位
Byte0255 无符号8位
Word065535 无符号16位
Longword04294967295 无符号32位

Constants

使用常量可使程序更具可读性,并有助于在程序开头的某个位置保留特殊数量。 Pascal允许numerical, logical, stringcharacter常量。 可以通过指定const声明在程序的声明部分声明const

常量类型声明的语法如下 -

const
Identifier = contant_value;

以下是一些不断声明的例子 -

VELOCITY_LIGHT = 3.0E=10;
PIE = 3.141592;
NAME = 'Stuart Little';
CHOICE = yes;
OPERATOR = '+';

必须在变量声明之前给出所有常量声明。

枚举类型

枚举数据类型是用户定义的数据类型。 它们允许在列表中指定值。 枚举数据类型只允许assignment运算符和relational运算符。 枚举数据类型可以声明如下 -

type
enum-identifier = (item1, item2, item3, ... )

以下是枚举类型声明的一些示例 -

type
SUMMER = (April, May, June, July, September);
COLORS = (Red, Green, Blue, Yellow, Magenta, Cyan, Black, White);
TRANSPORT = (Bus, Train, Airplane, Ship);

项目在枚举类型的域中列出的顺序定义了项目的顺序。 例如,在枚举类型SUMMER中,April在五月之前,五月在六月之前,依此类推。 枚举类型标识符的域不能由数字或字符常量组成。

子范围类型

子范围类型允许变量采用位于特定范围内的值。 例如,如果选民age应介于18至100年之间,则可将名为年龄的变量宣布为 -

var
age: 18 ... 100;

我们将在下一节详细介绍变量声明。 您还可以使用类型声明定义子范围类型。 声明子范围类型的语法如下 -

type
subrange-identifier = lower-limit ... upper-limit;

以下是子范围类型声明的一些示例 -

const
P = 18;
Q = 90;
type
Number = 1 ... 100;
Value = P ... Q;

可以从已定义的枚举类型的子集创建子范围类型,例如 -

type
months = (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec);
Summer = Apr ... Aug;
Winter = Oct ... Dec;

Pascal - Variable Types

变量只不过是我们的程序可以操作的存储区域的名称。 Pascal中的每个变量都有一个特定的类型,它决定了变量内存的大小和布局; 可存储在该内存中的值范围; 以及可以应用于变量的操作集。

变量的名称可以由字母,数字和下划线字符组成。 它必须以字母或下划线开头。 Pascal not case-sensitive ,因此大写和小写字母在这里意味着相同。 根据前一章中解释的基本类型,将有以下基本变量类型 -

Pascal中的基本变量

Sr.No 类型和描述
1

Character

通常是一个八位字节(一个字节)。 这是一个整数类型。

2

Integer

机器最自然的整数大小。

3

Real

单精度浮点值。

4

Boolean

指定true或false逻辑值。 这也是整数类型。

5

Enumerated

指定用户定义的列表。

6

Subrange

表示变量,其值位于范围内。

7

String

存储一组字符。

Pascal编程语言还允许定义各种其他类型的变量,我们将在后续章节中介绍它们,如指针,数组,记录,集合和文件等。在本章中,我们只研究基本变量类型。

Pascal中的变量声明

在我们在Pascal程序中使用它们之前,必须声明所有变量。 所有变量声明后跟var关键字。 声明指定变量列表,后跟冒号(:)和类型。 变量声明的语法是 -

var
variable_list : type;

这里,type必须是有效的Pascal数据类型,包括字符,整数,实数,布尔值或任何用户定义的数据类型等,variable_list可以包含一个或多个用逗号分隔的标识符名称。 这里显示了一些有效的变量声明 -

var
age, weekdays : integer;
taxrate, net_income: real;
choice, isready: boolean;
initials, grade: char;
name, surname : string;

在上一个教程中,我们已经讨论过Pascal允许声明一个类型。 可以通过名称或标识符来标识类型。 此类型可用于定义该类型的变量。 例如,

type
days, age = integer;
yes, true = boolean;
name, city = string;
fees, expenses = real;

现在,如此定义的类型可用于变量声明 -

var
weekdays, holidays : days;
choice: yes;
student_name, emp_name : name;
capital: city;
cost: expenses;

请注意type声明和var声明之间的区别。 类型声明指示类型的类别或类,例如整数,实数等,而变量规范指示变量可以采用的值的类型。 您可以将Pascal中的type声明与C中的typedef进行比较。最重要的是,变量名称是指将要存储变量值的内存位置。 类型声明不是这样。

Pascal中的变量初始化

为变量分配一个带冒号和等号的值,后跟一个常量表达式。 赋值的一般形式是 -

variable_name := value;

默认情况下,Pascal中的变量不会初始化为零。 它们可能含有垃圾值。 因此,在程序中初始化变量是一种更好的做法。 变量可以在其声明中初始化(分配初始值)。 初始化之后是var关键字,初始化语法如下 -

var
variable_name : type = value;

一些例子是 -

age: integer = 15;
taxrate: real = 0.5;
grade: char = 'A';
name: string = 'John Smith';

让我们看一个例子,它利用到目前为止讨论的各种类型的变量 -

program Greetings;
const
message = ' Welcome to the world of Pascal ';
type
name = string;
var
firstname, surname: name;
begin
   writeln('Please enter your first name: ');
   readln(firstname);
   writeln('Please enter your surname: ');
   readln(surname);
   writeln;
   writeln(message, ' ', firstname, ' ', surname);
end.

编译并执行上述代码时,会产生以下结果 -

Please enter your first name:
John
Please enter your surname:
Smith
Welcome to the world of Pascal John Smith

枚举变量

您已经了解了如何使用简单的变量类型,如整数,实数和布尔值。 现在,让我们看一下枚举类型的变量,可以定义为 -

var
var1, var2, ...  : enum-identifier;

声明枚举类型后,可以声明该类型的变量。 例如,

type
months = (January, February, March, April, May, June, July, August, September, October, November, December);
Var
m: months;
...
M := January;

以下示例说明了这一概念 -

program exEnumeration;
type
beverage = (coffee, tea, milk, water, coke, limejuice);
var
drink:beverage;
begin
   writeln('Which drink do you want?');
   drink := limejuice;
   writeln('You can drink ', drink);
end.

编译并执行上述代码时,会产生以下结果 -

Which drink do you want?
You can drink limejuice

子范围变量

子范围变量声明为 -

var
subrange-name : lowerlim ... uperlim;

子范围变量的例子是 -

var
marks: 1 ... 100;
grade: 'A' ... 'E';
age: 1 ... 25;

以下计划说明了这一概念 -

program exSubrange;
var
marks: 1 .. 100;
grade: 'A' .. 'E';
begin
   writeln( 'Enter your marks(1 - 100): ');
   readln(marks);
   writeln( 'Enter your grade(A - E): ');
   readln(grade);
   writeln('Marks: ' , marks, ' Grade: ', grade);
end.

编译并执行上述代码时,会产生以下结果 -

Enter your marks(1 - 100): 
100
Enter your grade(A - E):
A
Marks: 100 Grade: A

Pascal - Constants

常量是在程序执行期间保持不变的实体。 Pascal只允许声明以下类型的常量 -

  • Ordinal types
  • 设置类型
  • 指针类型(但唯一允许的值是Nil)。
  • Real types
  • Char
  • String

声明常量

声明常量的语法如下 -

const
identifier = constant_value;

下表提供了一些有效的常量声明的示例 -

Real type constant

Sr.No 常数类型和示例
1

Ordinal(Integer)type constant

valid_age = 21;

2

Set type constant

元音=(A,E,I,O,U)的集合;

3

Pointer type constant

P =无;

4

e = 2.7182818;

velocity_light = 3.0E + 10;

5

Character type constant

Operator ='+';

6

String type constant

总统='约翰尼德普';

以下示例说明了这一概念 -

program const_circle (input,output);
const
PI = 3.141592654;
var
r, d, c : real;   {variable declaration: radius, dia, circumference}
begin
   writeln('Enter the radius of the circle');
   readln(r);
   d := 2 * r;
   c :=  PI * d;
   writeln('The circumference of the circle is ',c:7:2);
end.

编译并执行上述代码时,会产生以下结果 -

Enter the radius of the circle
23
The circumference of the circle is 144.51

观察程序的输出语句中的格式。 变量c的格式为十进制符号后面的总位数7和2位。 Pascal允许使用数值变量进行此类输出格式化。

Pascal - Operators

运算符是一个符号,告诉编译器执行特定的数学或逻辑操作。 Pascal允许以下类型的运算符 -

  • 算术运算符
  • 关系运算符
  • 布尔运算符
  • 位操作符
  • 设置运算符
  • 字符串运算符

让我们逐一讨论算术,关系,布尔和位运算符。 我们稍后将讨论集合运算符和字符串运算。

算术运算符 (Arithmetic Operators)

下表显示了Pascal支持的所有算术运算符。 假设变量A保持10,变量B保持20,则 -

显示示例

操作者 描述
+ 添加两个操作数 A + B将给出30
- 从第一个减去第二个操作数 A - B将给-10
* 将两个操作数相乘 A * B将给出200
/ 分子除以分母 B/A会给2
% 模数运算符和整数除法后的余数 B%A将给出0

关系运算符 (Relational Operators)

下表显示了Pascal支持的所有关系运算符。 假设变量A保持10,变量B保持20,则 -

显示示例

操作者 描述
= 检查两个操作数的值是否相等,如果是,则条件变为真。 (A = B)不是真的。
<> 检查两个操作数的值是否相等,如果值不相等,则条件变为真。 (A <> B)是真的。
> 检查左操作数的值是否大于右操作数的值,如果是,则条件变为真。 (A> B)不是真的。
< 检查左操作数的值是否小于右操作数的值,如果是,则条件变为真。 (A < B) 为真
>= 检查左操作数的值是否大于或等于右操作数的值,如果是,则条件变为真。 (A> = B)不是真的。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是,则条件变为真。 (A <= B)是真的。

布尔运算符

下表显示了Pascal语言支持的所有布尔运算符。 所有这些运算符都处理布尔操作数并生成布尔结果。 假设变量A保持为真,变量B保持为假,则 -

显示示例

操作者 描述
and 称为布尔AND运算符。 如果两个操作数都为真,则条件成立。 (A和B)是假的。
然后 它类似于AND运算符,但它保证了编译器评估逻辑表达式的顺序。 从左到右,仅在必要时评估右操作数。 (A和B)是假的。
or 称为布尔OR运算符。 如果两个操作数中的任何一个为真,则条件成立。 (A或B)是真的。
要不然 它类似于布尔OR,但它保证了编译器评估逻辑表达式的顺序。 从左到右,仅在必要时评估右操作数。 (A或B)是真的。
not 称为布尔NOT运算符。 用于反转其操作数的逻辑状态。 如果条件为真,则Logical NOT运算符将使其为false。 不(A和B)是真的。

位运算符

按位运算符处理位并执行逐位运算。 所有这些运算符都处理整数操作数并产生整数结果。 按位和(&),按位或(|)和按位不是(〜)的真值表如下 -

p q p&q p | q 〜p 〜流量
000011
010110
111100
100101

假设A = 60; 和B = 13; 现在以二进制格式,他们将如下 -

A = 0011 1100

B = 0000 1101

-----------------

A&B = 0000 1100

A ^ B = 0011 0001

~A = 1100 0011

Pascal支持的Bitwise运算符如下表所示。 假设变量A保持60而变量B保持13,则:

显示示例

操作者 描述
& 如果二进制AND运算符存在于两个操作数中,则它会将结果复制到结果中。 (A&B)将给出12,即0000 1100
| 二进制OR运算符如果存在于任一操作数中,则复制一位。 (A | B)将给出61,即0011 1101
! 二进制OR运算符如果存在于任一操作数中,则复制一位。 与|相同 运算符。 (A!B)将给出61,即0011 1101
~ 二元一元补语运算符是一元的,具有“翻转”位的效果。 (~A)将给出-61,由于带符号的二进制数,它是2的补码形式的1100 0011。
<< 二进制左移运算符。 左操作数值向左移动右操作数指定的位数。 A << 2将给出240,即1111 0000
>> 二进制右移运算符。 左操作数值向右移动右操作数指定的位数。 A >> 2将给出15,即0000 1111

请注意,Pascal的不同实现在按位运算符方面有所不同。 我们在这里使用的编译器Free Pascal支持以下按位运算符 -

运算符 操作
notBitwise NOT
andBitwise AND
orBitwise OR 
xorBitwise XOR 
shl 按位向左移位
shr 按位向右移位
<< 按位向左移位
>> 按位向右移位

Pascal中的运算符优先级

运算符优先级确定表达式中的术语分组。 这会影响表达式的计算方式。 某些运算符的优先级高于其他运算符; 例如,乘法运算符的优先级高于加法运算符。

例如x = 7 + 3 * 2; 这里,x被赋值为13,而不是20,因为operator *的优先级高于+,所以它首先乘以3 * 2然后加到7中。

此处,具有最高优先级的运算符显示在表的顶部,具有最低优先级的运算符显示在底部。 在表达式中,将首先评估更高优先级的运算符。

显示示例

操作者 优先权
~, not,Highest
*, /, div, mod, and, &
|, !, +, -, or,
=, <>, <, <=, >, >=, in
否则,然后 Lowest

Pascal - Decision Making

决策结构要求程序员指定一个或多个要由程序评估或测试的条件,以及在条件被确定为真时要执行的一个或多个语句,以及可选的,如果条件要执行的其他语句被认定是假的。

以下是大多数编程语言中常见决策结构的一般形式 -

Pascal的决策声明

Pascal编程语言提供以下类型的决策制定语句。 单击以下链接以检查其详细信息。

Sr.No 声明和说明
1 if - then statement

if - then statement由布尔表达式后跟一个或多个语句组成。

2 If-then-else statement

if - then statement后面可以跟一个可选的else statement ,该else statement在布尔表达式为false时执行。

3 嵌套if语句

您可以在另一个ifelse if语句中使用ifelse if语句。

4 case statement

case语句允许根据值列表测试变量的相等性。

5 case - else statement

它类似于if-then-else语句。 在这里,一个else case statement跟在case statement

6 嵌套的case语句

您可以在另一个case语句中使用一个case语句。

Pascal - Loops

当您需要多次执行代码块时,可能会出现这种情况。 通常,语句按顺序执行:首先执行函数中的第一个语句,然后执行第二个语句,依此类推。

编程语言提供各种控制结构,允许更复杂的执行路径。

循环语句允许我们多次执行语句或语句组,以下是大多数编程语言中循环语句的一般形式 -

循环架构

Pascal编程语言提供以下类型的循环结构来处理循环需求。 单击以下链接以查看其详细信息。

Sr.No 循环类型和描述
1 while-do循环

在给定条件为真时重复语句或语句组。 它在执行循环体之前测试条件。

2 for-do循环

多次执行一系列语句,并缩写管理循环变量的代码。

3 重复 - 直到循环

像while语句一样,除了它测试循环体末尾的条件。

4 嵌套循环

你可以在任何一个或多个循环中使用一个或多个循环,用于或重复直到循环。

循环控制语句 (Loop Control Statements)

循环控制语句将执行从其正常序列更改。 当执行离开作用域时,将销毁在该作用域中创建的所有自动对象。

Pascal支持以下控制语句。 单击以下链接以查看其详细信息。

Sr.No 控制声明和描述
1 break statement

终止loopcase语句并将执行转移到循环或case语句之后的语句。

2 continue statement

导致循环跳过其身体的其余部分,并在重复之前立即重新测试其状态。

3 goto statement

将控制转移到带标签的声明。 虽然不建议在程序中使用goto语句。

Pascal - 函数

子程序 (Subprograms)

子程序是执行特定任务的程序单元/模块。 这些子程序组合在一起形成更大的程序。 这基本上被称为“模块化设计”。 子程序/程序可以调用子程序,称为调用程序。

Pascal提供两种子程序 -

  • Functions - 这些子程序返回单个值。

  • Procedures - 这些子程序不直接返回值。

功能 (Functions)

function是一组一起执行任务的语句。 每个Pascal程序至少有一个函数,即程序本身,所有最简单的程序都可以定义其他函数。

函数declaration告诉编译器函数的名称,返回类型和参数。 函数definition提供函数的实际主体。

Pascal标准库提供了许多程序可以调用的内置函数。 例如,函数AppendStr()附加两个字符串,函数New()动态地将内存分配给变量和更多函数。

定义一个函数 (Defining a Function)

在Pascal中,使用function关键字定义函数。 函数定义的一般形式如下 -

function name(argument(s): type1; argument(s): type2; ...): function_type;
local declarations;
begin
   ...
   < statements >
   ...
   name:= expression;
end;

Pascal中的函数定义由函数header ,局部declarations和函数body 。 函数头由关键字函数和赋予函数的name组成。 以下是函数的所有部分 -

  • Arguments - 参数建立调用程序和函数标识符之间的链接,也称为形式参数。 参数类似于占位符。 调用函数时,将值传递给参数。 该值称为实际参数或参数。 参数列表是指函数的类型,顺序和参数数量。 使用这种形式参数是可选的。 这些参数可以具有标准数据类型,用户定义的数据类型或子范围数据类型。

    出现在函数语句中的形式参数列表可以是简单的或下标的变量,数组或结构化变量,或子程序。

  • Return Type - 所有函数必须返回一个值,因此必须为所有函数分配一个类型。 function-type是函数返回的值的数据类型。 它可以是标准的,用户定义的标量或子范围类型,但它不能是结构化类型。

  • Local declarations - 局部声明是指标签,常量,变量,函数和过程的声明,它们仅适用于函数体。

  • Function Body - 函数体包含一组语句,用于定义函数的功能。 它应始终包含在保留字开头和结尾之间。 它是所有计算完成的函数的一部分。 必须有一个类型的赋值语句 - name := expression; 在函数体中为函数名赋值。 执行该函数时返回该值。 正文中的最后一个陈述必须是最终陈述。

以下是一个示例,说明如何在pascal中定义函数 -

(* function returning the max between two numbers *)
function max(num1, num2: integer): integer;
var
   (* local variable declaration *)
   result: integer;
begin
   if (num1 > num2) then
      result := num1
   else
      result := num2;
   max := result;
end;

函数声明 (Function Declarations)

函数declaration告诉编译器函数名称以及如何调用函数。 函数的实际主体可以单独定义。

功能声明包含以下部分 -

function name(argument(s): type1; argument(s): type2; ...): function_type;

对于上面定义的函数max(),以下是函数声明 -

function max(num1, num2: integer): integer;

在一个源文件中定义函数并在另一个文件中调用该函数时,需要函数声明。 在这种情况下,您应该在调用该函数的文件顶部声明该函数。

调用一个函数 (Calling a Function)

在创建函数时,您可以定义函数必须执行的操作。 要使用函数,您必须调用该函数来执行定义的任务。 当程序调用一个函数时,程序控制被转移到被调用的函数。 被调用的函数执行已定义的任务,当执行其返回语句或达到最后结束语句时,它将程序控制返回给主程序。

要调用函数,只需要传递必需的参数和函数名称,如果函数返回一个值,那么您可以存储返回的值。 以下是一个显示用法的简单示例 -

program exFunction;
var
   a, b, ret : integer;
(*function definition *)
function max(num1, num2: integer): integer;
var
   (* local variable declaration *)
   result: integer;
begin
   if (num1 > num2) then
      result := num1
   else
      result := num2;
   max := result;
end;
begin
   a := 100;
   b := 200;
   (* calling a function to get max value *)
   ret := max(a, b);
   writeln( 'Max value is : ', ret );
end.

编译并执行上述代码时,会产生以下结果 -

Max value is : 200 

Pascal - Procedures

Procedures是子程序,它不是返回单个值,而是允许获得一组结果。

定义程序

在Pascal中,使用procedure关键字定义procedure 。 程序定义的一般形式如下 -

procedure name(argument(s): type1, argument(s): type 2, ... );
   < local declarations >
begin
   < procedure body >
end;

Pascal中的过程definition由头,局部declarations和过程body组成。 过程标题由关键字procedure和给定procedure的名称组成。 以下是程序的所有部分 -

  • Arguments - 参数建立调用程序和过程标识符之间的链接,也称为形式参数。 过程中参数的规则与函数的参数规则相同。

  • Local declarations - 局部声明引用标签,常量,变量,函数和过程的声明,这些声明仅适用于过程主体。

  • Procedure Body - 过程主体包含一组语句,用于定义过程的作用。 它应始终包含在保留字开头和结尾之间。 它是完成所有计算的过程的一部分。

以下是名为findMin()的过程的源代码。 此过程采用4个参数x,y,z和m,并将前三个变量中的最小值存储在名为m的变量中。 变量m通过reference传递(稍后我们将通过引用讨论传递参数) -

procedure findMin(x, y, z: integer; var m: integer); 
(* Finds the minimum of the 3 values *)
begin
   if x < y then
      m := x
   else
      m := y;
   if z <m then
      m := z;
end; { end of procedure findMin }  

程序声明

过程declaration告诉编译器有关过程名称以及如何调用过程的信息。 程序的实际主体可以单独定义。

过程声明具有以下语法 -

procedure name(argument(s): type1, argument(s): type 2, ... );

请注意,该name of the procedure is not associated with any typename of the procedure is not associated with any type 。 对于上面定义的过程findMin() ,以下是声明 -

procedure findMin(x, y, z: integer; var m: integer);

调用程序

在创建过程时,您可以定义过程必须执行的操作。 要使用该过程,您必须调用该过程来执行定义的任务。 当程序调用过程时,程序控制将转移到被调用的过程。 被调用的过程执行定义的任务,当到达其最后一个结束语句时,它将控制返回给调用程序。

要调用过程,您只需要传递所需的参数以及过程名称,如下所示 -

program exProcedure;
var
   a, b, c,  min: integer;
procedure findMin(x, y, z: integer; var m: integer); 
(* Finds the minimum of the 3 values *)
begin
   if x < y then
      m:= x
   else
      m:= y;
   if z < m then
      m:= z;
end; { end of procedure findMin }  
begin
   writeln(' Enter three numbers: ');
   readln( a, b, c);
   findMin(a, b, c, min); (* Procedure call *)
   writeln(' Minimum: ', min);
end.

编译并执行上述代码时,会产生以下结果 -

Enter three numbers:
89 45 67
Minimum: 45

递归子程序

我们已经看到程序或子程序可能会调用另一个子程序。 当子程序调用自身时,它被称为递归调用,该过程称为递归。

为了说明这个概念,让我们计算一个数的阶乘。 数字n的因子定义为 -

n! = n*(n-1)!
   = n*(n-1)*(n-2)!
      ...
   = n*(n-1)*(n-2)*(n-3)... 1

以下程序通过递归调用自身来计算给定数字的阶乘。

program exRecursion;
var
   num, f: integer;
function fact(x: integer): integer; (* calculates factorial of x - x! *)
begin
   if x=0 then
      fact := 1
   else
      fact := x * fact(x-1); (* recursive call *)
end; { end of function fact}
begin
   writeln(' Enter a number: ');
   readln(num);
   f := fact(num);
   writeln(' Factorial ', num, ' is: ' , f);
end.

编译并执行上述代码时,会产生以下结果 -

Enter a number:
5
Factorial 5 is: 120

以下是另一个例子,它使用recursive函数为给定数字生成Fibonacci Series数列 -

program recursiveFibonacci;
var
   i: integer;
function fibonacci(n: integer): integer;
begin
   if n=1 then
      fibonacci := 0
   else if n=2 then
      fibonacci := 1
   else
      fibonacci := fibonacci(n-1) + fibonacci(n-2);
end; 
begin
   for i:= 1 to 10 do
   write(fibonacci (i), '  ');
end.

编译并执行上述代码时,会产生以下结果 -

0 1 1 2	3 5 8 13 21 34

子程序的论点

如果子程序( function or procedure )要使用参数,它必须声明接受参数值的变量。 这些变量称为子程序的formal parameters

形式参数的行为与子程序中的其他局部变量相似,并且在进入子程序时创建,并在退出时销毁。

在调用子程序时,有两种方法可以将参数传递给子程序 -

Sr.No 通话类型和说明
1 call by value [值传递]

此方法将参数的实际值复制到子程序的形式参数中。 在这种情况下,对子程序内的参数所做的更改对参数没有影响。

2 call by reference [引用传递]

此方法将参数的地址复制到形式参数中。 在子程序内,该地址用于访问调用中使用的实际参数。 这意味着对参数所做的更改会影响参数。

默认情况下,Pascal使用call by value来传递参数。 通常,这意味着子程序中的代码不能改变用于调用子程序的参数。 我们在“Pascal - Functions”一章中使用的示例程序使用call by value名为max()的函数。

然而,此处提供的示例程序( exProcedure )使用call by reference调用过程findMin()。

Pascal - Variable Scope

任何编程中的范围都是程序的一个区域,其中定义的变量可以存在,并且超出该变量无法访问。 有三个地方,其中变量可以用Pascal编程语言声明 -

  • 在子程序或块中,称为局部变量

  • 在所有子程序之外,称为全局变量

  • 在子程序参数的定义中称为形式参数

让我们解释什么是localglobal变量和形式参数。

局部变量 (Local Variables)

在子程序或块内声明的变量称为局部变量。 它们只能由子程序或代码块中的语句使用。 本地变量不属于他们自己的子程序。 以下是使用局部变量的示例。 这里,所有变量abc都是名为exLocal程序的本地exLocal

program exLocal; 
var
   a, b, c: integer;
begin
   (* actual initialization *)
   a := 10;
   b := 20;
   c := a + b;
   writeln('value of a = ', a , ' b =  ',  b, ' and c = ', c);
end.

编译并执行上述代码时,会产生以下结果 -

value of a = 10 b = 20 c = 30

现在,让我们更多地扩展程序,让我们创建一个名为display的过程,它将拥有自己的一组变量abc并从程序exLocal显示它们的值。

program exLocal;
var
   a, b, c: integer;
procedure display;
var
   a, b, c: integer;
begin
   (* local variables *)
   a := 10;
   b := 20;
   c := a + b;
   writeln('Winthin the procedure display');
   writeln('value of a = ', a , ' b =  ',  b, ' and c = ', c);
end;
begin
   a:= 100;
   b:= 200;
   c:= a + b;
   writeln('Winthin the program exlocal');
   writeln('value of a = ', a , ' b =  ',  b, ' and c = ', c);
   display();
end.

编译并执行上述代码时,会产生以下结果 -

Within the program exlocal
value of a = 100 b = 200 c = 300
Within the procedure display
value of a = 10 b = 20 c = 30

全局变量 (Global Variables)

全局变量在函数之外定义,通常在程序之上。 全局变量将在程序的整个生命周期中保持其值,并且可以在为程序定义的任何函数内访问它们。

任何函数都可以访问global变量。 也就是说,全局变量在声明后可用于整个程序。 以下是使用global变量和local变量的示例 -

program exGlobal;
var
   a, b, c: integer;
procedure display;
var
   x, y, z: integer;
begin
   (* local variables *)
   x := 10;
   y := 20;
   z := x + y;
   (*global variables *)
   a := 30;
   b:= 40;
   c:= a + b;
   writeln('Winthin the procedure display');
   writeln(' Displaying the global variables a, b, and c');
   writeln('value of a = ', a , ' b =  ',  b, ' and c = ', c);
   writeln('Displaying the local variables x, y, and z');
   writeln('value of x = ', x , ' y =  ',  y, ' and z = ', z);
end;
begin
   a:= 100;
   b:= 200;
   c:= 300;
   writeln('Winthin the program exlocal');
   writeln('value of a = ', a , ' b =  ',  b, ' and c = ', c);
   display();
end.

编译并执行上述代码时,会产生以下结果 -

Within the program exlocal
value of a = 100 b = 200 c = 300
Within the procedure display
Displaying the global variables a, b, and c
value of a = 30 b = 40 c = 70
Displaying the local variables x, y, and z
value of x = 10 y = 20 z = 30

请注意,过程显示可以访问变量a,b和c,它们是关于显示的全局变量以及它自己的局部变量。 程序对于局部变量和全局变量可以具有相同的名称,但函数内的局部变量值将优先考虑。

让我们稍微改变前面的例子,现在程序显示的局部变量与abc名字相同 -

program exGlobal;
var
   a, b, c: integer;
procedure display;
var
   a, b, c: integer;
begin
   (* local variables *)
   a := 10;
   b := 20;
   c := a + b;
   writeln('Winthin the procedure display');
   writeln(' Displaying the global variables a, b, and c');
   writeln('value of a = ', a , ' b =  ',  b, ' and c = ', c);
   writeln('Displaying the local variables a, b, and c');
   writeln('value of a = ', a , ' b =  ',  b, ' and c = ', c);
end;
begin
   a:= 100;
   b:= 200;
   c:= 300;
   writeln('Winthin the program exlocal');
   writeln('value of a = ', a , ' b =  ',  b, ' and c = ', c);   
   display();
end.

编译并执行上述代码时,会产生以下结果 -

Within the program exlocal
value of a = 100 b = 200 c = 300
Within the procedure display
Displaying the global variables a, b, and c
value of a = 10 b = 20 c = 30
Displaying the local variables a, b, and c
value of a = 10 b = 20 c = 30

Pascal - Strings

Pascal中的字符串实际上是一个具有可选大小规范的字符序列。 字符可以是数字,字母,空白,特殊字符或所有字符的组合。 Extended Pascal根据系统和实现提供多种类型的字符串对象。 我们将讨论程序中使用的更常见的字符串类型。

您可以通过多种方式定义字符串 -

  • Character arrays - 这是一个字符串,它是由单引号括起来的零个或多个字节大小的字符序列。

  • String variables - 字符串类型的变量,如Turbo Pascal中所定义。

  • Short strings - 具有大小规范的String类型的变量。

  • Null terminated strings - pchar类型的变量。

  • AnsiStrings - Ansistrings是没有长度限制的字符串。

Pascal只提供一个字符串运算符,字符串连接运算符(+)。

例子 (Examples)

以下程序打印前四种字符串。 我们将在下一个例子中使用AnsiStrings。

program exString;
var
   greetings: string;
   name: packed array [1..10] of char;
   organisation: string[10];
   message: pchar;
begin
   greetings := 'Hello ';
   message := 'Good Day!';
   writeln('Please Enter your Name');
   readln(name);
   writeln('Please Enter the name of your Organisation');
   readln(organisation);
   writeln(greetings, name, ' from ', organisation);
   writeln(message); 
end.

编译并执行上述代码时,会产生以下结果 -

Please Enter your Name
John Smith
Please Enter the name of your Organisation
Infotech
Hello John Smith from Infotech

以下示例使用了更多函数,让我们看看 -

program exString;
uses sysutils;
var
   str1, str2, str3 : ansistring;
   str4: string;
   len: integer;
begin
   str1 := 'Hello ';
   str2 := 'There!';
   (* copy str1 into str3 *)
   str3 := str1;
   writeln('appendstr( str3, str1) :  ', str3 );
   (* concatenates str1 and str2 *)
   appendstr( str1, str2);
   writeln( 'appendstr( str1, str2) ' , str1 );
   str4 := str1 + str2;
   writeln('Now str4 is: ', str4);
   (* total lenghth of str4 after concatenation  *)
   len := byte(str4[0]);
   writeln('Length of the final string str4: ', len); 
end.

编译并执行上述代码时,会产生以下结果 -

appendstr( str3, str1) : Hello
appendstr( str1, str2) : Hello There!
Now str4 is: Hello There! There!
Length of the final string str4: 18

Pascal字符串函数和过程

Pascal支持各种操作字符串的函数和过程。 这些子程序在实施方面有所不同。 在这里,我们列出了Free Pascal提供的各种字符串操作子程序 -

Sr.No. 功能与目的
1

function AnsiCompareStr(const S1: ; const S2:):Integer;

比较两个字符串

2

function AnsiCompareText(const S1: ; const S2:):Integer;

比较两个字符串,不区分大小写

3

function AnsiExtractQuotedStr(var Src: PChar; Quote: Char):;

从字符串中删除引号

4

function AnsiLastChar(const S:):PChar;

获取string的最后一个字符

5

function AnsiLowerCase(const s:):

将字符串转换为全小写

6

function AnsiQuotedStr(const S: ; Quote: Char):;

引用一个字符串

7

function AnsiStrComp(S1: PChar;S2: PChar):Integer;

比较字符串区分大小写

8

function AnsiStrIComp(S1: PChar; S2: PChar):Integer;

比较字符串不区分大小写

9

function AnsiStrLComp(S1: PChar; S2: PChar; MaxLen: Cardinal):Integer;

比较区分大小写的L字符区分大小写

10

function AnsiStrLIComp(S1: PChar; S2: PChar; MaxLen: Cardinal):Integer;

比较字符串的L个字符不区分大小写

11

function AnsiStrLastChar(Str: PChar):PChar;

获取string的最后一个字符

12

function AnsiStrLower(Str: PChar):PChar;

将字符串转换为全小写

13

function AnsiStrUpper(Str: PChar):PChar;

将字符串转换为全大写

14

function AnsiUpperCase(const s:):;

将字符串转换为全大写

15

procedure AppendStr(var Dest: ; const S:);

附加2个字符串

16

procedure AssignStr(var P: PString; const S:);

在堆上分配字符串的值

17

function CompareStr(const S1: ; const S2:):Integer; overload;

比较两个区分大小写的字符串

18

function CompareText(const S1: ; const S2:):Integer;

比较两个字符串不区分大小写

19 procedure DisposeStr(S: PString); overload;

从堆中删除字符串

20

procedure DisposeStr(S: PShortString); overload;

从堆中删除字符串

21

function IsValidIdent( const Ident:):Boolean;

字符串是有效的pascal标识符

22

function LastDelimiter(const Delimiters: ; const S:):Integer;

字符串中最后出现的字符

23

function LeftStr(const S: ; Count: Integer):;

获取字符串的前N个字符

24

function LoadStr(Ident: Integer):;

从资源加载字符串

25

function LowerCase(const s: ):; overload;

将字符串转换为全小写

26

function LowerCase(const V: variant ):; overload;

将字符串转换为全小写

27

function NewStr(const S:):PString; overload;

在堆上分配新字符串

28

function RightStr(const S: ; Count: Integer):;

获取字符串的最后N个字符

29

function StrAlloc(Size: Cardinal):PChar;

为字符串分配内存

30

function StrBufSize(Str: PChar):SizeUInt;

为字符串保留内存

31

procedure StrDispose(Str: PChar);

从堆中删除字符串

32

function StrPas(Str: PChar):;

将PChar转换为pascal字符串

33

function StrPCopy(Dest: PChar; Source:):PChar;

复制pascal字符串

34

function StrPLCopy(Dest: PChar; Source: ; MaxLen: SizeUInt):PChar;

复制N个字节的pascal字符串

35

function UpperCase(const s:):;

将字符串转换为全大写

Pascal - Booleans

Pascal提供数据类型Boolean,使程序员能够定义,存储和操作逻辑实体,例如常量,变量,函数和表达式等。

布尔值基本上是整数类型。 布尔类型变量有两个预定义的可能值TrueFalse 。 解析为布尔值的表达式也可以分配给布尔类型。

Free Pascal还支持ByteBoolWordBoolLongBool类型。 它们分别是Byte,Word或Longint类型。

值False等于0(零),并且在转换为布尔值时,任何非零值都被视为True。 如果将布尔值True分配给LongBool类型的变量,则将其转换为-1。

应该注意,逻辑运算符and/or not为布尔数据类型定义的。

布尔数据类型声明

使用var关键字声明布尔类型的变量。

var
boolean-identifier: boolean;

例如,

var
choice: boolean;

例子 (Example)

program exBoolean;
var
exit: boolean;
choice: char;
   begin
   writeln('Do you want to continue? ');
   writeln('Enter Y/y for yes, and N/n for no');
   readln(choice);
if(choice = 'n') then
   exit := true
else
   exit := false;
if (exit) then
   writeln(' Good Bye!')
else
   writeln('Please Continue');
readln;
end.

编译并执行上述代码时,会产生以下结果 -

Do you want to continue?
Enter Y/y for yes, and N/n for no
N
Good Bye!
Y
Please Continue

Pascal - Arrays

Pascal编程语言提供了一种称为数组的数据结构,它可以存储相同类型元素的固定大小顺序集合。 数组用于存储数据集合,但将数组视为相同类型的变量集合通常更有用。

您可以声明一个数组变量,例如数字,并使用数字[1],数字[2]和...,数字[100]来代表单个变量,例如number1,number2,...和number100,而不是声明单个变量。个别变数。 索引访问数组中的特定元素。

所有阵列都包含连续的内存位置。 最低地址对应于第一个元素,最高地址对应于最后一个元素。

请注意,如果你想要一个从索引0开始的C样式数组,你只需要从0开始索引,而不是1。

Pascal中的数组

声明数组 (Declaring Arrays)

要在Pascal中声明一个数组,程序员可以声明该类型,然后创建该数组的变量或直接声明数组变量。

一维数组类型声明的一般形式是 -

type
   array-identifier = array[index-type] of element-type;

Where,

  • array-identifier - 表示数组类型的名称。

  • index-type - 指定数组的下标; 它可以是除真实之外的任何标量数据类型

  • element-type - 指定要存储的值的类型

例如,

type
   vector = array [ 1..25] of real;
var
   velocity: vector;

现在,velocity是矢量类型的可变数组,足以容纳25个实数。

要从0索引启动数组,声明将是 -

type
   vector = array [ 0..24] of real;
var
   velocity: vector;

数组下标的类型

在Pascal中,数组下标可以是任何标量类型,如整数,布尔,枚举或子范围,除了真实。 数组下标也可能有负值。

例如,

type
   temperature = array [-10 .. 50] of real;
var
   day_temp, night_temp: temperature;

让我们再举一个下标是字符类型的例子 -

type
   ch_array = array[char] of 1..26;
var
   alphabet: ch_array;

下标可以是枚举类型 -

type
   color = ( red, black, blue, silver, beige);
   car_color = array of [color] of boolean;
var
   car_body: car_color;

初始化数组 (Initializing Arrays)

在Pascal中,通过赋值来初始化数组,方法是指定特定的下标或使用for-do循环。

例如 -

type
   ch_array = array[char] of 1..26;
var
   alphabet: ch_array;
   c: char;
begin
   ...
   for c:= 'A' to 'Z' do
   alphabet[c] := ord[m];  
   (* the ord() function returns the ordinal values *)

访问数组元素 (Accessing Array Elements)

通过索引数组名称来访问元素。 这是通过将元素的索引放在数组名称后面的方括号中来完成的。 例如 -

a: integer;
a: = alphabet['A'];

上面的语句将从名为alphabet的数组中取出第一个元素,并将值赋给变量a。

以下是一个例子,它将使用所有上述三个概念即。 声明,分配和访问数组 -

program exArrays;
var
   n: array [1..10] of integer;   (* n is an array of 10 integers *)
   i, j: integer;
begin
   (* initialize elements of array n to 0 *)        
   for i := 1 to 10 do
       n[ i ] := i + 100;   (* set element at location i to i + 100 *)
    (* output each array element's value *)
   for j:= 1 to 10 do
      writeln('Element[', j, '] = ', n[j] );
end.

编译并执行上述代码时,会产生以下结果 -

Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109
Element[10] = 110

Pascal Arrays详细信息

数组对Pascal很重要,需要更多细节。 以下几个与数组相关的重要概念应该对Pascal程序员清楚 -

Sr.No 概念与描述
1 多维数组

Pascal支持多维数组。 多维数组的最简单形式是二维数组。

2 动态数组

在这种类型的数组中,初始长度为零。 必须使用标准SetLength函数设置数组的实际长度。

3 打包阵列

这些数组是比特打包的,即每个字符或真值都存储在连续的字节中,而不是使用一个存储单元,通常是一个字(4个字节或更多)。

4 将数组传递给子程序

通过指定没有索引的数组名称,可以将子程序传递给子程序。

Pascal - Pointers

Pascal中的指针简单易学。 使用指针可以更轻松地执行某些Pascal编程任务,并且在不使用指针的情况下无法执行其他任务(如动态内存分配)。 所以有必要学习指向成为一个完美的Pascal程序员。 让我们开始通过简单而简单的步骤学习它们。

如您所知,每个变量都是一个内存位置,每个内存位置都定义了其地址,可以使用指针变量的名称来访问它,该变量表示内存中的地址。

什么是指针?

指针是动态变量,其值是另一个变量的地址,即存储器位置的直接地址。 与任何变量或常量一样,必须先声明指针,然后才能使用它来存储任何变量地址。 指针变量声明的一般形式是 -

type
   ptr-identifier = ^base-variable-type;

指针类型通过在插入符号(^)的向上箭头前缀为基本类型来定义。 基类型定义数据项的类型。 一旦指针变量被定义为某种类型,它就可以仅指向该类型的数据项。 一旦定义了指针类型,我们就可以使用var声明来声明指针变量。

var
   p1, p2, ... : ptr-identifier;

以下是一些有效的指针声明 -

type
   Rptr = ^real;
   Cptr = ^char;
   Bptr = ^ Boolean;
   Aptr = ^array[1..5] of real;
   date-ptr = ^ date;
      Date = record
         Day: 1..31;
         Month: 1..12;
         Year: 1900..3000;
      End;
var
   a, b : Rptr;
   d: date-ptr;

通过使用相同的插入符号(^)取消引用指针变量。 例如,由指针rptr引用的关联变量是rptr^ 。 可以访问 -

rptr^ := 234.56;

以下示例将说明此概念 -

program exPointers;
var
   number: integer;
   iptr: ^integer;
begin
   number := 100;
   writeln('Number is: ', number);
   iptr := @number;
   writeln('iptr points to a value: ', iptr^);
   iptr^ := 200;
   writeln('Number is: ', number);
   writeln('iptr points to a value: ', iptr^);
end.

编译并执行上述代码时,会产生以下结果 -

Number is: 100
iptr points to a value: 100
Number is: 200
iptr points to a value: 200

在Pascal中打印内存地址

在Pascal中,我们可以使用地址运算符(@)将变量的地址分配给指针变量。 我们使用此指针来操作和访问数据项。 但是,如果由于某种原因,我们需要使用内存地址本身,我们需要将它存储在word类型变量中。

让我们扩展上面的例子来打印存储在指针iptr的内存地址 -

program exPointers;
var
   number: integer;
   iptr: ^integer;
   y: ^word;
begin
   number := 100;
   writeln('Number is: ', number);
   iptr := @number;
   writeln('iptr points to a value: ', iptr^);
   iptr^ := 200;
   writeln('Number is: ', number);
   writeln('iptr points to a value: ', iptr^);
   y := addr(iptr);
   writeln(y^); 
end.

编译并执行上述代码时,会产生以下结果 -

Number is: 100
iptr points to a value: 100
Number is: 200
iptr points to a value: 200
45504

NIL指针

如果您没有要分配的确切地址,将NIL值分配给指针变量始终是一个好习惯。 这是在变量声明时完成的。 指定NIL指针指向无处。 考虑以下程序 -

program exPointers;
var
   number: integer;
   iptr: ^integer;
   y: ^word;
begin
   iptr := nil;
   y := addr(iptr);
   writeln('the vaule of iptr is ', y^);
end.

编译并执行上述代码时,会产生以下结果 -

The value of ptr is 0

要检查nil指针,可以使用if语句,如下所示 -

if(ptr <> nill )then     (* succeeds if p is not null *)
if(ptr = nill)then    (* succeeds if p is null *)

Pascal指针细节

指针有很多但很简单的概念,它们对Pascal编程非常重要。 有以下几个重要的指针概念,Pascal程序员应该清楚 -

Sr.No 概念与描述
1 Pascal - 指针算术

可以在指针上使用四个算术运算符:递增,递减,+, -

2 Pascal - 指针数组

您可以定义数组以包含许多指针。

3 Pascal - 指向指针

Pascal允许您在指针上指针等等。

4 在Pascal中传递指向子程序的指针

通过引用或地址传递参数都可以通过被调用的子程序在调用子程序中更改传递的参数。

5 从Pascal中的子程序返回指针

Pascal允许子程序返回指针。

Pascal - Records

Pascal数组允许您定义可以包含多个相同类型数据项的变量类型,但是记录是Pascal中可用的另一个用户定义数据类型,它允许您组合不同类型的数据项。

记录包含不同的字段。 假设您想要在库中跟踪您的书籍,您可能希望跟踪每本书的以下属性 -

  • Title
  • Author
  • Subject
  • 书名

定义记录

要定义记录类型,可以使用类型声明语句。 记录类型定义为 -

type
record-name = record
   field-1: field-type1;
   field-2: field-type2;
   ...
   field-n: field-typen;
end;

以下是您宣布图书记录的方式 -

type 
Books = record
   title: packed array [1..50] of char;
   author: packed array [1..50] of char;
   subject: packed array [1..100] of char;
   book_id: integer;
end;

记录变量以通常的方式定义

var
   r1, r2, ... : record-name;

或者,您可以直接将记录类型变量定义为 -

var
Books : record
   title: packed array [1..50] of char;
   author: packed array [1..50] of char;
   subject: packed array [1..100] of char;
   book_id: integer;
end;

访问记录的字段

要访问记录的任何字段,我们使用成员访问运算符(。)。 成员访问运算符被编码为记录变量名称和我们希望访问的字段之间的句点。 以下是解释结构用法的示例 -

program exRecords;
type
Books = record
   title: packed array [1..50] of char;
   author: packed array [1..50] of char;
   subject: packed array [1..100] of char;
   book_id: longint;
end;
var
   Book1, Book2: Books; (* Declare Book1 and Book2 of type Books *)
begin
   (* book 1 specification *)
   Book1.title  := 'C Programming';
   Book1.author := 'Nuha Ali '; 
   Book1.subject := 'C Programming Tutorial';
   Book1.book_id := 6495407;
   (* book 2 specification *)
   Book2.title := 'Telecom Billing';
   Book2.author := 'Zara Ali';
   Book2.subject := 'Telecom Billing Tutorial';
   Book2.book_id := 6495700;
   (* print Book1 info *)
   writeln ('Book 1 title : ', Book1.title);
   writeln('Book 1 author : ', Book1.author);
   writeln( 'Book 1 subject : ', Book1.subject);
   writeln( 'Book 1 book_id : ', Book1.book_id);
   writeln; 
   (* print Book2 info *)
   writeln ('Book 2 title : ', Book2.title);
   writeln('Book 2 author : ', Book2.author);
   writeln( 'Book 2 subject : ', Book2.subject);
   writeln( 'Book 2 book_id : ', Book2.book_id);
end.

编译并执行上述代码时,会产生以下结果 -

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

记录为子程序参数

您可以将记录作为子程序参数传递,与传递任何其他变量或指针的方式非常相似。 您可以按照上面示例中访问的方式访问记录字段 -

program exRecords;
type
Books = record
   title: packed array [1..50] of char;
   author: packed array [1..50] of char;
   subject: packed array [1..100] of char;
   book_id: longint;
end;
var
   Book1, Book2: Books; (* Declare Book1 and Book2 of type Books *)
(* procedure declaration *)
procedure printBook( var book: Books );
begin
   (* print Book info *)
   writeln ('Book  title : ', book.title);
   writeln('Book  author : ', book.author);
   writeln( 'Book  subject : ', book.subject);
   writeln( 'Book book_id : ', book.book_id);
end;
begin
   (* book 1 specification *)
   Book1.title  := 'C Programming';
   Book1.author := 'Nuha Ali '; 
   Book1.subject := 'C Programming Tutorial';
   Book1.book_id := 6495407;
   (* book 2 specification *)
   Book2.title := 'Telecom Billing';
   Book2.author := 'Zara Ali';
   Book2.subject := 'Telecom Billing Tutorial';
   Book2.book_id := 6495700;
   (* print Book1 info *)
   printbook(Book1);
   writeln; 
   (* print Book2 info *)
   printbook(Book2);
end.

编译并执行上述代码时,会产生以下结果 -

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

指针记录

您可以按照与定义指向任何其他变量的指针非常类似的方式定义指向记录的指针,如下所示 -

type
record-ptr = ^ record-name;
record-name = record
   field-1: field-type1;
   field-2: field-type2;
   ...
   field-n: field-typen;
end;

现在,您可以将记录类型变量的地址存储在上面定义的指针变量中。 要声明已创建指针类型的变量,请使用var关键字 -

var
   r1, r2, ... : record-ptr;

在使用这些指针之前,必须为记录名称类型变量创建存储,这些变量将由这些指针操作。

new(r1);
new(r2);

要使用指向该记录的指针访问记录成员,必须使用^。 运算符如下 -

r1^.feild1 := value1;
r1^.feild2 := value2;
...
r1^fieldn := valuen;

最后,当不再使用存储时,不要忘记将其用于处置 -

dispose(r1);
dispose(r2);

让我们使用指向Books记录的指针重写第一个示例。 希望您能够轻松理解这个概念 -

program exRecords;
type
BooksPtr = ^ Books;
Books = record
   title: packed array [1..50] of char;
   author: packed array [1..50] of char;
   subject: packed array [1..100] of char;
   book_id: longint;
end;
var
  (* Declare Book1 and Book2 of pointer type that refers to Book type *)
   Book1, Book2: BooksPtr; 
begin
   new(Book1);
   new(book2);
   (* book 1 specification *)
   Book1^.title  := 'C Programming';
   Book1^.author := 'Nuha Ali '; 
   Book1^.subject := 'C Programming Tutorial';
   Book1^.book_id := 6495407;
   (* book 2 specification *)
   Book2^.title := 'Telecom Billing';
   Book2^.author := 'Zara Ali';
   Book2^.subject := 'Telecom Billing Tutorial';
   Book2^.book_id := 6495700;
   (* print Book1 info *)
   writeln ('Book 1 title : ', Book1^.title);
   writeln('Book 1 author : ', Book1^.author);
   writeln( 'Book 1 subject : ', Book1^.subject);
   writeln( 'Book 1 book_id : ', Book1^.book_id);
   (* print Book2 info *)
   writeln ('Book 2 title : ', Book2^.title);
   writeln('Book 2 author : ', Book2^.author);
   writeln( 'Book 2 subject : ', Book2^.subject);
   writeln( 'Book 2 book_id : ', Book2^.book_id);
   dispose(Book1); 
   dispose(Book2);
end.

编译并执行上述代码时,会产生以下结果 -

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

With 语句

我们已经讨论过可以使用成员访问运算符(。)访问记录的成员。 这样,每次都必须写入记录变量的名称。 With语句提供了另一种方法。

请看我们的第一个示例中的以下代码片段 -

   (* book 1 specification *)
   Book1.title  := 'C Programming';
   Book1.author := 'Nuha Ali '; 
   Book1.subject := 'C Programming Tutorial';
   Book1.book_id := 6495407;

可以使用With语句编写相同的赋值 -

(* book 1 specification *)
With Book1 do
begin
   title  := 'C Programming';
   author := 'Nuha Ali '; 
   subject := 'C Programming Tutorial';
   book_id := 6495407;
end;

Pascal - Variants

Pascal支持一种名为variant的独特存储类型。 您可以在变量变量中指定任何简单类型的值。 存储在变体中的值的类型仅在运行时确定。 几乎任何简单类型都可以分配给变体:序数类型,字符串类型,int64类型。

结构化类型(如集合,记录,数组,文件,对象和类)与变量不是分配兼容的。 您还可以指定变量的指针。

Free Pascal支持变体。

声明变体

您可以使用var关键字声明变体类型,就像任何其他类型一样。 声明变体类型的语法是 -

var
   v: variant;

现在,这个变量变量v可以分配给几乎所有简单类型,包括枚举类型,反之亦然。

type  
   color = (red, black, white);  
var  
   v : variant;  
   i : integer;  
   b : byte;  
   w : word;  
   q : int64;  
   e : extended;  
   d : double;  
   en : color;  
   as : ansistring;  
   ws : widestring;  
begin  
   v := i;  
   v := b;  
   v := w;  
   v := q;  
   v := e;  
   v := en;  
   v := d:  
   v := as;  
   v := ws;  
end;

例子 (Example)

以下示例将说明这一概念 -

Program exVariant;
uses variants;
type
   color = (red, black, white);
var
   v : variant;
   i : integer;
   r: real;
   c : color;
   as : ansistring;
begin
   i := 100;
   v:= i;
   writeln('Variant as Integer: ', v);
   r:= 234.345;
   v:= r;
   writeln('Variant as real: ', v);
   c := red;
   v := c;
   writeln('Variant as Enumerated data: ', v);
   as:= ' I am an AnsiString';
   v:= as;
   writeln('Variant as AnsiString: ', v);
end.

编译并执行上述代码时,会产生以下结果 -

Variant as Integer: 100
Variant as real: 234.345
Variant as Enumerated data: 0
Variant as AnsiString: I am an AnsiString

Pascal - Sets

集合是相同类型的元素的集合。 Pascal允许定义设置数据类型。 集合中的元素称为其成员。 在数学中,集合通过将成员braces{}braces{}内来表示。 但是,在Pascal中,set元素包含在方括号[]中,它们被称为set构造函数。

定义集类型和变量

Pascal集类型定义为

type
set-identifier = set of base type;

集类型的变量定义为

var
s1, s2, ...: set-identifier;

要么,

s1, s2...: set of base type;

一些有效的集类型声明的示例是 -

type
Days = (mon, tue, wed, thu, fri, sat, sun);
Letters = set of char;
DaySet = set of days;
Alphabets = set of 'A' .. 'Z';
studentAge = set of 13..20;

设置运算符

您可以在Pascal集上执行以下设置操作。

Sr.No 操作和描述
1

Union

这将连接两个集合,并为两个集合中的成员提供一个新集合。

2

Difference

获取两个集合的差异,并给出一个新集合,其中的元素与任何集合都不相同。

3

Intersection

获取两个集合的交集,并给出一个新集合,其中包含两个集合共有的元素。

4

Inclusion

如果P中的所有项目也在Q中但是反之亦然,则集合P包括在集合Q中。

5

Symmetric difference

获取两个集合的对称差异,并给出一组元素,这些元素位于任一集合中,而不是在它们的交集中。

6

In

它检查会员资格。

下表显示了Free Pascal支持的所有集合运算符。 假设S1S2是两个字符集,这样 -

S1:= ['a','b','c'];

S2:= ['c','d','e'];

操作者 描述
+ 联盟两套

S1 + S2将给出一组

['a','b','c','d','e']

- 两套的差异

S1-S2将给出一组

['a','b']

* 交叉两套

S1 * S2将给出一组

['C']

>< 两组的对称差异 S1>
= 检查两组的相等性 S1 = S2将给出布尔值False
<> 检查两组不相等 S1 <> S2将给出布尔值True
<= 包含(检查一组是否是另一组的子集) S1 <= S2将给出布尔值False
Include 包括集合中的元素; 基本上它是一个集合的联合和一个相同基类型的元素

包含(S1,['d'])将给出一组

['A B C D']

Exclude 从集合中排除元素; 基本上它是一个集合的差异和相同基本类型的元素

排除(S2,['d'])将给出一组

['c','e']

In 检查设置集合中元素的成员资格 S2中的['e']给出布尔值True

例子 (Example)

以下示例说明了其中一些运算符的使用 -

program setColors;
type  
color = (red, blue, yellow, green, white, black, orange);  
colors = set of color;  
procedure displayColors(c : colors);  
const  
names : array [color] of String[7]  
  = ('red', 'blue', 'yellow', 'green', 'white', 'black', 'orange');  
var  
   cl : color;  
   s : String;  
begin  
   s:= ' ';  
   for cl:=red to orange do  
      if cl in c then  
      begin  
         if (s<>' ') then s :=s +' , ';  
         s:=s+names[cl];  
      end;  
   writeln('[',s,']');  
end;  
var  
   c : colors;  
begin  
   c:= [red, blue, yellow, green, white, black, orange];
   displayColors(c);
   c:=[red, blue]+[yellow, green]; 
   displayColors(c);  
   c:=[red, blue, yellow, green, white, black, orange] - [green, white];     
   displayColors(c);    
   c:= [red, blue, yellow, green, white, black, orange]*[green, white];     
   displayColors(c);  
   c:= [red, blue, yellow, green]><[yellow, green, white, black]; 
   displayColors(c);  
end.

编译并执行上述代码时,会产生以下结果 -

[ red , blue , yellow , green , white , black , orange]
[ red , blue , yellow , green]
[ red , blue , yellow , black , orange]
[ green , white]
[ red , blue , white , black]

Pascal - File Handling

Pascal将文件视为一系列组件,它们必须是统一类型。 文件的类型由组件的类型决定。 文件数据类型定义为 -

type
file-name = file of base-type;

其中,base-type表示文件组件的类型。 除了另一种文件类型之外,基类型可以是整数,实数,布尔,枚举,子范围,记录,数组和集合。 使用var声明创建文件类型的变量 -

var
f1, f2,...: file-name;

以下是定义一些文件类型和文件变量的一些示例 -

type
   rfile = file of real;
   ifile = file of integer;
   bfile = file of boolean;
   datafile = file of record
   arrfile = file of array[1..4] of integer;
var
   marks: arrfile;
   studentdata: datafile;
   rainfalldata: rfile;
   tempdata: ifile;
   choices: bfile;

创建和写入文件

让我们编写一个程序,为学生的记录创建一个数据文件。 它会创建一个名为students.dat的文件,并将学生的数据写入其中 -

program DataFiles;
type
   StudentRecord = Record
      s_name: String;
      s_addr: String;
      s_batchcode: String;
   end;
var
   Student: StudentRecord;
   f: file of StudentRecord;
begin
   Assign(f,'students.dat');
   Rewrite(f);
   Student.s_name := 'John Smith';
   Student.s_addr := 'United States of America';
   Student.s_batchcode := 'Computer Science';
   Write(f,Student);
   Close(f);
end.

编译和运行时,程序会在工作目录中创建一个名为students.dat的文件。 您可以使用文本编辑器(如记事本)打开文件,以查看John Smith的数据。

从文件中读取 (Reading from a File)

我们刚刚创建并写入名为students.dat的文件中。 现在,让我们编写一个程序,从文件中读取学生的数据 -

program DataFiles;
type
   StudentRecord = Record
      s_name: String;
      s_addr: String;
      s_batchcode: String;
   end;
var
   Student: StudentRecord;
   f: file of StudentRecord;
begin
   assign(f, 'students.dat');
   reset(f); 
   while not eof(f) do
   begin
      read(f,Student);
      writeln('Name: ',Student.s_name);
      writeln('Address: ',Student.s_addr);
      writeln('Batch Code: ', Student.s_batchcode);
   end;
   close(f);
end.

编译并执行上述代码时,会产生以下结果 -

Name: John Smith
Address: United States of America
Batch Code: Computer Science

文件作为子程序参数

Pascal允许将文件变量用作标准和用户定义的子程序中的参数。 以下示例说明了此概念。 该程序创建一个名为rainfall.txt的文件并存储一些降雨数据。 接下来,它打开文件,读取数据并计算平均降雨量。

请注意, if you use a file parameter with subprograms, it must be declared as a var parameter.

program addFiledata;
const
   MAX = 4;
type
   raindata = file of real;
var
   rainfile: raindata;
   filename: string;
procedure writedata(var f: raindata);
var
   data: real;
   i: integer;
begin
   rewrite(f, sizeof(data));
   for i:=1 to MAX do
   begin
      writeln('Enter rainfall data: ');
      readln(data);
      write(f, data);
   end;
   close(f);
end;
procedure computeAverage(var x: raindata);
var
   d, sum: real;
   average: real;
begin
   reset(x);
   sum:= 0.0;
   while not eof(x) do
   begin
      read(x, d);
      sum := sum + d;
   end;
   average := sum/MAX;
   close(x);
   writeln('Average Rainfall: ', average:7:2);
end;
begin
   writeln('Enter the File Name: ');
   readln(filename);
   assign(rainfile, filename);
   writedata(rainfile);
   computeAverage(rainfile);
end.

编译并执行上述代码时,会产生以下结果 -

Enter the File Name:
rainfall.txt
Enter rainfall data:
34
Enter rainfall data:
45
Enter rainfall data:
56
Enter rainfall data:
78
Average Rainfall: 53.25

文本文件

Pascal中的文本文件由字符行组成,其中每行以行尾标记结束。 您可以声明并定义这样的文件 -

type
file-name = text;

普通字符文件和文本文件之间的区别在于文本文件被分成行,每行由特殊的行尾标记终止,由系统自动插入。 以下示例创建并写入名为contact.txt的文本文件 -

program exText;
var
   filename, data: string;
   myfile: text;
begin
   writeln('Enter the file name: ');
   readln(filename);
   assign(myfile, filename);
   rewrite(myfile);
   writeln(myfile, 'Note to Students: ');
   writeln(myfile, 'For details information on Pascal Programming');
   writeln(myfile, 'Contact: IOWIKI');
   writeln('Completed writing'); 
   close(myfile);
end.

编译并执行上述代码时,会产生以下结果 -

Enter the file name:
contact.txt 
Completed writing

附加到文件

附加到文件意味着写入已经包含某些数据的现有文件而不覆盖该文件。 以下程序说明了这一点 -

program exAppendfile;
var
   myfile: text;
   info: string;
begin
   assign(myfile, 'contact.txt');
   append(myfile);
   writeln('Contact Details');
   writeln('webmaster@iowiki.com');
   close(myfile);
   (* let us read from this file *)
   assign(myfile, 'contact.txt');
   reset(myfile);
   while not eof(myfile) do
   begin
      readln(myfile, info);
      writeln(info);
   end;
   close(myfile);
end.

编译并执行上述代码时,会产生以下结果 -

Contact Details
webmaster@iowiki.com
Note to Students:
For details information on Pascal Programming
Contact: IOWIKI

文件处理函数 (File Handling Functions)

Free Pascal提供以下文件处理功能/程序 -

Sr.No. 功能名称和描述
1

procedure Append(var t: Text);

以附加模式打开文件

2

procedure Assign(out f: file; const Name:);

为文件指定名称

3

procedure Assign(out f: file; p: PChar);

为文件指定名称

4

procedure Assign(out f: file; c: Char);

为文件指定名称

5

procedure Assign(out f: TypedFile; const Name:);

为文件指定名称

6

procedure Assign(out f: TypedFile; p: PChar);

为文件指定名称

7

procedure Assign(out f: TypedFile; c: Char);

为文件指定名称

8

procedure Assign(out t: Text; const s:);

为文件指定名称

9

procedure Assign(out t: Text; p: PChar);

为文件指定名称

10

procedure Assign(out t: Text; c: Char);

为文件指定名称

11

procedure BlockRead(var f: file; var Buf; count: Int64; var Result: Int64);

将文件中的数据读入内存

12

procedure BlockRead(var f: file; var Buf; count: LongInt; var Result: LongInt);

将文件中的数据读入内存

13

procedure BlockRead(var f: file; var Buf; count: Cardinal; var Result: Cardinal);

将文件中的数据读入内存

14

procedure BlockRead(var f: file; var Buf; count: Word; var Result: Word);

将文件中的数据读入内存

15

procedure BlockRead(var f: file; var Buf; count: Word; var Result: Integer);

将文件中的数据读入内存

16

procedure BlockRead(var f: file; var Buf; count: Int64);

将文件中的数据读入内存

17

procedure BlockWrite(var f: file; const Buf; Count: Int64; var Result: Int64);

将数据从内存写入文件

18

procedure BlockWrite(var f: file; const Buf; Count: LongInt; var Result: LongInt);

将数据从内存写入文件

19

procedure BlockWrite(var f: file; const Buf; Count: Cardinal; var Result: Cardinal);

将数据从内存写入文件

20

procedure BlockWrite(var f: file; const Buf; Count: Word; var Result: Word);

将数据从内存写入文件

21

procedure BlockWrite(var f: file; const Buf; Count: Word; var Result: Integer);

将数据从内存写入文件

22

procedure BlockWrite(var f: file; const Buf; Count: LongInt);

将数据从内存写入文件

23

procedure Close(var f: file);

关闭文件

24

procedure Close(var t: Text);

关闭文件

25

function EOF(var f: file):Boolean;

检查文件结尾

26

function EOF(var t: Text):Boolean;

检查文件结尾

27

function EOF: Boolean;

检查文件结尾

28

function EOLn(var t: Text):Boolean;

检查行尾

29

function EOLn: Boolean;

检查行尾

30

procedure Erase(var f: file);

从磁盘删除文件

31

procedure Erase(var t: Text);

从磁盘删除文件

32

function FilePos( var f: file):Int64;

在文件中的位置

33

function FileSize(var f: file):Int64;

文件大小

34

procedure Flush(var t: Text);

将文件缓冲区写入磁盘

35

function IOResult: Word;

返回上一个文件IO操作的结果

36

procedure Read(var F: Text; Args: Arguments);

从文件读入变量

37

procedure Read(Args: Arguments);

从文件读入变量

38

procedure ReadLn(var F: Text; Args: Arguments);

从文件读入变量并转到下一行

39

procedure ReadLn(Args: Arguments);

从文件读入变量并转到下一行

40

procedure Rename(var f: file; const s:);

重命名磁盘上的文件

41

procedure Rename(var f: file; p: PChar);

重命名磁盘上的文件

42

procedure Rename(var f: file; c: Char);

重命名磁盘上的文件

43

procedure Rename(var t: Text; const s);

重命名磁盘上的文件

44

procedure Rename(var t: Text; p: PChar);

重命名磁盘上的文件

45

procedure Rename( var t: Text; c: Char);

重命名磁盘上的文件

46

procedure Reset(var f: file; l: LongInt);

打开文件进行阅读

47

procedure Reset(var f: file);

打开文件进行阅读

48

procedure Reset(var f: TypedFile);

打开文件进行阅读

49

procedure Reset(var t: Text);

打开文件进行阅读

50

procedure Rewrite(var f: file; l: LongInt);

打开文件进行写入

51

procedure Rewrite(var f: file);

打开文件进行写入

52

procedure Rewrite(var f: TypedFile);

打开文件进行写入

53

procedure Rewrite(var t: Text);

打开文件进行写入

54

procedure Seek(var f: file; Pos: Int64);

设置文件位置

55

function SeekEOF(var t: Text):Boolean;

将文件位置设置为文件末尾

56

function SeekEOF: Boolean;

将文件位置设置为文件末尾

57

function SeekEOLn(var t: Text):Boolean;

将文件位置设置为行尾

58

function SeekEOLn: Boolean;

将文件位置设置为行尾

59

procedure SetTextBuf(var f: Text; var Buf);

设置文件缓冲区的大小

60

procedure SetTextBuf(var f: Text; var Buf; Size: SizeInt);

设置文件缓冲区的大小

61

procedure Truncate(var F: file);

在位置截断文件

62

procedure Write(Args: Arguments);

将变量写入文件

63

procedure Write(var F: Text; Args: Arguments);

将变量写入文件

64

procedure Writeln(Args: Arguments);

将变量写入文件并附加换行符

65

procedure WriteLn(var F: Text; Args: Arguments);

将变量写入文件并附加换行符

Pascal - Memory Management

本章介绍Pascal中的动态内存管理。 Pascal编程语言为内存分配和管理提供了多种功能。

动态分配内存

在进行编程时,如果您了解数组的大小,那么它很容易,您可以将其定义为数组。 例如,要存储任何人的姓名,它最多可以包含100个字符,因此您可以按如下方式定义内容 -

var
name: array[1..100] of char;

但现在,让我们考虑一种情况,您不知道需要存储的文本的长度,例如,您想要存储有关主题的详细说明。 在这里,我们需要定义一个指向string的指针,而不需要定义需要多少内存。

Pascal提供了一个new的过程来创建指针变量。

program exMemory;
var
name: array[1..100] of char;
description: ^string;
begin
   name:= 'Zara Ali';
   new(description);
      if not assigned(description) then
         writeln(' Error - unable to allocate required memory')
      else
         description^ := 'Zara ali a DPS student in class 10th';
   writeln('Name = ', name );
   writeln('Description: ', description^ );
end.

编译并执行上述代码时,会产生以下结果 -

Name = Zara Ali
Description: Zara ali a DPS student in class 10th

现在,如果您需要定义一个具有特定字节数的指针,稍后将引用它,您应该使用getmem函数或getmem过程,它具有以下语法 -

procedure Getmem(
   out p: pointer;
   Size: PtrUInt
);
function GetMem(
   size: PtrUInt
):pointer;

在前面的示例中,我们声明了一个指向字符串的指针。 字符串的最大值为255个字节。 如果你真的不需要那么多的空间或更大的空间,就字节而言, getmem子程序允许指定它。 让我们使用getmem重写前面的例子 -

program exMemory;
var
name: array[1..100] of char;
description: ^string;
begin
   name:= 'Zara Ali';
   description := getmem(200);
      if not assigned(description) then
         writeln(' Error - unable to allocate required memory')
      else
         description^ := 'Zara ali a DPS student in class 10th';
   writeln('Name = ', name );
   writeln('Description: ', description^ );
   freemem(description);
end.

编译并执行上述代码时,会产生以下结果 -

Name = Zara Ali
Description: Zara ali a DPS student in class 10th

因此,您可以完全控制并且可以在分配内存时传递任何大小的值,而不像数组一样,一旦定义了大小,就无法更改。

调整大小和释放内存

当你的程序出来时,操作系统会自动释放程序分配的所有内存,但是当你不再需要内存时,这是一个很好的做法,那么你应该释放那个内存。

Pascal提供了使用new.过程释放动态创建的变量的过程new. 如果使用getmem子程序分配了内存,则需要使用子程序freemem释放该内存。 freemem子程序具有以下语法 -

procedure Freemem(
   p: pointer;
  Size: PtrUInt
);
function Freemem(
   p: pointer
):PtrUInt;

或者,您可以通过调用ReAllocMem函数来增加或减少分配的内存块的大小。 让我们再次检查上面的程序,并使用ReAllocMemfreemem子程序。 以下是ReAllocMem的语法 -

function ReAllocMem(
   var p: pointer;
   Size: PtrUInt
):pointer;   

以下是使用ReAllocMemfreemem子程序的示例 -

program exMemory;
var
name: array[1..100] of char;
description: ^string;
desp: string;
begin
   name:= 'Zara Ali';
   desp := 'Zara ali a DPS student.';
   description := getmem(30);
      if not assigned(description) then
         writeln('Error - unable to allocate required memory')
      else
         description^ := desp;
   (* Suppose you want to store bigger description *)
   description := reallocmem(description, 100);
   desp := desp + ' She is in class 10th.';
   description^:= desp; 
   writeln('Name = ', name );
   writeln('Description: ', description^ );
   freemem(description);
end.

编译并执行上述代码时,会产生以下结果 -

Name = Zara Ali
Description: Zara ali a DPS student. She is in class 10th

内存管理函数 (Memory Management Functions)

Pascal提供了大量内存管理功能,用于实现各种数据结构并在Pascal中实现低级编程。 其中许多功能都依赖于实现。 Free Pascal提供以下内存管理功能和程序 -

SN 功能名称和描述
1

function Addr(X: TAnytype):Pointer;

返回变量的地址

2

function Assigned(P: Pointer):Boolean;

检查指针是否有效

3

function CompareByte(const buf1; const buf2; len: SizeInt):SizeInt;

每字节比较2个内存缓冲区字节

4

function CompareChar(const buf1; const buf2; len: SizeInt):SizeInt;

每字节比较2个内存缓冲区字节

5

function CompareDWord(const buf1; const buf2; len: SizeInt):SizeInt;

每字节比较2个内存缓冲区字节

6

function CompareWord(const buf1; const buf2; len: SizeInt):SizeInt;

每字节比较2个内存缓冲区字节

7

function Cseg: Word;

返回代码段

8

procedure Dispose(P: Pointer);

释放动态分配的内存

9

procedure Dispose(P: TypedPointer; Des: TProcedure);

释放动态分配的内存

10

function Dseg: Word;

返回数据段

11

procedure FillByte(var x; count: SizeInt; value: Byte);

用8位模式填充内存区域

12

procedure FillChar( var x; count: SizeInt; Value: Byte|Boolean|Char);

填充具有特定字符的内存区域

13

procedure FillDWord( var x; count: SizeInt; value: DWord);

使用32位模式填充内存区域

14

procedure FillQWord( var x; count: SizeInt; value: QWord);

使用64位模式填充内存区域

15 procedure FillWord( var x; count: SizeInt; Value: Word);

使用16位模式填充内存区域

16

procedure Freemem( p: pointer; Size: PtrUInt);

释放分配的内存

17

procedure Freemem( p: pointer );

释放分配的内存

18

procedure Getmem( out p: pointer; Size: PtrUInt);

分配新内存

19

procedure Getmem( out p: pointer);

分配新内存

20

procedure GetMemoryManager( var MemMgr: TMemoryManager);

返回当前内存管理器

21

function High( Arg: TypeOrVariable):TOrdinal;

返回open数组或枚举的最高索引

22

function IndexByte( const buf; len: SizeInt; b: Byte):SizeInt;

在内存范围中查找字节大小的值

23

function IndexChar( const buf; len: SizeInt; b: Char):SizeInt;

在内存范围中查找char大小的值

24

function IndexDWord( const buf; len: SizeInt; b: DWord):SizeInt;

在内存范围中查找DWord大小(32位)的值

25

function IndexQWord( const buf; len: SizeInt; b: QWord):SizeInt;

在内存范围中查找QWord大小的值

26

function Indexword( const buf; len: SizeInt; b: Word):SizeInt;

在内存范围中查找字大小的值

27

function IsMemoryManagerSet: Boolean;

是否设置了内存管理器

28

function Low( Arg: TypeOrVariable ):TOrdinal;

返回打开数组或枚举的最低索引

29

procedure Move( const source; var dest; count: SizeInt );

将数据从内存中的一个位置移动到另一个位置

30

procedure MoveChar0( const buf1; var buf2; len: SizeInt);

将数据移动到第一个零字符

31

procedure New( var P: Pointer);

为变量动态分配内存

32

procedure New( var P: Pointer; Cons: TProcedure);

动态地为变量分配内存

33

function Ofs( var X ):LongInt;

返回变量的偏移量

34

function ptr( sel: LongInt; off: LongInt):farpointer;

将段和偏移量组合到指针

35

function ReAllocMem( var p: pointer; Size: PtrUInt):pointer;

调整堆上的内存块大小

36

function Seg( var X):LongInt;

返回段

37

procedure SetMemoryManager( const MemMgr: TMemoryManager );

设置内存管理器

38

function Sptr: Pointer;

返回当前堆栈指针

39

function Sseg: Word;

返回堆栈段寄存器值

Pascal - Units

Pascal程序可以包含称为单元的模块。 一个单元可能包含一些代码块,而这些代码块又由变量和类型声明,语句,过程等组成.Pascal和Pascal中有许多内置单元允许程序员定义和编写自己的单元以供使用后来在各种节目中。

使用内置单元

使用子句将内置单元和用户定义单元都包含在程序中。 我们已经在Pascal - Variants教程中使用了变体单元。 本教程介绍如何创建和包含用户定义的单元。 但是,让我们首先看看如何在程序中包含内置单元crt -

program myprog;
uses crt;

以下示例说明了使用crt单元 -

Program Calculate_Area (input, output);
uses crt;
var 
   a, b, c, s, area: real;
begin
   textbackground(white); (* gives a white background *)
   clrscr; (*clears the screen *)
   textcolor(green); (* text color is green *)
   gotoxy(30, 4); (* takes the pointer to the 4th line and 30th column) 
   writeln('This program calculates area of a triangle:');
   writeln('Area = area = sqrt(s(s-a)(s-b)(s-c))');
   writeln('S stands for semi-perimeter');
   writeln('a, b, c are sides of the triangle');
   writeln('Press any key when you are ready');
   readkey;
   clrscr;
   gotoxy(20,3);
   write('Enter a: ');
   readln(a);
   gotoxy(20,5);
   write('Enter b:');
   readln(b);
   gotoxy(20, 7);
   write('Enter c: ');
   readln(c);
   s := (a + b + c)/2.0;
   area := sqrt(s * (s - a)*(s-b)*(s-c));
   gotoxy(20, 9);
   writeln('Area: ',area:10:3);
   readkey;
end.

它与我们在Pascal教程开头使用的程序相同,编译并运行它以查找更改的效果。

创建和使用Pascal单元

要创建单元,您需要编写要存储在其中的模块或子程序,并将其保存在扩展名为.pas的文件中。 此文件的第一行应以关键字unit开头,后跟单元名称。 例如 -

unit calculateArea;

以下是创建Pascal单元的三个重要步骤 -

  • 文件名和单元名应完全相同。 因此,我们的单位calculateArea将保存在名为calculateArea.pas.的文件中calculateArea.pas.

  • 下一行应包含单个关键字interface 。 在此行之后,您将编写本单元中将包含的所有函数和过程的声明。

  • 在函数声明之后,写下单词implementation ,这又是一个关键字。 在包含关键字实现的行之后,提供所有子程序的定义。

以下程序创建名为calculateArea的单元 -

unit CalculateArea;
interface
function RectangleArea( length, width: real): real;
function CircleArea(radius: real) : real;
function TriangleArea( side1, side2, side3: real): real;
implementation
function RectangleArea( length, width: real): real;
begin
   RectangleArea := length * width;
end;
function CircleArea(radius: real) : real;
const
   PI = 3.14159;
begin
   CircleArea := PI * radius * radius;
end;
function TriangleArea( side1, side2, side3: real): real;
var
   s, area: real;
begin
   s := (side1 + side2 + side3)/2.0;
   area := sqrt(s * (s - side1)*(s-side2)*(s-side3));
   TriangleArea := area;
end;
end.

接下来,让我们编写一个使用上面定义的单元的简单程序 -

program AreaCalculation;
uses CalculateArea,crt;
var
   l, w, r, a, b, c, area: real;
begin
   clrscr;
   l := 5.4;
   w := 4.7;
   area := RectangleArea(l, w);
   writeln('Area of Rectangle 5.4 x 4.7 is: ', area:7:3);
   r:= 7.0;
   area:= CircleArea(r);
   writeln('Area of Circle with radius 7.0 is: ', area:7:3);
   a := 3.0;
   b:= 4.0;
   c:= 5.0;
   area:= TriangleArea(a, b, c);
   writeln('Area of Triangle 3.0 by 4.0 by 5.0 is: ', area:7:3);
end.

编译并执行上述代码时,会产生以下结果 -

Area of Rectangle 5.4 x 4.7 is: 25.380
Area of Circle with radius 7.0 is: 153.938
Area of Triangle 3.0 by 4.0 by 5.0 is: 6.000

Pascal - Date and Time

您编写的大多数软件都需要实现某种形式的日期函数来返回当前日期和时间。 日期是日常生活的重要组成部分,无需思考即可轻松与他们合作。 Pascal还提供了强大的日期算术工具,可以轻松操作日期。 但是,对于不同的编译器,这些函数的实际名称和工作方式是不同的。

获取当前日期和时间

Pascal的TimeToString函数以冒号(:)分隔的形式为您提供当前时间。 以下示例显示如何获取当前时间 -

program TimeDemo;
uses sysutils;
begin
   writeln ('Current time : ',TimeToStr(Time));
end.

编译并执行上述代码时,会产生以下结果 -

Current time : 18:33:08

Date函数以TDateTime格式返回当前日期。 TDateTime是一个double值,需要一些解码和格式化。 以下程序演示了如何在程序中使用它来显示当前日期 -

Program DateDemo;
uses sysutils;
var
   YY,MM,DD : Word;
begin
   writeln ('Date : ',Date);
   DeCodeDate (Date,YY,MM,DD);
   writeln (format ('Today is (DD/MM/YY): %d/%d/%d ',[dd,mm,yy]));
end.

编译并执行上述代码时,会产生以下结果 -

Date: 4.111300000000000E+004
Today is (DD/MM/YY):23/7/2012

Now函数返回当前日期和时间 -

Program DatenTimeDemo;
uses sysutils;
begin
   writeln ('Date and Time at the time of writing : ',DateTimeToStr(Now));
end.

编译并执行上述代码时,会产生以下结果 -

Date and Time at the time of writing : 23/7/2012 18:51:

Free Pascal提供了一个名为TTimeStamp的简单时间戳结构,它具有以下格式 -

type TTimeStamp = record
   Time: Integer;
   Date: Integer;
end;

各种日期和时间功能

Free Pascal提供以下日期和时间功能 -

Sr.No. 功能名称和描述
1

function DateTimeToFileDate(DateTime: TDateTime):LongInt;

将DateTime类型转换为文件日期。

2

function DateTimeToStr( DateTime: TDateTime):;

构造DateTime的字符串表示形式

3

function DateTimeToStr(DateTime: TDateTime; const FormatSettings: TFormatSettings):;

构造DateTime的字符串表示形式

4

procedure DateTimeToString(out Result: ;const FormatStr: ;const DateTime: TDateTime);

构造DateTime的字符串表示形式

5

procedure DateTimeToString(out Result: ; const FormatStr: ; const DateTime: TDateTime; const FormatSettings: TFormatSettings);

构造DateTime的字符串表示形式

6

procedure DateTimeToSystemTime(DateTime: TDateTime; out SystemTime: TSystemTime);

将DateTime转换为系统时间

7

function DateTimeToTimeStamp( DateTime: TDateTime):TTimeStamp; 将DateTime转换为时间戳

8

function DateToStr(Date: TDateTime):;

构造日期的字符串表示

9

function DateToStr(Date: TDateTime; const FormatSettings: TFormatSettings):;

构造日期的字符串表示

10

function Date: TDateTime;

获取当前日期

11

function DayOfWeek(DateTime: TDateTime):Integer;

获取星期几

12

procedure DecodeDate(Date: TDateTime; out Year: Word; out Month: Word; out Day: Word);

将DateTime解码为年月和日

13

procedure DecodeTime(Time: TDateTime; out Hour: Word; out Minute: Word; out Second: Word; out MilliSecond: Word);

将DateTime解码为小时,分钟和秒

14

function EncodeDate(Year: Word; Month: Word; Day: Word):TDateTime;

将日期,日期和月份编码为DateTime

15

function EncodeTime(Hour: Word; Minute: Word; Second: Word; MilliSecond: Word):TDateTime;

将日期,分钟和秒编码到DateTime

16

function FormatDateTime(const FormatStr: ; DateTime: TDateTime):;

返回DateTime的字符串表示形式

17

function FormatDateTime(const FormatStr: ; DateTime: TDateTime; const FormatSettings: TFormatSettings):;

返回DateTime的字符串表示形式

18

function IncMonth(const DateTime: TDateTime; NumberOfMonths: Integer = 1):TDateTime;

添加1个月

19

function IsLeapYear(Year: Word):Boolean;

确定年份是否为闰年

20

function MSecsToTimeStamp(MSecs: Comp):TTimeStamp;

将毫秒数转换为时间戳

21

function Now: TDateTime;

获取当前日期和时间

22

function StrToDateTime(const S:):TDateTime;

将字符串转换为DateTime

23

function StrToDateTime(const s: ShortString; const FormatSettings: TFormatSettings):TDateTime;

将字符串转换为DateTime

24

function StrToDateTime(const s: AnsiString; const FormatSettings: TFormatSettings):TDateTime;

将字符串转换为DateTime

25

function StrToDate(const S: ShortString):TDateTime;

将字符串转换为日期

26

function StrToDate(const S: Ansistring):TDateTime;

将字符串转换为日期

27

function StrToDate(const S: ShortString; separator: Char):TDateTime;

将字符串转换为日期

28

function StrToDate(const S: AnsiString; separator: Char):TDateTime;

将字符串转换为日期

29

function StrToDate(const S: ShortString; const useformat: ; separator: Char):TDateTime;

将字符串转换为日期

30

function StrToDate(const S: AnsiString; const useformat: ; separator: Char):TDateTime;

将字符串转换为日期

31

function StrToDate(const S: PChar; Len: Integer; const useformat: ; separator: Char = #0):TDateTime;

将字符串转换为日期

32

function StrToTime(const S: Shortstring):TDateTime;

将字符串转换为时间

33

function StrToTime(const S: Ansistring):TDateTime;

将字符串转换为时间

34

function StrToTime(const S: ShortString; separator: Char):TDateTime;

将字符串转换为时间

35

function StrToTime(const S: AnsiString; separator: Char):TDateTime;

将字符串转换为时间

36

function StrToTime(const S: ; FormatSettings: TFormatSettings):TDateTime;

将字符串转换为时间

37

function StrToTime(const S: PChar; Len: Integer; separator: Char = #0):TDateTime;

将字符串转换为时间

38

function SystemTimeToDateTime(const SystemTime: TSystemTime):TDateTime;

将系统时间转换为日期时间

39

function TimeStampToDateTime(const TimeStamp: TTimeStamp):TDateTime;

将时间戳转换为DateTime

40

function TimeStampToMSecs(const TimeStamp: TTimeStamp):comp;

将时间戳转换为毫秒数

41

function TimeToStr(Time: TDateTime):;

返回Time的字符串表示形式

42

function TimeToStr(Time: TDateTime; const FormatSettings: TFormatSettings):;

返回Time的字符串表示形式

43

function Time: TDateTime;

获取当前时间

以下示例说明了上述某些功能的使用 -

Program DatenTimeDemo;
uses sysutils;
var
year, month, day, hr, min, sec, ms: Word;
begin
   writeln ('Date and Time at the time of writing : ',DateTimeToStr(Now));
   writeln('Today is ',LongDayNames[DayOfWeek(Date)]);
   writeln;
   writeln('Details of Date: ');
   DecodeDate(Date,year,month,day);
   writeln (Format ('Day: %d',[day]));
   writeln (Format ('Month: %d',[month]));
   writeln (Format ('Year: %d',[year]));
   writeln;
   writeln('Details of Time: ');
   DecodeTime(Time,hr, min, sec, ms);
   writeln (format('Hour: %d:',[hr]));
   writeln (format('Minutes: %d:',[min]));
   writeln (format('Seconds: %d:',[sec]));
   writeln (format('Milliseconds: %d:',[hr]));
end.

编译并执行上述代码时,会产生以下结果:

Date and Time at the time of writing : 7/24/2012 8:26:
Today is Tuesday
Details of Date:
Day:24
Month:7
Year: 2012
Details of Time:
Hour: 8
Minutes: 26
Seconds: 21
Milliseconds: 8

Pascal - Object Oriented

我们可以想象我们的宇宙由不同的物体组成,如太阳,地球,月亮等。同样,我们可以想象我们的汽车由不同的物体组成,如车轮,转向,齿轮等。同样,有面向对象的编程概念,假设所有内容都是对象,并使用不同的对象实现软件。 在Pascal中,有两种用于实现现实世界对象的结构数据类型 -

  • Object types
  • Class types

Object-Oriented Concepts

在我们详细介绍之前,让我们定义与面向对象Pascal相关的重要Pascal术语。

  • Object - 对象是一种特殊的记录,包含记录等字段; 但是,与记录不同,对象包含过程和函数作为对象的一部分。 这些过程和函数作为指向与对象类型相关的方法的指针。

  • Class - 类的定义方式与对象几乎相同,但它们的创建方式有所不同。 Class在程序的Heap上分配,而Object在Stack上分配。 它是指向对象的指针,而不是对象本身。

  • Instantiation of a class - 实例化意味着创建该类类型的变量。 由于类只是一个指针,当声明类类型的变量时,只为指针分配内存,而不是为整个对象分配内存。 只有在使用其构造函数对其进行实例化时,才会为该对象分配内存。 类的实例也称为“对象”,但不要将它们与Object Pascal对象混淆。 在本教程中,我们将为Pascal对象编写'Object',为概念对象或类实例编写'object'。

  • Member Variables - 这些是在类或对象中定义的变量。

  • Member Functions - 这些是在类或对象中定义的函数或过程,用于访问对象数据。

  • Visibility of Members - 对象或类的成员也称为字段。 这些领域具有不同的可见性。 可见性是指成员的可访问性,即这些成员可以访问的确切位置。 对象有三个可见性级别:public,private和protected。 类具有五种可见性类型:公共,私有,严格私有,受保护和已发布。 我们将详细讨论可见性。

  • Inheritance - 当通过继承父类的现有功能来定义类时,则认为它是继承的。 这里子类将继承父类的所有或几个成员函数和变量。 对象也可以继承。

  • Parent Class - 由另一个类继承的类。 这也称为基类或超类。

  • Child Class - 从另一个类继承的类。 这也称为子类或派生类。

  • Polymorphism - 这是一个面向对象的概念,其中相同的功能可用于不同的目的。 例如,函数名称将保持不变,但它可能需要不同数量的参数,并且可以执行不同的任务。 Pascal类实现多态。 对象不实现多态。

  • Overloading - 它是一种多态,其中一些或所有运算符具有不同的实现,具体取决于它们的参数类型。 类似地,函数也可以通过不同的实现来重载。 Pascal类实现重载,但Objects不实现。

  • Data Abstraction - 隐藏实现细节(抽象)的任何数据表示。

  • Encapsulation - 指我们将所有数据和成员函数封装在一起以形成对象的概念。

  • Constructor - 指特殊类型的函数,只要从类或对象形成对象,就会自动调用该函数。

  • Destructor函数 - 指一种特殊类型的函数,只要删除对象或类或超出范围,就会自动调用该函数。

定义Pascal对象

使用类型声明声明对象。 对象声明的一般形式如下 -

type object-identifier = object  
   private
   field1 : field-type;  
   field2 : field-type;  
   ...
   public
   procedure proc1;  
   function f1(): function-type;
   end;  
var objectvar : object-identifier;

让我们定义一个Rectangle Object,它有两个整数类型的数据成员 - lengthwidth以及一些用于操作这些数据成员的成员函数和一个绘制矩形的过程。

type 
   Rectangle = object  
   private  
      length, width: integer; 
   public  
      constructor init;  
      destructor done;  
      procedure setlength(l: inteter);  
      function getlength(): integer;  
      procedure setwidth(w: integer);  
      function getwidth(): integer;  
      procedure draw;
end;
var
   r1: Rectangle;
   pr1: ^Rectangle;

创建对象后,您将能够调用与该对象相关的成员函数。 一个成员函数只能处理相关对象的成员变量。

下面的示例演示如何设置两个矩形对象的长度和宽度,并通过调用成员函数来绘制它们。

r1.setlength(3);
r1.setwidth(7);
writeln(' Draw a rectangle: ', r1.getlength(), ' by ' , r1.getwidth());
r1.draw;
new(pr1);
pr1^.setlength(5);
pr1^.setwidth(4);
writeln(' Draw a rectangle: ', pr1^.getlength(), ' by ' ,pr1^.getwidth());
pr1^.draw;
dispose(pr1);

以下是一个完整的示例,说明如何在Pascal中使用对象 -

program exObjects;
type 
   Rectangle = object  
   private  
      length, width: integer; 
   public  
      procedure setlength(l: integer);
      function getlength(): integer;  
      procedure setwidth(w: integer);  
      function getwidth(): integer;  
      procedure draw;
end;
var
   r1: Rectangle;
   pr1: ^Rectangle;
procedure Rectangle.setlength(l: integer);
begin
   length := l;
end;
procedure Rectangle.setwidth(w: integer);
begin
   width :=w;
end;
function Rectangle.getlength(): integer;  
begin
   getlength := length;
end;
function Rectangle.getwidth(): integer;  
begin
   getwidth := width;
end;
procedure Rectangle.draw;
var 
   i, j: integer;
begin
   for i:= 1 to length do
   begin
     for j:= 1 to width do
        write(' * ');
     writeln;
   end;
end;
begin
   r1.setlength(3);
   r1.setwidth(7);
   writeln('Draw a rectangle:', r1.getlength(), ' by ' , r1.getwidth());
   r1.draw;
   new(pr1);
   pr1^.setlength(5);
   pr1^.setwidth(4);
   writeln('Draw a rectangle:', pr1^.getlength(), ' by ' ,pr1^.getwidth());
   pr1^.draw;
   dispose(pr1);
end.

编译并执行上述代码时,会产生以下结果 -

Draw a rectangle: 3 by 7
* * * * * * *
* * * * * * *
* * * * * * *
Draw a rectangle: 5 by 4
* * * *
* * * *
* * * *
* * * *
* * * *

对象成员的可见性

可见性表示对象成员的可访问性。 Pascal对象成员有三种类型的可见性 -

Sr.No 可见性和可访问性
1

Public

成员可以由程序单元外的其他单元使用

2

Private

成员只能在当前单位中访问。

3

Protected

成员仅可用于父对象的后续对象。

默认情况下,对象的字段和方法是公共的,并导出到当前单位之外。

Pascal对象的构造函数和析构函数 -

Constructors是特殊类型的方法,只要创建对象,就会自动调用这些方法。 只需通过声明一个带有关键字构造函数的方法,就可以在Pascal中创建一个构造函数。 通常,方法名称为Init,但是,您可以提供自己的任何有效标识符。 您可以将任意数量的参数传递给构造函数。

Destructors构函数是在销毁对象期间调用的方法。 析构函数方法会破坏构造函数创建的任何内存分配。

下面的示例将为Rectangle类提供构造函数和析构函数,它将在创建对象时初始化矩形的长度和宽度,并在超出作用域时将其销毁。

program exObjects;
type 
   Rectangle = object  
   private  
      length, width: integer; 
   public  
      constructor init(l, w: integer);
      destructor done;
      procedure setlength(l: integer);
      function getlength(): integer;  
      procedure setwidth(w: integer);  
      function getwidth(): integer;  
      procedure draw;
end;
var
   r1: Rectangle;
   pr1: ^Rectangle;
constructor Rectangle.init(l, w: integer);
begin
   length := l;
   width := w;
end;
destructor Rectangle.done;
begin
   writeln(' Desctructor Called');
end; 
procedure Rectangle.setlength(l: integer);
begin
   length := l;
end;
procedure Rectangle.setwidth(w: integer);
begin
   width :=w;
end;
function Rectangle.getlength(): integer;  
begin
   getlength := length;
end;
function Rectangle.getwidth(): integer;  
begin
   getwidth := width;
end;
procedure Rectangle.draw;
var 
   i, j: integer;
begin
   for i:= 1 to length do
   begin
      for j:= 1 to width do
         write(' * ');
      writeln;
   end;
end;
begin
   r1.init(3, 7);
   writeln('Draw a rectangle:', r1.getlength(), ' by ' , r1.getwidth());
   r1.draw;
   new(pr1, init(5, 4));
   writeln('Draw a rectangle:', pr1^.getlength(), ' by ',pr1^.getwidth());
   pr1^.draw;
   pr1^.init(7, 9);
   writeln('Draw a rectangle:', pr1^.getlength(), ' by ' ,pr1^.getwidth());
   pr1^.draw;
   dispose(pr1);
   r1.done;
end.

编译并执行上述代码时,会产生以下结果 -

Draw a rectangle: 3 by 7
* * * * * * *
* * * * * * *
* * * * * * *
Draw a rectangle: 5 by 4
* * * *
* * * *
* * * *
* * * *
* * * *
Draw a rectangle: 7 by 9
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
Destructor Called

Pascal对象的继承

Pascal对象可以选择从父对象继承。 以下程序说明了Pascal对象中的继承。 让我们创建另一个名为TableTop对象,它继承自Rectangle对象。

program exObjects;
type 
   Rectangle = object  
   private  
      length, width: integer; 
   public  
      procedure setlength(l: integer);  
      function getlength(): integer;  
      procedure setwidth(w: integer);  
      function getwidth(): integer;  
      procedure draw;
end;
TableTop = object (Rectangle)
   private
     material: string;
   public
      function getmaterial(): string;
      procedure setmaterial( m: string);
      procedure displaydetails;
      procedure draw;
end;
var
   tt1: TableTop;
procedure Rectangle.setlength(l: integer);
begin
   length := l;
end;
procedure Rectangle.setwidth(w: integer);
begin
   width :=w;
end;
function Rectangle.getlength(): integer;  
begin
   getlength := length;
end;
function Rectangle.getwidth():integer;
begin
   getwidth := width;
end;
procedure Rectangle.draw;
var 
   i, j: integer;
begin
   for i:= 1 to length do
   begin
      for j:= 1 to width do
         write(' * ');
      writeln;
  end;
end;
function TableTop.getmaterial(): string;
begin
   getmaterial := material;
end;
procedure TableTop.setmaterial( m: string);
begin
   material := m;
end;
procedure TableTop.displaydetails;
begin
   writeln('Table Top: ', self.getlength(), ' by ' , self.getwidth());
   writeln('Material: ', self.getmaterial());
end;
procedure TableTop.draw();
var
   i, j: integer;
begin
   for i:= 1 to length do
   begin
      for j:= 1 to width do
         write(' * ');
   writeln;
   end;
   writeln('Material: ', material);
end;
begin
   tt1.setlength(3);
   tt1.setwidth(7);
   tt1.setmaterial('Wood');
   tt1.displaydetails();
   writeln;
   writeln('Calling the Draw method');
   tt1.draw();
end.

以下是应注意的重点 -

  • 对象Tabletop继承了Rectangle对象的所有成员。

  • TableTop也有一个draw方法。 使用TableTop对象调用draw方法时,将调用TableTop的绘制。

  • 有一个名为self的隐式实例,它引用了对象的当前实例。

编译并执行上述代码时,会产生以下结果 -

Table Top: 3 by 7
Material: Wood
Calling the Draw Method 
* * * * * * *
* * * * * * *
* * * * * * *
Material: Wood

Pascal - Classes

您已经看到Pascal Objects展示了面向对象范式的一些特征。 它们实现了封装,数据隐藏和继承,但它们也有局限性。 例如,Pascal Objects不参与多态。 因此,类被广泛用于在程序中实现适当的面向对象行为,尤其是基于GUI的软件。

Class的定义方式与Object几乎相同,但它是指向Object而不是Object本身的指针。 从技术上讲,这意味着Class在程序的堆上分配,而Object在堆栈上分配。 换句话说,当您将变量声明为对象类型时,它将占用堆栈上与对象大小相同的空间,但是当您声明类类型的变量时,它将始终采用指针的大小在堆栈上。 实际的类数据将在堆上。

定义Pascal类

使用类型声明以与对象相同的方式声明类。 类声明的一般形式如下 -

type class-identifier = class  
   private
      field1 : field-type;  
      field2 : field-type;  
        ...
   public
      constructor create();
      procedure proc1;  
      function f1(): function-type;
end;  
var classvar : class-identifier;

值得注意的是以下要点 -

  • 类定义应仅在程序的类型声明部分下。

  • 使用class关键字定义class

  • 字段是存在于类的每个实例中的数据项。

  • 方法在类的定义中声明。

  • Root类中有一个名为Create的预定义构造函数。 每个抽象类和每个具体类都是Root的后代,因此所有类都至少有一个构造函数。

  • Root类中有一个名为Destroy的预定义析构函数。 每个抽象类和每个具体类都是Root的后代,因此,所有类都至少有一个析构函数。

让我们定义一个Rectangle类,它有两个整数类型数据成员 - 长度和宽度,一些成员函数用于操作这些数据成员和一个绘制矩形的过程。

type
   Rectangle = class
   private
      length, width: integer;
   public
      constructor create(l, w: integer);
      procedure setlength(l: integer);
      function getlength(): integer;
      procedure setwidth(w: integer);
      function getwidth(): integer;
      procedure draw;
end;

让我们编写一个完整的程序,创建一个矩形类的实例并绘制矩形。 这是我们在讨论Pascal对象时使用的相同示例。 您会发现这两个程序几乎相同,但以下情况除外 -

  • 您需要包含{$ mode objfpc}指令才能使用这些类。

  • 您需要包含{$ m +}指令以使用构造函数。

  • 类实例化与对象实例化不同。 只声明变量不会为实例创建空间,您将使用构造函数create来分配内存。

这是完整的例子 -

{$mode objfpc} // directive to be used for defining classes
{$m+}		   // directive to be used for using constructor
program exClass;
type
   Rectangle = class
   private
      length, width: integer;
   public
      constructor create(l, w: integer);
      procedure setlength(l: integer);
      function getlength(): integer;
      procedure setwidth(w: integer);
      function getwidth(): integer;
      procedure draw;
end;
var
   r1: Rectangle;
constructor Rectangle.create(l, w: integer);
begin
   length := l;
   width := w;
end;
procedure Rectangle.setlength(l: integer);
begin
   length := l;
end;
procedure Rectangle.setwidth(w: integer);
begin
   width :=w;
end;
function Rectangle.getlength(): integer;
begin
   getlength := length;
end;
function Rectangle.getwidth(): integer;
begin
   getwidth := width;
end;
procedure Rectangle.draw;
var
   i, j: integer;
begin
   for i:= 1 to length do
   begin
      for j:= 1 to width do
         write(' * ');
      writeln;
   end;
end;
begin
   r1:= Rectangle.create(3, 7);
   writeln(' Draw Rectangle: ', r1.getlength(), ' by ' , r1.getwidth());
   r1.draw;
   r1.setlength(4);
   r1.setwidth(6);
   writeln(' Draw Rectangle: ', r1.getlength(), ' by ' , r1.getwidth());
   r1.draw;
end.

编译并执行上述代码时,会产生以下结果 -

Draw Rectangle: 3 by 7
* * * * * * *
* * * * * * *
* * * * * * *
Draw Rectangle: 4 by 6
* * * * * * 
* * * * * * 
* * * * * * 
* * * * * * 

class成员的可见性

可见性表示class成员的可访问性。 Pascal类成员有五种可见性 -

Sr.No 可见性和可访问性
1

Public

这些成员始终可访问。

2

Private

只能在包含类定义的模块或单元中访问这些成员。 可以从类方法内部或从它们外部访问它们。

3

Strict Private

这些成员只能从类本身的方法中访问。 同一单元中的其他类或后代类无法访问它们。

4

Protected

这与private相同,除了这些成员可以访问后代类型,即使它们是在其他模块中实现的。

5

Published

这与Public相同,但如果编译器处于{$ M +}状态,编译器将生成这些类的自动流所需的类型信息。 已发布部分中定义的字段必须是类类型。

Pascal类的构造函数和析构函数

构造函数是特殊方法,只要创建对象,就会自动调用这些方法。 因此,我们通过构造函数初始化许多东西来充分利用这种行为。

Pascal提供了一个名为create()的特殊函数来定义构造函数。 您可以将任意数量的参数传递给构造函数。

下面的示例将为名为Books的类创建一个构造函数,它将在创建对象时初始化该书的价格和标题。

program classExample;
{$MODE OBJFPC} //directive to be used for creating classes
{$M+} //directive that allows class constructors and destructors
type
   Books = Class 
   private 
      title : String; 
      price: real;
   public
      constructor Create(t : String; p: real); //default constructor
      procedure setTitle(t : String); //sets title for a book
      function getTitle() : String; //retrieves title
      procedure setPrice(p : real); //sets price for a book
      function getPrice() : real; //retrieves price
      procedure Display(); // display details of a book
end;
var
   physics, chemistry, maths: Books;
//default constructor 
constructor Books.Create(t : String; p: real);
begin
   title := t;
   price := p;
end;
procedure Books.setTitle(t : String); //sets title for a book
begin
   title := t;
end;
function Books.getTitle() : String; //retrieves title
begin
   getTitle := title;
end;
procedure Books.setPrice(p : real); //sets price for a book
begin
   price := p;
end;
function Books.getPrice() : real; //retrieves price
begin
   getPrice:= price;
end;
procedure Books.Display();
begin
   writeln('Title: ', title);
   writeln('Price: ', price:5:2);
end;
begin 
   physics := Books.Create('Physics for High School', 10);
   chemistry := Books.Create('Advanced Chemistry', 15);
   maths := Books.Create('Algebra', 7);
   physics.Display;
   chemistry.Display;
   maths.Display;
end.

编译并执行上述代码时,会产生以下结果 -

Title: Physics for High School
Price: 10
Title: Advanced Chemistry
Price: 15
Title: Algebra
Price: 7

与名为create的隐式构造函数一样,还有一个隐式析构函数方法destroy,您可以使用它释放类中使用的所有资源。

继承 (Inheritance)

Pascal类定义可以选择从父类定义继承。 语法如下 -

type
childClas-identifier = class(baseClass-identifier) 
< members >
end; 

下面的示例提供了一个小说类,它继承了Books类并根据需求添加了更多功能。

program inheritanceExample;
{$MODE OBJFPC} //directive to be used for creating classes
{$M+} //directive that allows class constructors and destructors
type
   Books = Class 
   protected 
      title : String; 
      price: real;
   public
      constructor Create(t : String; p: real); //default constructor
      procedure setTitle(t : String); //sets title for a book
      function getTitle() : String; //retrieves title
      procedure setPrice(p : real); //sets price for a book
      function getPrice() : real; //retrieves price
      procedure Display(); virtual; // display details of a book
end;
(* Creating a derived class *)
type
   Novels = Class(Books)
   private
      author: String;
   public
      constructor Create(t: String); overload;
      constructor Create(a: String; t: String; p: real); overload;
      procedure setAuthor(a: String); // sets author for a book
      function getAuthor(): String; // retrieves author name
      procedure Display(); override;
end;
var
   n1, n2: Novels;
//default constructor 
constructor Books.Create(t : String; p: real);
begin
   title := t;
   price := p;
end;
procedure Books.setTitle(t : String); //sets title for a book
begin
   title := t;
end;
function Books.getTitle() : String; //retrieves title
begin
   getTitle := title;
end;
procedure Books.setPrice(p : real); //sets price for a book
begin
   price := p;
end;
function Books.getPrice() : real; //retrieves price
begin
   getPrice:= price;
end;
procedure Books.Display();
begin
   writeln('Title: ', title);
   writeln('Price: ', price);
end;
(* Now the derived class methods  *)
constructor Novels.Create(t: String);
begin
   inherited Create(t, 0.0);
   author:= ' ';
end;
constructor Novels.Create(a: String; t: String; p: real);
begin
   inherited Create(t, p);
   author:= a;
end;
procedure Novels.setAuthor(a : String); //sets author for a book
begin
   author := a;
end;
function Novels.getAuthor() : String; //retrieves author
begin
   getAuthor := author;
end;
procedure Novels.Display();
begin
   writeln('Title: ', title);
   writeln('Price: ', price:5:2);
   writeln('Author: ', author);
end;
begin 
   n1 := Novels.Create('Gone with the Wind');
   n2 := Novels.Create('Ayn Rand','Atlas Shrugged', 467.75);
   n1.setAuthor('Margaret Mitchell');
   n1.setPrice(375.99);
   n1.Display;
   n2.Display;
end.

编译并执行上述代码时,会产生以下结果 -

Title: Gone with the Wind
Price: 375.99
Author: Margaret Mitchell
Title: Atlas Shrugged
Price: 467.75
Author: Ayn Rand

值得注意的是以下要点 -

  • Books类的成员具有protected可见性。

  • Novels类有两个构造函数,因此overload运算符用于函数重载。

  • Books.Display过程已声明为virtual ,因此Novels类中的相同方法可以override它。

  • Novels.Create构造函数使用inherited关键字调用基类构造函数。

Interfaces

定义接口以向实现者提供通用功能名称。 不同的实现者可以根据他们的要求实现这些接口。 你可以说,接口是由开发人员实现的骨架。 以下是界面示例 -

type  
   Mail = Interface  
      Procedure SendMail;  
      Procedure GetMail;  
   end;  
   Report = Class(TInterfacedObject,  Mail)  
      Procedure SendMail;  
      Procedure GetMail;  
   end;  

请注意,当一个类实现一个接口时,它应该实现该接口的所有方法。 如果未实现接口的方法,则编译器将给出错误。

抽象类

抽象类是无法实例化的,只能继承的类。 通过在类定义中包含单词symbol abstract来指定抽象类,如下所示 -

type
   Shape = ABSTRACT CLASS (Root)
      Procedure draw; ABSTRACT;
      ...
   end;

从抽象类继承时,父类声明中标记为abstract的所有方法都必须由子类定义; 此外,必须使用相同的可见性定义这些方法。

静态关键字

将类成员或方法声明为静态使它们可以访问而无需实例化类。 声明为static的成员无法使用实例化的类对象访问(尽管静态方法可以)。 以下示例说明了这一概念 -

program StaticExample;
{$mode objfpc}
{$static on}
type
   myclass=class
      num : integer;static;
   end;
var
   n1, n2 : myclass;
begin
   n1:= myclass.create;
   n2:= myclass.create;
   n1.num := 12;
   writeln(n2.num);
   n2.num := 31;
   writeln(n1.num);
   writeln(myclass.num);
   myclass.num := myclass.num + 20;
   writeln(n1.num);
   writeln(n2.num);
end.

编译并执行上述代码时,会产生以下结果 -

12
31
31
51
51

您必须使用指令{$ static on}来使用静态成员。

↑回到顶部↑
WIKI教程 @2018