Pascal是一种结构化编程语言,而Free Pascal作为其现代编译器,不仅支持跨多种操作系统和处理器架构,还提供了高效的内存使用和函数重载等先进功能。Free Pascal继承了Pascal语言的核心特性,同时进行了扩展和优化,使其成为教育、学术和多领域应用开发的理想工具,展示了Pascal语言的持久影响力和Free Pascal的现代化改进。
定义变量
在Free Pascal中,变量的声明可以有多种形式,每种形式都有其特定的用途和含义,需要注意的是汇编名称必须唯一,不能声明或导出两个具有相同汇编名称的变量。特别是,不要尝试导出以FPC_
开头的公共名称的变量,因为这是编译器用于某些内部系统例程的名称:
var
// 定义并初始化整数变量
myInteger: integer = 10;
// 定义并初始化实型变量
myReal: real = 3.14;
// 定义并初始化布尔型变量
myBoolean: boolean = true;
// 定义并初始化字符型变量
myChar: char = 'A';
// 定义并初始化字符串型变量
myString: string = 'Hello, World!';
begin
writeln('Integer: ', myInteger);
writeln('Real: ', myReal);
writeln('Boolean: ', myBoolean);
writeln('Char: ', myChar);
writeln('String: ', myString);
end.
数据类型
在Free Pascal中,数据类型主要分为基本类型、字符类型、结构化类型、指针类型、过程类型、泛型类型和专用类型:
-
基本类型:
- 序数类型:包括整数类型(如
integer
,longint
,shortint
,byte
等)、布尔类型(boolean
)以及枚举类型(enumeration
)。这些类型都是可计数的、有序的。 - 实数类型:Free Pascal支持IEEE浮点类型,主要使用的是
real
类型,它可以根据处理器的能力表示为single
或double
精度。
- 序数类型:包括整数类型(如
-
字符类型:
char
:表示单个字符,通常占用一个字节。string
:表示字符串,即字符的序列。
-
结构化类型:这些类型允许用户定义更复杂的数据结构,如记录(
record
)、集合(set
)等。 -
指针类型:指针类型用于存储内存地址,指向其他类型的数据。
-
过程类型:表示指向过程或函数的指针,可用于回调或动态调用。
-
泛型类型和专用类型:这些类型提供了更高级的类型构造能力,允许用户定义可重用和灵活的数据结构。
此外,Free Pascal还支持类型别名(type alias
),允许用户为现有类型定义新的名称。
以下是常用类型的使用实例:
{ 文件名是: hello.pas }
Const
e = 2.7182818; { 实数类型常量。}
a = 2; { 序数(整数)类型常量。}
c = '4'; { 字符类型常量。}
s = '这是一个常量字符串'; { 字符串类型常量。}
sc = chr(32);
Var
ls: Longint;
P: Pointer;
Ss: set of 0..10; { 假设集合的范围是 0 到 10 }
i: Integer; { 声明循环计数器变量 }
begin
ls := SizeOf(Longint);
P := nil;
Ss := [1, 2];
writeln('浮点数:', e);
writeln('整数:', a);
writeln('字符:', c);
writeln('字符串:', s);
writeln('空格字符:', sc);
writeln('Longint类型大小:', ls);
{ 打印指针是否为nil或者其指向的内存地址 }
if P = nil then
writeln('指针P是nil')
else
writeln('指针P不是nil');
{ 遍历集合元素并打印 }
writeln('集合Ss的元素:');
for i := 0 to 10 do
if i in Ss then
writeln(i);
end.
编译Pascal文件
fpc hello.pas
运行编译好的可运行文件
./hello
循环语句
for...to...do循环
在Free Pascal中,For
循环是一种非常常用的控制结构,它允许我们重复执行一段代码直到满足某个条件。For
循环使用一个控制变量,该变量在循环开始时被初始化,并在每次循环迭代后递增或递减,直到达到一个终止条件。
var
i: Integer;
begin
for i := 1 to 10 do
begin
WriteLn('当前数值是: ', i);
end;
end.
while...do循环
var
i: Integer;
begin
i := 1;
while i <= 10 do
begin
WriteLn('当前数值是: ', i);
i := i + 1;
end;
end.
repeat...until循环
在 Free Pascal 中,repeat...until
语句用于创建一个循环,该循环会一直执行,直到指定的表达式结果为真。由于表达式的评估是在语句执行之后进行的,因此循环体内的语句至少会执行一次,请注意,布尔表达式会默认进行短路评估,这意味着一旦结果确定,评估就会停止。
var
i: Integer;
begin
i := 1;
repeat
WriteLn('当前数值是: ', i);
i := i + 1;
until i > 10;
end.
case语句
在 Pascal 语言中,case
语句用于根据表达式的值来选择执行不同的代码块。case
语句中的表达式和常量必须在编译时是已知的,它们可以是枚举类型、序数类型(包括字符)或字符串类型。所有的 case
常量必须是同一类型。
编译器会评估 case
表达式。如果表达式的值与某个 case
常量匹配,那么会执行该常量后面的语句。执行完毕后,程序会继续执行 case
语句块之后的代码。
如果没有任何 case
常量与表达式的值匹配,那么会执行 else
或 otherwise
关键字后面的语句列表。这个列表可以为空。如果没有 else
部分,且没有 case
常量与表达式的值匹配,程序会在 case
语句块之后继续执行。
在 Free Pascal 中,与 Turbo Pascal 不同的是,不允许重复的 case
标签。此外,Free Pascal 还允许使用字符串作为 case
标签,此时 case
变量也必须是字符串类型,并且字符串比较是区分大小写的。
program Case;
var
C: char;
Number: integer;
OS: string;
begin
// 使用字符作为 case 标签
C := 'c';
case C of
'a': WriteLn('A pressed');
'b': WriteLn('B pressed');
'c': WriteLn('C pressed');
else
WriteLn('Unknown letter pressed: ', C);
end;
// 使用多个字符和 else 语句
C := 'd';
case C of
'a', 'e', 'i', 'o', 'u': WriteLn('Vowel pressed');
'y': WriteLn('This one depends on the language');
else
WriteLn('Consonant pressed');
end;
// 使用数字范围和 else 语句包含多个指令
Number := 105;
case Number of
1..10: WriteLn('Small number');
11..100: WriteLn('Normal, medium number');
else
WriteLn('HUGE number');
WriteLn('How did we get this much?');
end;
// 使用字符串作为 case 标签
OS := 'Linux';
case lowercase(OS) of
'windows', 'dos': WriteLn('Microsoft platform');
'macos', 'darwin': WriteLn('Apple platform');
'linux', 'freebsd', 'netbsd': WriteLn('Community platform');
else
WriteLn('Other platform');
end;
end.
运行效果:
if...than...else条件判断语句
在Free Pascal中,if...then...else
语句用于根据条件执行不同的代码块。if
和then
关键字之间的表达式必须返回布尔值(即真或假)。如果表达式的结果为True
,则执行then
关键字后面的语句。如果表达式的结果为False
,则执行else
关键字后面的语句(如果存在)。
请注意以下几点:
- 布尔表达式默认会进行短路评估,这意味着评估将在结果确定时停止。
- 在
else
关键字之前,不允许使用分号(;),但所有的语句都可以是复合语句。 - 在嵌套的
if...then...else
结构中,可能会出现歧义,即哪个else
语句与哪个if
语句配对。规则是,else
关键字与第一个尚未与else
配对的if
关键字匹配(向后搜索)。
为了避免歧义,当需要嵌套if...then...else
语句时,最好使用begin
和end
关键字来明确界定代码块。
var
score: Integer;
evaluation: string;
begin
Write('请输入学生的分数: ');
ReadLn(score);
if score >= 90 then
evaluation := '优秀'
else if score >= 80 then
evaluation := '良好'
else if score >= 70 then
evaluation := '中等'
else if score >= 60 then
evaluation := '及格'
else
evaluation := '不及格';
WriteLn('学生的评价是: ', evaluation);
ReadLn; // 等待用户输入,防止程序立即退出
end.
运行结果:
with语句简化字段和方法的访问
在Free Pascal中,with
语句允许我们更方便地访问记录(record)、对象或类的字段和方法。使用with
语句时,编译器会检查其中的变量引用或方法引用是否是该记录、对象或类的字段或方法。如果是,则直接访问该字段或调用该方法
Type
Passenger = Record
Name: String[30];
Flight: String[10];
end;
Var
TheCustomer: Passenger;
begin
// 初始化乘客信息
TheCustomer.Name := 'Unknown';
TheCustomer.Flight := 'XXXX';
// 使用with语句更新乘客信息
With TheCustomer do
begin
Name := 'GGBond';
Flight := 'PS901';
end;
// 输出更新后的乘客信息
WriteLn('Passenger Name: ', TheCustomer.Name);
WriteLn('Flight Number: ', TheCustomer.Flight);
ReadLn; // 防止程序立即退出
end.
运算符
算数运算符
运算符 | 操作 |
+ | 加法 |
- | 减法 |
* | 乘法 |
** | 幂运算 |
/ | 除法 |
Div | 整除 |
Mod | 取余 |
赋值运算符 :=
赋值运算符定义将一种类型的变量赋值到另一种变量的操作。这 结果类型必须与赋值语句左侧的变量类型匹配,即单个 赋值运算符的参数必须与右侧的表达式类型相同 赋值运算符,此系统可用于声明新类型,并为该类型定义赋值。
在Free Pascal中,赋值运算符(:=
)不仅用于基本的变量赋值,还可以重载以支持自定义类型的赋值操作。通过重载赋值运算符,我们可以定义如何将一个类型的值赋给另一个类型的变量。这种特性在处理复杂数据类型,如记录(record)或自定义类时特别有用。
type
Complex = record
re, im: real;
end;
// 重载赋值运算符,以支持将实数赋给复数
operator := (r: real) z: Complex;
begin
z.re := r;
z.im := 0.0;
end;
var
R: real;
C: Complex;
begin
R := 3.14;
C := R; // 这里使用了重载的赋值运算符
writeln('复数 C 的实部: ', C.re, ' 虚部: ', C.im);
readln;
end.
逻辑运算符
运算符 | 操作 |
not | 按位求反(一元) |
and | 按位与 |
or | 按位或 |
xor | 按位异或 |
shl | 向左按位移位 |
shr | 向右按位移位 |
<< | 向左按位移位(与shl相同) |
>> | 按位向右移位(与shr相同) |
集合运算符
运算符 | 操作 |
+ | 并集 |
- | 差集 |
* | 交集 |
>< | 对称差集 |
<= | 包含 |
>= | 左侧集合是右侧集合的超集 |
include | 在集合中包含一个元素 |
exclude | 从集合中排除一个元素 |
in | 检查一个元素是否在集合中 |