Delphi 是以 Object Pascal 語言為基礎的可視化開發工具,雖然兩者之間有著很大區別,但是要學好 Delphi,首先要掌握的就是 Object Pascal 語言。
?Object Pascal語言編寫環境
如何使用Delphi編寫Object Pascal 程序。一般來說,使用 Delphi 開發出來的程序有以下 3 種。
1.圖形界面程序
圖形界面程序是目前Windows 平臺最常見的應用程序,這些程序通過窗體和對話框與用戶進行信息交互,實現一定的功能。例如Microsoft 公司的Office 系列軟件和正在使用的Delphi 等,它們都是圖形界面程序。
2.控制臺程序
控制臺程序是指一些沒有圖形用戶界面的32 位Windows應用程序,類似在DOS 環境下運行的程序。這些程序很少要求用戶輸入大量的信息,一般只實現特定的功能。控制臺程序的代碼較小,占用的系統資源少,因此編譯、鏈接的速度比較快。
3.服務器程序
服務器程序可以接受和處理客戶應用程序的請求,并將結果信息返回給客戶應用程序。服務器應用程序一般在后臺運行,不需要大量的人機交互信息。
下面以開發一個簡單的控制臺程序為例,向讀者介紹Delphi 中生成Object Pascal 程序的基本方法,并對Object Pascal 程序的一般結構進行簡單說明。
在Delphi集成開發環境中,依次選擇“File”? “New”?“Other”菜單項打開“New Items”對話框。選中“New”標簽頁中的“Console Application”選項,單擊“OK”按鈕,代碼編輯器中將自動打開一個初始名為Project1.dpr的控制臺程序。請將Project1.dpr 文件修改為如下內容:
program
? Project1;
{$APPTYPE
? CONSOLE}
//uses
? SysUtils;
var
? str:string;
begin
? // Insert user code here
? writeln(’您好,這是一個示范程序,請輸入一行文字:’);
? readln(str);
? writeln(’您輸入的是:’,str);
? readln;
end.
依次選擇“File”? “Save
All”菜單項可以將更改后的工程文件保存到指定的文件夾中。本章后面的例子都可以在該工程的基礎上方便地實現。
按F9鍵進入編譯、鏈接、運行程序。待程序提示“您好,這是一個示范程序,請輸入一行文字:” 文字后,用戶可以輸入一些內容,例如輸入“早上好!”,程序將輸出結果:“您輸入的是:早上好!”。
以下是對該程序的幾點說明:
[if !supportLists]?????????[endif]程序第2 行中{$APPTYPE
CONSOLE}是一個編譯器指令,它告訴編譯器這個程序是一個控制臺程序。
[if !supportLists]?????????[endif]uses SysUtils 語句前加了兩個斜線,將這條語句以注釋語句的形式屏蔽掉了,因為在這個例子中是不需要SysUtils 單元的。
[if !supportLists]?????????[endif]writeln 和readln兩個函數分別表示輸出和輸入一行字符。程序最后的readln 語句是為了鎖定窗口,否則輸出結果將很快消失。
注釋語句
作為起點,首先介紹如何在Object Pascal 代碼中添加注釋。如果不給程序加上適當的注釋,一段時間后就很難理清程序的流程。同時編譯器會將注解忽略,不會影響程序的編譯與運行。
Object Pascal 中有3 種類型的注釋。
花括號注釋:組合符號“{”和“}”的成對使用。——{……}
圓括號/星號注釋:組合符號“(*”和“*)”的成對使用。——(*……*)
Visual C++風格的雙斜杠注釋:符號“//”的單獨使用。——//……
注意,相同類型的注釋不要嵌套使用。雖然不同類型的注釋進行嵌套在語法上是合法的,但不建議這樣做。
標識符
Object Pascal 語言使用的標識符包括字母 A~Z、a~z、數字 0~9 及其他一些標準字符。
?Object Pascal 語言的特殊符號
$ & * # ? ( ) [ ] { } ^ ; : @ < = > , . ? + /? ? ?
?Object Pascal 語言的單個的特殊符號
(* *) (. .) .. // := <> >= <=? ?
在 Object Pascal 語言中,標識符用來標識變量、常量、屬性、類、對象、過程、函數、程序、組件庫等。標識符可以由任意長度不帶空格的字符串組成,但對于編譯器來講只有前面
255 個字符有效。其中,標識符的第 1 個字符必須是字母或下劃線,其余字符可以是字母、數字或下劃線。通常,標識符由一個或多個具有適當意義的英文單詞組成。Object Pascal 語言對區分字母的大小寫是不敏感的。
?保留字和指令字
Object Pascal 還定義了 39 個指令字,它們具有特殊含義。但是,在用戶重新定義了指令字后,在作用域內它們就失去了原來的意義。
其中Private、Protected、Public、Published、Automated、On 和At是指令字,但是,應當視其為保留字,不要定義和它們同名的標識符。
在 Delphi 集成開發環境的代碼編輯器中,保留字和指令字以黑體顯示,這樣就大大方便了用戶的使用,不必擔心因為不小心而錯誤地將保留字或指令字定義為標識符。
?數據類型與定義變量
傳遞給過程或函數的參數值必須與形參的類型一致。變量是程序代碼中代表一個內存地址的標識符,那么該地址的內存內容就可以在程序代碼執行時被改變。每個變量都有一個名字和數據類型,名字可以用來引用變量,數據類型決定變量的取值范圍。
1.數據類型概論
Object Pascal 語言提供了非常豐富的數據類型,即簡單類型(Simple)、字符串類型(String)、結構類型(Struct)、指針類型(Pointer)、函數和過程類型(Procedural)和變體類型(Variant)等。
(1)簡單類型(Simple)
簡單類型包括實數類型(Real)和有序類型(Ordinal)。有序類型又包括整數類型、字符類型、布爾類型、枚舉類型和子界類型等。
① 整數類型;包括的類型:
Integer ?-2 147 483 648~2147 483 647
Cardinal ?0~42 994 967 295
Shortint ?-128~127
Smallint ?-32 768~32? 767
Longint ?-2 147 443 648~2? 147 483 647
Int64 ?-2? ~2?????? -1
Byte ?0~255
Word 0~65 535
Longword 0~4 294 967 295
?②字符類型;字符類型有 3 種字符變量:
AnsiChar ????8 位 ?????????根據擴展 ANSI 字符表排列
WideChar ????16 位? ? ? ?根據 Unicode 碼排列,前 256個 Unicode 字符同 ANSI 字符相同
Char? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Delpi 中通用的字符類型,相當于WideChar
注意:因為一個字符在長度上并不表示一個字節,如果程序中必須用到字符的字節數,最好用 SizeOf()函數獲取。
③布爾類型
布爾類型包括4種,分別為Boolean、ByteBool、WordBool 和LongBool。Boolean和ByteBool 各占用一個字節,WordBool 占用兩個字節,LongBool 占用4 個字節。
Boolean的值只能是0(False)或1(True),ByteBool、WordBool 和LongBool 可以是有符號的整數,為0 值代表False,非0值代表True。
最常用的是Boolean 類型,而ByteBool、WordBool 和LongBool 類型是為了與其他語言和Windows 環境兼容,因為Windows 的API 在返回一個布爾值時,其值可能是一個兩字節的有符號整數。如果試圖把返回值賦給Boolean 類型的數據,編譯器認為類型不匹配,若是進行類型強制轉換,可能使返回值的有效數據被截斷。
④枚舉類型
枚舉類型是由一組有序的標識符組成的,它列出了所有這種類型可以包括的值。例如一個星期有7 天,程序中分別用 0、1、2、3、4、5、6 來表示一個星期的每一天,但在程序中很不直觀。
type?//變量名=(枚舉列表)
? DayOfWeek=(Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday);
為了引用此枚舉類型,必須聲明一個DayOfWeek 類型的變量,例如:
var
Days:DayOfWeek;
這樣就聲明了一個DayOfWeek類型的枚舉變量Days,Days 的值總是標識符列表中的一個。
為了簡化程序,還可以將類型聲明和變量聲明合二為一,例如:
var
? Days:(Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday);
注意:枚舉的元素只能是標識符,標識符的命名規則必須符合Object Pascal 關于標識符的規定。例如不能以數字打頭,標識符不能是保留字,同一個枚舉元素不能同時出現在多個枚舉中。
⑤子界類型
子界類型是下列類型中某范圍內的值,即整型、布爾型、字符型或枚舉型。如果需要限制一個變量的取值范圍時,子界類型是一個好的選擇。
⑥實型
實型不是有序類型,因為它的值域是無限的,實型的數據也叫實數,實型用于表示通常所說的浮點數。Object Pascal 語言中的實數數據(Real)類型
Real48? ? Single????Double????Extended????Comp????Currency????Real。
常用的實數類型是 Real、Single、Double。
(2)字符串類型(String)
Object Pascal 的字符串類型分為短字符串和長字符串兩種。
短字符串,指字符串長度最大不超過 255 個字符的字符序列。當編譯開關的狀態為{$H-}時,用保留字 String 聲明的是一個短字符串,不管編譯開關$H 處于什么狀態下,用 ShortString聲明的變量總是短字符串類型。保留字String 后用方括號括起來的無符號整數,表示字符串的最大長度是200。當把一個字符串賦給一個短字符類型的變量時,超過其最大長度的將被截掉。短字符串中的每一個字符都可以通過字符串名加字符索引來訪問。索引是從0 開始的,但索引 0 處存放的是字符串的實際長度,如下兩行代碼的功能是一樣的,索引1 處才是真正的字符開始處。短字符串的長度是動態改變的,可以使用Low和High 函數取得字符串的最小序號和最大序號,Low 的返回值是0,High 的返回值是所聲明的字符串的最大長度。
長字符串的長度幾乎是無限制的,理論上可以達到2GB,實際上只會受計算機內存的限制。要聲明一個長字符串,可以用預定義的標識符AnsiString 或把編譯開關$H 改為{$H+}后用保留字String 聲明。長字符串在聲明以后自動被初始化為空字符串。長字符串中的每個字符,是從索引1 開始的,長字符串沒有索引0,要取得長字符串的實際長度,只能調用Length()函數。長字符串在它最后一個字符后自動加一個NULL 字符表示字符串結束(NULL 字符并不是長字符串的一部分),這一點與字符指針類型(PChar)類似,因此將一個長字符串轉換為PChar類型很方便,語法為:PChar(Str),其中Str 代表長字符串。長字符串被轉換為一個指針,指向字符串的每一個字符,即使長字符串是空的,強制轉換后總是能夠獲得一個指向以NULL 字符結束的字符中的指針。Object Pascal 允許字符串和長字符串同時出現在一個表達式中,編譯器會自動根據需要進行轉換。
注意:字符串變量必須用一對單引號括起來,如果字符串本身就有單引號,這個單引號要用兩個連續的單引號表示,如:’His name is ’’Jim’’’。
(3)結構類型(Struct)
結構數據類型包括:集合類型、數組類型、記錄類型、文件類型、類類型、類引用類型和接口類型等。
集合類型是一群具有相同類型的元素的組合,這些類型必須是有限類型,如整型、布爾型、字符型、枚舉型和子界類型。
type ?
Set1=set of ’A’.. ’Z’;?????????? //基類型是子界型 ?
Set2=set of Char;???????????? //基類型是字符型 ?
Set3=set(Jan,Feb,Mar,Apr);???? //基類型是枚舉型
Object
Pascal 語言提供了幾個用于集合的運算符,用這些運行符可以判斷集合與集合之間的關系,例如對集合增刪元素,求交集運算等。賦值運算與簡單類型一樣,聲明了一個集合類型的變量后,要為這個變量設定一個明確的值,例如:
var ?
TInt1,Tint2:set of 1..10;
以上代碼雖然聲明了兩個集合變量,但變量 TInt1 和 TInt2并不是代表 1~10 組成的集合,必須對它們賦值:
TInt1:=[1,3,5,7,9];
TInt2:=[2..5,8..10];
這樣TInt1 就是由1、3、5、7、9 組成的集合,TInt2 就是由2、3、4、5、8、9、10組成的集合。
關系運算,就是對集合類型的運算,遵循數學中關于集合運算的規則,運算的結果是布爾值。集合的關系運算就是判斷兩個集合相互之間的關系,關系運算符包括:=(等于)、<>(不等于)、>=(大于等于)、<=(小于等于)。
集合 A 等于集合 B,是指兩個集合中的元素完全一樣(不管元素的排列順序如何),否則就是不相等.
數組類型
數組類型是某種數據類型的有序組合,其中每一個元素的值由其相對位置來指定,可以在數組的某個位置上放置數據,并在需要時使用這些數據。下面代碼聲明了一個 Integer 型的數組變量:
var ?
TInt:array [1..15] of Integer;
表示 TInt 指向一個含有 15 個 Integer型元素的數據串列,代表每一個元素的是 1~15 之間的數字,稱為索引。數組的每一項由數據組名加“[ ]”中的索引來表示。TInt 包含 15 個變量,TInt[1]代表第 1 個變量,TInt[2]代表第 2 個變量,依次類推。
數組也可以用類型定義:type????Int=array [1..15] of Integer;????var????TInt:Int;
可以用下面的方法對數組進行賦值: for????I=0 to 15 do????TInt[I]:=0;????//為數組各元素賦初值為0
數組可以有多維的,定義及賦值方法如下:
type
? TArr=array [1..15,1..15] of Integer; var
? Arr:TArr;
? C,R:Integer;
??
for
? C:=1 to 15 do
? for R:=1 to 15 do
? Arr[C,R]:=0;????????? //為多維數組各元素賦初值為0
??
記錄類型:記錄是程序可以成組訪問的一群數據的集合。例如下列代碼,說明了一個記錄類型的定義方法:
type
? TStudent=record
? ID:Integer;
? Name:String[10];
? Age:Integer;
? Memo:String[100];
end;
記錄包含可以保存數據的域,每一個域都有一個數據類型。上面代碼中聲明的 TStuednt
類型有 4 個域。用下面的方法對記錄類型的變量進行聲明與使用:
var
? Stu:TStudent;
? with Stu do?????? //以下代碼為記錄賦值,也可以只給記錄的單個域賦值
? begin
??? ID:=1;
? Name:= ’Jim’;
??? Age:=18;
??? Memo:= ’He is a good student.’;
? end;
(4)指針類型(Pointer)
指針是一個表示內存地址的變量。指針類型在任何語言中都比較難理解,也是一種比較靈活的數據類型。用以下形式定義指針變量:type????指針類型標識符=^基類型;?
下面列舉一個對指針操作的例子,代碼如下:
program Point;???????? //指針示例工程
{$Apptype
? console}
type
? PInt=^Integer;????????????? //定義指針類型 var
? I,K:Integer;
? PI:Pint;?????????????????? //整形指針?
? P:Pointer;???????????????? //無類型指針?
begin
? I:=3;
? K:=5;
? PI:=@K;???????????????? //整形指針指向整形數據?
? writeln(’K=’,PI^);
? P:=@I;
? K:=Integer(P^);?????????? //無類型指針指向整形數據?
? writeln(’K=’,K);
? PI:=P;?????????????????? //指針之間賦值??
? writeln(’PI^:’,PI^);
? readln;
end.
(5)函數和過程類型(Procedural)
Delphi 是面向對象和事件驅動的,因此以前那種自上而下的結構化設計方法已經不適合在Delphi 中編程了。函數和過程是Pascal 語言的兩種子程序,它們可以隨時被調用。函數執行時有返回值,而過程執行時,是沒有返回值的。函數的調用是為了得到一個返回值,調用過程僅僅為了執行某種操作。函數只能出現在表達式中,不能單獨使用;過程不能出現在表達式中,僅能以某個語句的形式出現。
函數的使用:函數在調用之前必須先聲明。函數聲明的語法格式如下:
function 函數名(<形式參數表>):<類型>;
begin
? <語句>;
? <語句>;
? ...
? <語句>;
end;
函數調用的語法格式為:
<函數名>(<實參表>);
注意:實參表中的各個參數必須用逗號分割,其順序必須和函數說明的順序相對應,并且個數相同、類型相符。
過程的使用:過程與函數類似,在調用之前必須進行聲明。過程聲明的語法格式如下:
proceduce
? <過程名>(<形式參數表>)
begin?
? <語句>
? <語句>
? ...
? <語句>
end;
過程調用的語法格式為:<過程名>(<實參表>)
(6)變體類型(Variant)
變體類型能夠在運行期間動態地改變類型。變體類型能支持所有簡單的數據類型,如整型、浮點型、字符串、布爾型、日期時間、貨幣及OLE 自動化對象等。
注意:變體類型不能表達Object Pascal 對象。
2.Type類型聲明語句
在Object Pascal 中,所有的變量必須是某種特定的數據類型,數據類型決定了它所能包含的數值和可進行的操作。Object Pascal 提供了豐富的預定義數據類型,更重要的是它允許定義自己的類型,這就要用到類型聲明語句了。類型也有作用域問題,在程序的Type 區聲明的類型可以在整個程序中使用。在某個過程或函數中聲明的類型則只能在這個過程或函數中使用。
類型聲明語句的格式如下:
type 類型標識符=類型描述;
3.定義變量
變量和常量的區別在于變量在運行期間其值是可以改變的。變量必須明確地指定一個數據類型,而常量是通過等號右邊的數值隱含確定的。
變量的類型可以是標準的類型,也可以是自己定義的類型,其語法如下:
var?????變量標識符:類型;
4.定義常量
常量的特點是在它運行期間不能被修改,因此對常量的賦值是非法的。Object Pascal 提供了幾個預定義的常量,如 True 和 False 等,當然也可以聲明自己的常量,其語法如下:
Const 常量標識符=常數;
Object Pascal 的運算符
1.算術運算符:
操作符 ?操作 操作數據類型 結果類型
+???? 加 ?????整型、實型 ????????整型、實型
-? ? ? 減 ?????整型、實型 ????????整型、實型
*? ? ? 乘 ?????整型、實型 ????????整型、實型
/? ? ? ?除? ? ?整型、實型 ????????整型、實型
mod 取余 ?????整型 ????????????????????整型
div? ? 整除? ? ?整型? ? ? ? ? ? ? ? ? ? ?整型
2.邏輯運算符;邏輯運算符操作對象和返回值都為布爾型,
not ????????非? ? ? ? ? 布爾
and? ? ? ? 與? ? ? ? ? 布爾
or? ? ? ? ? ?或? ? ? ? ? 布爾
xor ????????異或? ? ? ?布爾
3.比較運算符;比較運算符返回值為布爾型(True 或 False),
=? ? ? ? ? 等于 ????????????????????????簡單數據類型、指針、集合、字符串或字符串包
<> ????????不等于 ????????????????????簡單數據類型、指針、集合、字符串或字符串包
<? ? ? ? ? 小于???????????????????????? 簡單數據類型、指針、集合、字符串或 PChar
>? ? ? ? ? 大于???????????????????????? 簡單數據類型、指針、集合、字符串或 PChar
<= ????????小于等于???????????????? 簡單數據類型、指針、集合、字符串或 PChar
>= ????????大于等于 ????????????????簡單數據類型、指針、集合、字符串或 PChar
<= ????????子集 ????????????????????????集合
>= ????????父集 ????????????????????????集合
4.按位運算符
通過按位運算符可以修改一個變量的單獨的位。可以進行按位與、或、非、異或,也可以對一個數進行向左(Shl)或向右(Shr)移位操作。
5.運算符優先級
一個表達式中可能有多個運算符,它們的運算是有先后順序的,不同的運算符在表達式中的優先級如表4-12 所示。
() 括號
+,- 正號和負號
^ 乘方
*,/ 乘和除
+,- 加和減,字符串連接
=,>,<,<=,>=,<> 關系運算符
not 邏輯非
and 邏輯與
or 邏輯或
語句
1.常量聲明語句;常量在聲明時就被賦予了一個值,在程序執行過程中是不可改變的。像變量一樣,常量也有類型。
2.賦值語句—— “=”
3.Goto 語句;Goto 語句可以從程序中的一個地方直接跳轉到另一個地方。但是從結構化程序設計的角度來考慮,盡量不要使用 Goto語句。
goto label;//在使用Goto 語句之前,首先要聲明標號。標號聲明語句如下:
label label1,label2,??,labeln;
4.復合語句;首尾使用 Begin 和 End 包括起來的一組語句稱為復合語句。復合語句可以嵌套使用,也允許有空的復合語句。
5.If 語句
if? <條件> then
? <語句>
else
? <語句>;
If...Then 語句被認為是單語句,在語句結束時只有一個分號
6.Case 語句;If...Then?Else 語句適合選項較少的情況,如果有很多選項的話利用 If 語句就比較麻煩,在這種情況下,Case 語句就容易多了。Case 語句的語法如下:
case <表達式> of
? <數值>:<語句>;
? <數值>:<語句>;
else
? <語句>;
end;
注意:Case 構造中的任何一個語句都可以是單語句或復合語句。如果需要在某種情況下執行多行代碼,必須將它們用Begin?End 括起來。
7.Repeat語句;Repeat 語句會重復執行一行或多行語句,直到某一狀態為真。語句以 Repeat 開始,以 Until 結束,其后跟隨被判斷的布爾表達式。例如:
? I:=0;?? repeat
??? I:=I+1;
??? Writeln(IntToStr(I));
? until I>5;
執行以上的例子時,會顯示1~6 的數字。布爾表達式I>5直到Repeat?Until 程序段結束才會被計算,也就是Repeat 語句至少要執行一次。
8.While語句;While 語句和 Repeat 語句的不同之處在于 While 語句的布爾表達式在循環的開始進行判斷。如果表達式的結果為真則執行循環,否則退出循環。
9.For 語句;For 語句內的程序代碼會執行一定的次數。它需要一個循環變量來控制循環次數。循環變量的類型可以是整型、布爾型、字符型、枚舉型或子界型。
10.Break 語句;在各循環中調用 Break,可以使得程序的執行流程立即跳到循環的結尾。例如程序執行 5 次后跳出循環.
11.Continue 語句;如果想跳過循環中部分代碼,并開始下一次循環,可以調用Continue語句。下面的例子在執行第3 次循環時,Continue 后的代碼不執行而繼續下一次的循環
12.With 語句;使用記錄類型的變量時,可以通過 With 語句指定一些語句,這些都是針對某一個變量來說的,這樣可以簡化代碼的輸入量。
? 過程與函數
過程與函數是實現一定功能的語句塊,是程序中的特定功能單元。可以在程序的其他地方被調用,也可以進行遞歸調用。過程與函數的區別在于過程沒有返回值,而函數有返回值。
1.過程與函數的定義;過程與函數的定義包括過程原型或函數原型、過程體或函數體的定義。過程定義的形式如下:
procedure? ProcedureName(ParameterList); directives;
var
? LocalDeclarations;
begin
? statements
end;
ProcedureName 是過程名,是有效的標識符。ParameterList為過程的參數列表,需要指明參數的個 數 和 數 據 類 型 。Directives 是一 些 關 于 函 數 的 指 令 字 , 如 果 設 置 多 個 , 應 該 用 分 號 隔 開 。LocalDeclarations 中定義了該函數中需要使用的一些臨時變量,通常也稱作本地變量。在Begin與End 之間是過程調用時實現特定功能的一系列語句。ParameterList、Directives、LocalDeclarations和Statements 都是可選部分。
函數的定義與過程非常類似,只是使用的保留字不同,而且多了一個返回值類型。具體形式如下:
function? FunctionName(ParameterList): ReturnType; directives;
var
? LocalDeclarations;
begin
?statements
end;
可以將函數需要返回的數值賦值給變量 Result。如果函數體中存在著一些由于判斷而產生的分支語句時,就要在每一個分支中設置返回值。通常要根據函數的返回值來確定下一步的操作。注意,這里與Visual C 和 Visual C++不一樣,把一個值賦給 Result,函數并不會結束。
2.參數
函數定義時參數列表中的參數稱為形參,函數調用時參數列表中的參數稱為實參。在定義的函數原型中,多個參數之間用分號隔開,同一類型的參數可以放在一起,以逗號隔開。函數調用的時候,在函數原型中,多個參數之間用逗號隔開。
一般來說,形參列表和實參列表完全匹配是指參數的個數一樣,而且順序排列的數據類型也完全一致。對于普通的函數,如果編譯器發現實參的數據類型與形參的數據類型不匹配,會將實參的數據類型進行一次或多次的“提升”,比如把Integer類型轉換為Double 類型。可以為過程和函數的參數指定默認數值。
指定默認數值的參數要放在參數列表的后部,而沒有指定默認數值的參數要放在參數列表的前部。在函數調用的時候,可以為設置了默認值的參數指定一個新值。在函數體中,各語句使用的是指定的新值,如果沒有指定新值,則使用默認值。同樣,如果存在多個設置了默認值的參數,只有在前面的參數指定了新值后,后面的參數才可以指定新值。
下面的例子定義了一個 OutputNum 函數,可以將一個浮點數按指定的精度輸出。通過這個例子,可以體會函數中參數的使用:
program Project1;
{$APPTYPE
? CONSOLE}
uses? Sysutils;???????????????????????? //為了使用函數Format
function
? OutputNum(number:double;n:integer = 5):Boolean; var
? Str : string; //浮點數顯示輸出的內容?
begin
? if n <= -1 then?????????????????????? //小數點后的位數要大于或等于0
? begin
??? Result:=False;
? Exit;????????????????????????????
? //退出顯示函數??
? end
? else
? begin
??? //設置顯示的格式
??? Str := Format(’%*.*f’, [10, n, number]);
??? Result := True ;
??? Writeln(Str);??????????????????????? //顯示數據?
? end;
end;
begin
? OutputNum(12.345);??????????????????? //n默認為5
? OutputNum(123,3);???????????????????? //參數對數據類型進行升級?
? //下面一句代碼不正確,故屏蔽掉?
? //OutputNum(123.456789,9.13);?????????? //參數對數據類型不能降級?
? //可以根據函數的返回值確定下一步的操作
? if OutputNum(123.456789,-3) = False then
? Writeln( ’輸出失敗。’ ) ;
? Readln;
end.
3.過程與函數的調用約定
在調用過程或函數的時候,如果參數列表中具有多個參數,那么參數傳遞給過程或函數的順序會對結果產生一定的影響。對于不同的語言,參數傳遞的順序是不同的:Pascal 語言是按照從左向右的順序進行傳遞的,而C語言是按照從右向左的順序來傳遞的。為了確定傳遞的順序,可以在過程或函數定義的時候,在Directives部分利用指令字指定傳遞的順序。
4.過程和函數的重載
可以在同一個作用范圍內給不同的過程或函數取同一個名稱,這種現象就叫做重載。這樣可以使編程更方便。在重載的情況下,決定使用哪個過程或函數的依據是形參和實參的一致性,即參數個數、參數類型以及它們之間的順序,不存在一個函數調用滿足兩個重載函數的情況。另外重載函數必須用指令字Overload 來進行說明,函數的返回值類型不同就不可以作為重載函數的依據。下面的兩個函數就是重載函數:
function Average(a:Integer; b:Integer):Double;overload;??????? //求整形數據的平均值
function? Average(a:Double; b:Double):Double;overload;??????? //求實數數據的平均值?
5.函數的遞歸調用
在 Object Pascal 中,過程或函數必須先說明再調用。以上規則在遞歸調用時屬于例外情況。所謂遞歸調用,是指函數 A 調用函數 B,而函數 B 又調用函數 A 的情況,或是指一個函數調用自身的特殊情況。在遞歸調用中,函數要進行前置,即在函數或過程的標題部分最后加上保留字Forward。
program? Project1;
{$APPTYPE CONSOLE}
var
? Alpha:Integer;
? procedure Test2(var A:Integer);forward;
? //Test2被說明為前置過程
procedure
? Test1(var A:Integer);
begin
? A:=A-1;
? if A>0 then
??? Test2(A);?????????????? //經前置說明,調用未執行的過程Test2
procedure? Test2(var A:Integer); //經前置說明的Test2 的執行部分?
begin
? A:=A div 2;
? if A>0 then
? Test1(A);?????????????? //在Test2 中調用已執行的過程Test1 end;
begin
? Alpha := 15;????????????? //給Alpha
? 賦初值
? Test1(Alpha);???????????? //第1
? 次調用Test1,遞歸開始?
end.