Delphi程序由多个unit模块组成,这些模块被一个单一的源文件——工程文件所联系,格式为.dpr;
.dpr的组成:程序头,[users 从句],主程序块;
编写的程序的名称,与.dpr文件名相同;
程序主文件中使用到的所有.pas文件的名称,就像java的import;
用begin,end包裹的代码段,工程文件中的全局标识符必须声明于begin之前;
程序的子模块称为一个单元,格式为.pas;
相当于类,包含单元名称,Interface关键字,implementation,[initialization],[finalization],关键字end;
举例:
unit Unitl;
interface
uses...
...
implementation
uses...
...
initialization
...
finalization
...
end.
一个.dpr不能引用两个名称相同的.pas;
implementation部分也可以定义常量,变量,例程等,但是只能在本单元内使用;
finalization相当于是finally块,程序退出时运行此部分的代码;
常见程序类型:命令行程序、窗体程序;
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.
标识符分为标准标识符和自定义标识符;
标准标识符包括:
1.标准常量及变量名称,如FALSE,TRUE等
2.标准类型名称,如Integer,Real等
3.标准例程名称,如Sin,IntToStr等
4.标准文件名称,如标准I/O名称Input,Output等
5.Delphi2010的保留字和指令符,如procedure,class等
自定义标识符需要满足以下条件:
1.Delphi语言不区分大小写,标识符亦然
2.自定义标识符不能与当前域中的其他标识符相同
3.长度小于255字符,超过部分将被舍弃
4.只能由英文字母,下划线和数字组成,不能包含空格,第一个字符不能是数字
单个符号
#$&'()*+,-./:;<=>@[]^{}
组合符号
(*
(.
*)
..
//
:=
<=
>=
<>
(.等效于[
.)等效于]
(*等效于{
*)等效于}
除此之外,%?\!"|~也不能用于标识符
局部标识符是指定义于例程(函数或者过程)中的标识符,此种标识符只能定义他们的例程;
除此之外都是全局标识符,全局标识符分为公有和私有标识符;
定义于.pas文件的Interface部分是公有,其他为私有;
公有标识符不但在本.pas文件中有效,在所有引用了本.pas文件的其他文件如.dpr文件中也有效;
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
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在定义一个类时,被视作保留字,在其他场合被视为指令符;
直接常量、声明常量、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,不能再指向其他变量;
变量分为静态变量和动态变量;
静态变量在定就确定所需的内存大小;
变量手动赋值前会由系统赋值;
全局变量初始化为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;
举例
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;
//...单行注释
{...}
(*...*)
注释嵌套必须嵌套其他类型注释,如;
{XXXXX=9,I=0(*参数传递*)}
{$APPTYPE CONSOLE}
解释:
当第一个字符是$
,而且是{}
或者(**)
包裹时,表示编译器提示符;
比如当前这句,表示当前程序是一个命令行程序;
表达式必须有一个返回值,Delphi的过程调用不返回任何值,故过程调用不属于表达式,同理;
i:=3; // 不属于表达式
i>=9; // 属于表达式
注:Delphi中,表达式不能单独存在,只能位于赋值符号:=
的右边;
包括赋值语句、例程调用、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;
包括复合语句,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);
function UpperCase(const S:string):string;
var
Ch:Char;
L:Integer;
Source, Dest:PChar;
begin
...
end;
以上是一个函数的声明,和四个变量的声明一起构成了块的声明部分;
注:块中声明的标识符具有局部性,如上面的四个变量都只能声明在它们的块中;
域指的是标识符的有效范围;
声明在块中的标识符只能用在这个块,成为局部标识符;
如果是变量则是局部变量,如果是常量则是局部常量;
声明在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可以是单元名,工程名,结构类型的变量名。
当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;
包括值转换和变量转换;
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.
文章浏览阅读5.4k次,点赞2次,收藏20次。ONVIF Discovery 协议介绍
文章浏览阅读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.方便,简化数据操作当我们业务需求要查出多张表的数据,这时我们可能会关联多张表查询处理.如..._哪种情况更适合建立视图
文章浏览阅读643次,点赞4次,收藏6次。Anaconda的安装及基本概念Anaconda中通过conda进行python包的管理Anaconda中通过conda进行虚拟环境的管理为形成良好的编程习惯,为每一个项目单独创建一个虚拟环境对开发来说至关重要。这一习惯即使对非数据data项目(如Web App)也能十分有效的帮助管理开发环境。_anaconda csdn
文章浏览阅读6.4k次。 软件缺陷的描述是是软件缺陷报告的基础部分,也是测试人员就一个软件问题与开发小组交流的最初且最好的机会。一个好的描述,需要使用简单的、准确的、专业的语言来抓住缺陷的本质。否则,它就会使信息含糊不清,可能会误导开发人员。准确报告软件缺陷是非常重要的,因为: 清晰准确的软件缺陷描述可以减少软件缺陷从开发人员返回的数量 提高软件缺陷修复的速度,使每一个小组能够有效的_描述缺陷发生的可能性的是
文章浏览阅读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
文章浏览阅读1k次。最近在做appStore时,涉及到一个第三方app下载视频后将车机存储撑爆的问题,从而影响到我们车机自带的app使用,问题很是严重,于是就需要提供缓存清理以及垃圾清理的功能,当用户使用第三方app时,存储空间达到一定量的时候会提示用户去清理,否则不允许使用第三方app。缓存获取获取各个应用程序的缓存大小,可以通过使用PackageManager.getPackageSizeInfo方法来获取,但是..._android packageinstaller缓存数据很大
文章浏览阅读1.8w次。vue给对象动态添加属性和值一、背景介绍:在vue中请求接口中,一个请求方法可能对应后台两个请求接口,所以请求参数就会有所不同。需要我们先设置共同的参数,然后根据条件动态添加参数属性。二、案例let that = this; let params = { "type":that.addQueTab..._vue3 键值对动态添加与获取
文章浏览阅读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
文章浏览阅读1.2k次。今天帮助哥们解决了一个比较蛋疼的问题,就是在有的情况下会出现设置activity的windowSoftInputMode="adjustResize"时,会失效的情况。历尽千辛万苦,终于在stackflow上找到解决方法。在activity的根布局上添加fitsSystemWindows="true".然后adjustResize就可以成功的起作用了。但是在这种情况下,你的titlebar会下移s..._adjustresize
文章浏览阅读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
文章浏览阅读1.8k次。微信商户通有这么一个需求,用户打开H5页面后,引导用户到电脑下载设计资源包,由于各种内部原因,被告知无后台资源支持,自己折腾了一段时间找了下面2个办法,简单做下笔记。使用mailto功能,让用户自己给自己发送一份包含资源包的下载链接 调用QQ邮件分享功能,让用户自己给自己发送一份包含资源包的下载链接mailto使用方法1、基础写法当浏览者点击这个链接时,浏览器会自动调用默认的客户端电子邮件程序,并在收件人框中自动填上收件人的地址下面<a href="mailto:xxx@fo_前端静态网页无需后台发送邮件留言的方式