Delphi语法(一)工程文件与语法基础_delphi 工程文件-程序员宅基地

技术标签: delphi  开发语言  

第一章 工程文件介绍

1.1 工程文件 .dpr

Delphi程序由多个unit模块组成,这些模块被一个单一的源文件——工程文件所联系,格式为.dpr;

.dpr的组成:程序头,[users 从句],主程序块;

  • 程序头

编写的程序的名称,与.dpr文件名相同;

  • uses从句

程序主文件中使用到的所有.pas文件的名称,就像java的import;

  • 主程序块

用begin,end包裹的代码段,工程文件中的全局标识符必须声明于begin之前;

1.2 子模块 .pas

程序的子模块称为一个单元,格式为.pas;

相当于类,包含单元名称,Interface关键字,implementation,[initialization],[finalization],关键字end;
举例:

unit Unitl;
interface
 uses...
...
implementation
 uses...
...
initialization
...
finalization
...
end.

一个.dpr不能引用两个名称相同的.pas;

implementation部分也可以定义常量,变量,例程等,但是只能在本单元内使用;

finalization相当于是finally块,程序退出时运行此部分的代码;

1.3 常见程序类型

常见程序类型:命令行程序、窗体程序;

命令行程序
program Project1;
{$APPTYPE CONSOLE}
uses
 SysUtils;
var
 x,y:integer;
begin
 x:=9;
 y:=7;
 writeln(x+y);
 readln;
end.

注:readln用于使屏幕暂停,按回车键可以结束暂停;

窗体程序

在Delphi中,窗体程序可以通过直接拖动组件组成窗体,然后再手动调整生成的程序内容,比较便捷;

下面是Unit1.pas文件的代码;

unit Unit1;
interface
uses
 Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,Dialogs;
type
 TForm1 = class(TForm)
 private
 {Private declarations}
 public
 {Public declarations}
 end;

var
 Form1:TForm1;
implementation
{$R *.dfm}
end.
源文件.dpr的代码如下
program Project1;
uses
 Forms,
 Unit1 in 'Unit1.pas'{Form1};
{$R *.res}
begin
 Application.Initialize;
 Application.MainFormOnTaskbar := True;
 Application.CreateForm(TForm1, Form1);
 Application.Run;
end.

第二章 语法基础

2.1标识符

标识符分为标准标识符和自定义标识符;

标准标识符包括:

1.标准常量及变量名称,如FALSE,TRUE等

2.标准类型名称,如Integer,Real等

3.标准例程名称,如Sin,IntToStr等

4.标准文件名称,如标准I/O名称Input,Output等

5.Delphi2010的保留字和指令符,如procedure,class等

自定义标识符需要满足以下条件:

1.Delphi语言不区分大小写,标识符亦然

2.自定义标识符不能与当前域中的其他标识符相同

3.长度小于255字符,超过部分将被舍弃

4.只能由英文字母,下划线和数字组成,不能包含空格,第一个字符不能是数字

2.2特殊符号
单个符号
#$&'()*+,-./:;<=>@[]^{}

组合符号
(* 
(. 
*) 
.. 
// 
:= 
<= 
>= 
<>

(.等效于[
.)等效于]
(*等效于{
*)等效于}

除此之外,%?\!"|~也不能用于标识符

2.3标识符的作用域

局部标识符是指定义于例程(函数或者过程)中的标识符,此种标识符只能定义他们的例程;

除此之外都是全局标识符,全局标识符分为公有和私有标识符;

定义于.pas文件的Interface部分是公有,其他为私有;

公有标识符不但在本.pas文件中有效,在所有引用了本.pas文件的其他文件如.dpr文件中也有效;

2.4保留字
and,else,inline,property,try,

array,end,interface,raise,type,

as,except,is,record,unit,

at,exports,label,remove,until,

asm,file,library,repeat,uses,

begin,finalization,mod,resourcestring,var,

case,finally,nil,set,while,

class,for,not,shl,with,

const,function,on,shr,xor,

constructor,goto,of,strict private,

destructor,if,or,strict protected,

dispinterface,implementation,out,string,

div,in,packed,then,

do,inherited,procedure,threadvar,

downto,initialization,program,to
2.5指令符
absolute,dispid,helper,near,private,reintroduce,stored,
abstract,dynamic,implements,nodefault,protected,requires,unsafe,
assembler,experimental,index,operator,public,resident,varargs,
automated,export,inline,overload,published,safecall,virtual,
cdecl,external,library,override,read,sealed,winapi,
contains,far,local,package,readonly,static,write,
default,final,message,pascal,reference,stdcall,writeonly,
deprecated,forward,Name,platform,register,strict,delayed

注:private,protected,public,published,automated在定义一个类时,被视作保留字,在其他场合被视为指令符;

2.6常量

直接常量、声明常量、Delphi本身预定义的常量;

直接常量:

整型常量、实型常量(即浮点数、小数)、字符及字符串型常量、布尔型常量;

符号常量
Const
    CONS_A = 123;
    CONS_B = CONS_A+234;
    CONS_C = CONS_A+CONS_B+89;

编译器在编译时根据值的类型推测常量的类型,如果

CONS_B=CONS_A+'delphi';

将编译错误,字符串型常量与数值型常量不能相加;

资源字符串
resourcestring
    str='The Current Edition is Delphi2010';

这种方式声明的字符串用于程序中时将被编译到资源文件中,这样的好处是可以任意修改字符串而不需要重载编译程序;

类型常量
Const
    <标识符1>:<类型1>=<常量值1>;

不能将常量声明为文件类型和变体类型;

类型常量的常量值中不能含有其他常量;

Const
    Name:string='delphi2010';
    Caption:string='my'+name;//不合法,name是另一个常量,不能在表达式中
    MultiPi:real=2*3.14;
数组常量

数组常量主要有三种:静态数组、字符串、多维数组;

记录常量
type
  TPoint = record
     X,Y:Single;
  end;
  TRec = record
     x:integer;
  case tag:integer of
     1:(i:integer);
     2:(n:integer);
  end;
const
   Origin:TPoint=(X:0.0;Y:0.0);
   VRec:TRec=(x:7;tag:1;i:2;);

注:

记录常量不能含有任何形式的文件变量;

各个字段的赋值顺序必须与声明时的顺序一致;

对于变体记录,如果其中出现了一个tag值,则必须赋值;

只有含有tag值时变体记录中的变体部分才能被赋值。

指针常量举例
var
   i,n:integer;
const
   pi:^integer = @i;

i的值可以随时改变,但是指针pi只能指向i,不能再指向其他变量;

2.7变量

变量分为静态变量和动态变量;

静态变量在定就确定所需的内存大小;

变量手动赋值前会由系统赋值;

全局变量初始化为0,如果是指针就初始化为nil;如果是字符串初始化为空字符串;

局部变量系统会随机赋值,这种赋值非常不可靠,所以局部变量一定要手动赋值后才能使用。

全局变量手动初始化举例

Var
    GlobalVar:integer=100;

共址变量举例

var
    c:AnsiChar;
    i:Byte absolute c;
begin
    c:='A';
    writeln(i);//屏幕显示65
    readln;
end.

i被声明为变量c的共址变量,这样i与c在内存中的起始位置相同;

i在内存中占用一个字节,当读取i时,系统将c的第一个字节当成i的值,故为65;

注:

1.共址变量具有相互性,如下所示,结果不变;

var
    i:Byte;
    c:AnsiChar ansolute i;//显示为65

2.可以声明多个变量为共址变量;

var
    i:Byte;
    c:AnsiChar absolute i;
    str: ShortString absolute i;
2.8类型声明

举例

type
   aSet = set of char;
   myInteger = Integer;

除此之外,还有一种声明方式

type
    myInteger = type Integer;

1.当类型表达式是另一个类型的名称,比如Integer;

如果说第一种声明是相当于一个人的名字,myInteger与Integer都是一个人的名字;

第二种声明就是两个人的名字,只不过这两个人各个方面除了名字都完全相同;

一般情况下不会被注意到,但是牵涉到数据类型的动态判断等比较高级的用法时,这种差别会导致类型不兼容;

2.当类型表达式是一个结构,如set of char;

type
    aSet = set of Char;
    bSet = set of Char;

从表面上看,aSet与bSet应当完全一致,然而并非如此,以上相当于;

type
    aSet = type bSet;

    bSet = type aSet;

如果要完全相同,则;

type
    aSet = set of Char;
    bSet = aSet;
2.9注释
//...单行注释

{...}

(*...*)

注释嵌套必须嵌套其他类型注释,如;

{XXXXX=9,I=0(*参数传递*)}
{$APPTYPE CONSOLE}

解释:

当第一个字符是$,而且是{}或者(**)包裹时,表示编译器提示符;

比如当前这句,表示当前程序是一个命令行程序;

2.10表达式

表达式必须有一个返回值,Delphi的过程调用不返回任何值,故过程调用不属于表达式,同理;

i:=3; // 不属于表达式

i>=9; // 属于表达式

注:Delphi中,表达式不能单独存在,只能位于赋值符号:=的右边;

2.11语句
2.11.1简单语句

包括赋值语句、例程调用、goto语句;

例程调用举例

对于不接受参数的过程和函数,在调用时可以省略例程名后的括号,如;

procedure M1;
...
   M1;
   ...

对于函数,调用时,可以将其返回值赋给一个变量,也可以单独调用;

 procedure M1:integer;
 ...
 var
    i:integer
 ...
    i:=M1;
    M1;
 ...

goto语句举例

 var
    i:integer;
 label 1, 2;
 begin
 1:writeln('请输入i的值:');
    readln(i);
    if i <> 0 then
       goto 1;
    exit;
 end.

输入数字i,如果i为0,自动退出,如果不为0,再次输入i;

2.11.2结构语句

包括复合语句,with语句,条件语句,循环语句等;

复合语句举例

 begin
    Z:=X;
    X:=Y;//可以省略分号X:=Y
 end;

汇编语句举例

使用asm和end包裹;

 var
    a:word;
 begin
    asm
       mov ax,43;
       add ax,54;
       mov a, ax;
    end;
    writeln(a);
    readln;
 end.

With语句举例

定义一个日期;

 type
    TDate = record
       Day:Integer;
       Month:Integer;
       Year:Integer;
    end;
 var
    OrderDate:TDate;

可以通过如下方式访问其中的字段;

 if OrderDate.Month = 12 then
 begin
    OrderDate.Month = 1;
    OrderDate.Year := OrderDate.Year+1;
 end
 else
    OrderDate.Month := OrderDate.Month+1;

但是如果运用with语句,可以简化为;

with OrderDate do
   if Month=12 then
      begin
         Month := 1;
         Year := Year+1;
   end
   else
Month := Month+1;

注:with的声明方式为;

with obj do 语句
with obj1, obj2 do 语句

注:对于with语句中出现的所有单独的标识符,编译器优先在obj中寻找其含义,即;

type
   TRec = record;
      x,y:integer;
   end;
var
   obj:TRec;
   x:integer;
begin
   with obj do
   begin
      x:=3;
   end;
   writeln(obj.x);
end.

这里的赋值是赋给了obj的x,如果想赋值给全局变量x,则;

project1.x := 3;

注:嵌套的with语句,with obj1,obj2,obj3...do...相当于;

with obj1 do
   with obj2
      ...
      with objn do
      ...

编译器会从最内层的objn开始寻找标识符,如果没找到,则在外面一层找,以此类推,直到obj1,如果还没找到,会在with语句之外寻找;

如:

type
   TInner = record
      x,y:Integer;
   end;
   TRec = record;
      x,y:integer;
      z:string;
   end;
var
   Rec:TRec;
   Inner:TInner;
   x:integer;
   z:string;
begin
   with rec, inner do
   begin
      x:=3;
      z:='delphi';
   end;
   writeln(Inner.x);
   writeln(rec.z);
2.12块和域
function UpperCase(const S:string):string;
var
   Ch:Char;
   L:Integer;
   Source, Dest:PChar;
begin
   ...
end;

以上是一个函数的声明,和四个变量的声明一起构成了块的声明部分;

注:块中声明的标识符具有局部性,如上面的四个变量都只能声明在它们的块中;

域Scope

域指的是标识符的有效范围;

声明在块中的标识符只能用在这个块,成为局部标识符;

如果是变量则是局部变量,如果是常量则是局部常量;

声明在interface部分的标识符的有效域是任何一个引用这个单元的源文件,成为全局标识符;

当一个块包含了另一个块,内部块的标识符将掩盖外部块的标识符,如:

function M1:integer;
var
   s:string;
   function M2:integer;
   var
      s:string;
   begin
      s:='delphi';
   end;
begin
end;

这里被赋值的是M2的s;

注:

uses从句中的第一个单元为最外层,但是system和sysinit单元永远是最外层;

最内层的单元并不是uses从句中最后出现的单元,而是正在使用这个标识符的单元才是最里层的单元;

多个单元在interface部分声明了同一标识符,则任何一个未限定的标识符都会被认为是最里层的标识符,

限定即Modle.Fun,表示目前引用的是Modle中的Fun,Modle可以是单元名,工程名,结构类型的变量名。

2.13兼容
类型兼容条件

当A、B两种数据类型满足以下条件时,可以将B类型的值赋给A类型的变量,这种情况成为类型兼容。

1.都是实数类型;

2.都是整数类型;

3.B是A的子界类型,如A是Integer,B是Byte;

4.同种类型的子界类型,如byte和smallint都是integer的子界类型,所以byte可以赋给smallint,反之亦可;

这种情况要注意B的值不能超出A的表示范围,否则可能会编译错误或数据丢失。

5.都是集合类型,并且基础类型兼容,如;

var
   s1:set of byte;
   s2:set of byte;

6.A是字符串类型,B是字符串、packed-string、Char类型;

7.A是Variant,B是整数、实数、字符串、字符、布尔类型,反之亦可;

8.都是类、类引用或接口类型,并且B继承A;

9.A是PChar或者PWideChar,B是0下标开始的字符数组;

array[0..n] of Char

10.A是Pointer(无类型指针),B是任意类型指针;

11.两个是同一种类型的指针,并且开启了编译器指示字{$T+};

12.两个都是过程类型,有相同的返回类型,并且参数的个数、位置和类型都相同;

赋值兼容条件

T1是一个变量,T2是一个表达式,若T2的值在T1的取值范围内,则如果以下条件至少一个成立,T2可以赋给T1;

1.T1和T2是同一种类型,并且不是文件类型或者包含文件类型的结构类型;

2.T1和T2是兼容的有序类型;

3.都是实数类型;

4.T1 是实数类型,T2是整数类型;

5.T1是PChar类型或者任何字符串类型,T2是字符串常量;

6.都是字符串类型;

7.T1是字符串类型,T2是字符或packed-string类型;

8.T1是一个长串类型,T2是一个PChar类型;

9.是兼容的packed-string类型;

10.是兼容的集合类型;

11.是兼容的指针类型;

12.都是类、类引用或接口,并且T2继承T1;

13.T1是接口,T2是实现T1的一个;

14.T1是PChar或PWideChar,T2是一个0下标开始的字符数组;

15.兼容的过程类型;

16.T1是Variant类型,T2是整数、实数、字符串、字符、布尔或接口类型;

17.T1是整数、实数、字符串、字符或布尔类型,T2是Variant;

18.T1是IUnknown或IDispatch接口类型,T2是Variant;

如果T1是IUnknown,T2类型编码必须是varEmpty、varUnknown或varDispatch;

如果T1是Idispatch,T2 的编码类型必须是varEmpty或者varDispatch;

2.14类型转换

包括值转换和变量转换;

值转换
Integer('A')
Char(65)

var
   ch:AnsiChar;
   ...
   ch:=AnsiChar(320);
   ...

这里,AnsiChar类型的值域中只有256个值(最大序数255),320超出,这时候编译器可以报错,也可以截取;

一般的截取直接取最大值255,这里的截取不一样;

首先将320除以255得到余数64,然后将64和值域中的最小值0相加,所得结果即目标值;

注:

无论是直接截取还是反绕,都不会改变赋值的符号,一个负数得到的结果一定是负数,只是绝对值不一定相同;

变量转换
var
   ch:AnsiChar;
   i:Integer;
   b:Byte;
begin
   ch:=AnsiChar(321);
   i:=320;
   b:=Byte(i);
   writeln(integer(ch));
   writeln(b);
   readln;
end.

变量转换第一规则:目标类型占用的内存永远不要小于源类型,否则编译器会进行反绕或截断。

注:

实数的类型转换较为特殊,所有类型的实数在转换到其他类型的值时,首先被转换为实数中的extended类型,然后再转成其他类型,

而extended类型过大,大部分变量无法容纳这种类型,所以将实数转换成其他类型时应当使用Delphi提供的例程。

如Int、Round、Trunc,均定义于system单元中,

Int返回一个实数的整数部分,是实数的形式,

Round返回与指定实数最接近的整数,

Trunc返回一个实数的整数部分,是整数的形式。

举例

var
   r:real;
begin
   r:=3.84;
   writeln(Int(r));
   writeln(Round(r));
   writeln(Trunc(r));
   readln;
end.
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ForAnnuus/article/details/130217189

智能推荐

ONVIF协议--ONVIF WS-Discovery (设备发现协议)-程序员宅基地

文章浏览阅读5.4k次,点赞2次,收藏20次。ONVIF Discovery 协议介绍

HDOJ1172解题报告【暴力】-程序员宅基地

文章浏览阅读54次。题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1172题目概述:  对于每组数据,先给出一个n,然后n行每行一个四位数,然后两个数b,c表示与答案有b个数相同,c个数在同一位置上,对于所有的n个给出的四位数,如果推出的答案唯一则输出,否则输出“Not sure”(不含引号)大致思路:  首先我想的是用搜索。穷极一生之力写了100+行的...

数据库视图作用?什么时候用视图?_哪种情况更适合建立视图-程序员宅基地

文章浏览阅读2w次,点赞6次,收藏37次。刚工作时候第一次看到接触到视图,感觉很不能理解,我当时就在想为什么要用视图呢?明明可以关联表查出来数据的,为什么又单独创建一个视图查询数据呢?工作久了我有以下几点心得分享给大家.1.安全性 因为视图是虚拟的,物理上是不存在的,只是存储了数据的集合,视图中数据是根据基表的更新而更新,用户不可以更改/删除视图。2.方便,简化数据操作当我们业务需求要查出多张表的数据,这时我们可能会关联多张表查询处理.如..._哪种情况更适合建立视图

Anaconda介绍及常用命令总结_anaconda csdn-程序员宅基地

文章浏览阅读643次,点赞4次,收藏6次。Anaconda的安装及基本概念Anaconda中通过conda进行python包的管理Anaconda中通过conda进行虚拟环境的管理为形成良好的编程习惯,为每一个项目单独创建一个虚拟环境对开发来说至关重要。这一习惯即使对非数据data项目(如Web App)也能十分有效的帮助管理开发环境。_anaconda csdn

第25回 准确报告软件缺陷_描述缺陷发生的可能性的是-程序员宅基地

文章浏览阅读6.4k次。 软件缺陷的描述是是软件缺陷报告的基础部分,也是测试人员就一个软件问题与开发小组交流的最初且最好的机会。一个好的描述,需要使用简单的、准确的、专业的语言来抓住缺陷的本质。否则,它就会使信息含糊不清,可能会误导开发人员。准确报告软件缺陷是非常重要的,因为: 清晰准确的软件缺陷描述可以减少软件缺陷从开发人员返回的数量 提高软件缺陷修复的速度,使每一个小组能够有效的_描述缺陷发生的可能性的是

signature=77a5bffa142f96901b9bf201769a775d,tibot/yarn.lock at 79fb61111b881d3a2fc858eadda5bf250a2475...-程序员宅基地

文章浏览阅读6.6k次。# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.# yarn lockfile v1accepts@~1.3.5, accepts@~1.3.7:version "1.3.7"resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc..._hsck735.cc

随便推点

android 清楚app缓存数据,android 获取其他应用程序的缓存大小以及清理应用缓存...-程序员宅基地

文章浏览阅读1k次。最近在做appStore时,涉及到一个第三方app下载视频后将车机存储撑爆的问题,从而影响到我们车机自带的app使用,问题很是严重,于是就需要提供缓存清理以及垃圾清理的功能,当用户使用第三方app时,存储空间达到一定量的时候会提示用户去清理,否则不允许使用第三方app。缓存获取获取各个应用程序的缓存大小,可以通过使用PackageManager.getPackageSizeInfo方法来获取,但是..._android packageinstaller缓存数据很大

vue给对象动态添加属性和值_vue3 键值对动态添加与获取-程序员宅基地

文章浏览阅读1.8w次。vue给对象动态添加属性和值一、背景介绍:在vue中请求接口中,一个请求方法可能对应后台两个请求接口,所以请求参数就会有所不同。需要我们先设置共同的参数,然后根据条件动态添加参数属性。二、案例let that = this; let params = { "type":that.addQueTab..._vue3 键值对动态添加与获取

解决keil:error C132: : not in formal parameter list等等突然出现很多很多报错_main.c(34): error c132: 'lcd1602_busycheck': not i-程序员宅基地

文章浏览阅读3.1w次,点赞55次,收藏16次。http://www.51hei.com/bbs/dpj-25003-1.html这里参考了这个帖子,在我身上发生的问题就是我在声明一个函数的时候忘记加分号了,会报错特别多奇奇怪怪的东西,吓死我了。解决办法就是加上分号就好了..._main.c(34): error c132: 'lcd1602_busycheck': not in formal parameter list

android adjustresize 设置大小,Android中adjustResize失效的解决办法之一-程序员宅基地

文章浏览阅读1.2k次。今天帮助哥们解决了一个比较蛋疼的问题,就是在有的情况下会出现设置activity的windowSoftInputMode="adjustResize"时,会失效的情况。历尽千辛万苦,终于在stackflow上找到解决方法。在activity的根布局上添加fitsSystemWindows="true".然后adjustResize就可以成功的起作用了。但是在这种情况下,你的titlebar会下移s..._adjustresize

消息自定义_c++ lersult-程序员宅基地

文章浏览阅读139次。// 消息自定义// 1、#defien WM_MSG WM_USER// 2、.h文件中添加事件: afx_msg LERSULT OnFun(WPARAM wparam, LPARAM lparam);// 3、宏定义消息路由: ON_MESSAGE(WM_MSG, OnFun)_c++ lersult

【原】移动web页面给用户发送邮件的方法 (邮件含文本、图片、链接)_前端静态网页无需后台发送邮件留言的方式-程序员宅基地

文章浏览阅读1.8k次。微信商户通有这么一个需求,用户打开H5页面后,引导用户到电脑下载设计资源包,由于各种内部原因,被告知无后台资源支持,自己折腾了一段时间找了下面2个办法,简单做下笔记。使用mailto功能,让用户自己给自己发送一份包含资源包的下载链接 调用QQ邮件分享功能,让用户自己给自己发送一份包含资源包的下载链接mailto使用方法1、基础写法当浏览者点击这个链接时,浏览器会自动调用默认的客户端电子邮件程序,并在收件人框中自动填上收件人的地址下面<a href="mailto:xxx@fo_前端静态网页无需后台发送邮件留言的方式