2.1.8.4 過程和函數的語句部分
過程或函數的語句部分由begin開始,end結束。函數需要一個返回值。可以將返回值賦給函數名稱,也可以將返回值賦給Result變量。下面的例程將返回值賦給函數名稱:
function CalculateInterest(Principal,InterestRate: Double):Double;
begin
CalculateInterest := Principal * InterestRate;
end;
將返回值賦給Result變量也是可以的,則上面的程序改為:
Result := Principal*InterestRate;
下面是這個函數的調用方法:
InterestEarned :=CalculateInterest(2000,0.012);
在Implementation後面的過程和函數,可以且只能被此庫單元的事件處理過程使用。要讓過程和函數可以被其他的程序庫單元使用,則需要將過程或函數的標題部分放在庫單元中的interface部分,而把含標題的整個過程或函數放在庫單元的inplementation部分,並在要訪問這個過程或函數的庫單元的uses子句中加入說明這個過程或函數的庫單元名稱。
2.1.8.5 函數的遞歸調用
在Object Pascal中,過程或函數必須先說明再調用。上文的NoValue函數必須在使用它的事件處理過程之前說明和執行,否則程序會報告一個未知標識符的錯誤。
以上規則在遞歸調用時是例外情況。所謂遞歸調用,是指函數A調用函數B,而函數B又調用函數A的情況。在遞歸調用中,函數要進行前置,即在函數或過程的標題部分最後加上保留字forword。下文的例程是一個遞歸調用的典型例子:
…
implementation
var
alpha:Integer;
procedure Test2(var A:Integer):forword;
{Test2被說明為前置過程}
procedure Test1(var A:Integer);
begin
A :=A-1;
if A>0 then
test2(A); {經前置說明,調用未執行的過程Test2}
writeln(A);
end;
procedure Test2(var A:Integer);{經前置說明的Test2的執行部分}
begin
A :=A div 2;
if A>0 rhen
test1(A); {在Test2中調用已執行的過程Test1}
end;
procedure TForm1.Button1Click(Sender:TObject);
begin
Alpha := 15; {給Alpha賦初值}
Test1(Alpha); { 第一次調用Test1,遞歸開始}
end;
按鈕的OnClick事件處理過程給Alpha賦初值,並實現先減1再除2的循環遞歸調用,直到Alpha小於0為止。
2.1.8.6 過程和函數的參數
當您的程序代碼在調用一個過程或函數時,通常用參數傳遞數據到被調用的過程或函數中。最常用的參數有數值參數、變量參數和常量參數三種。
由被調用過程或函數定義的參數為形參,而由調用過程或函數指明的參數叫實參。在NoValue函數中,說明函數體中的AnEditBox是形參,而調用時在if NoValue(Edit1)…中,Edit1是實參。
數值參數在運行過程中只改變其形參的值,不改變其實參的值,即參數的值不能傳遞到過程的外面。試看下面的例程:
procedure Calculate(CalNo:Integer);
begin
CalNo := CalNo*10;
end;
用以下例程調用Calculate函數:
…
Number := StrToInt(Edit1.Text);
Calculate(Number);
Edit2.Text := IntToStr(Number);
…
Number接受由編輯框1輸入的數值,經Calculate過程運算。它是一個數值型實參。在進入Calculate函數後,會把Number實參拷貝給形參CalNo,在過程中CalNo增大十倍,但並未傳遞出來,因此Number值並未改變,在編輯框2中顯示仍然是編輯框1中的輸入值。形參和實參占用不同的內存地址,在過程或函數被調用時,將實參的值復制到形參占用的內存中。因此出了過程或函數後,形參和實參的數值是不同的,但實參的值並不發生變化。
如果您想改變傳入的參數值,就需要使用變量參數,即在被調用程序的參數表中的形參前加上保留字var。例如:
procedure Calculate(var CalNo : Integer);
則CalNo並不在內存中占據一個位置,而是指向實參Number。當一個變參被傳遞時,任何對形參所作的改變會反映到實參中。這是因為兩個參數指向同一個地址。將上一個例程中過程頭的形參CalNo前面加上var,再以同樣的程序調用它,則在第二個編輯框中會顯示計算的結果,把第一個編輯框中的數值放大十倍。這時形參CalNo和實參Number的值都是Nnmber初始值的10倍。
如果當過程或函數執行是要求不改變形參的值,最保險的辦法是使用常量參數。在參數表的參數名稱前加上保留字const可以使一個形參成為常量參數。使用常量參數代替數值參數可以保護您的參數,使您在不想改變參數值時不會意外地將新的值賦給這個參數。
2.1.9 定義新的數據類型
Object Pascal有一些系統預定義的數據類型,在2.1.2中已經對它們作了介紹。您可以利用這些數據類型以建立新的數據類型來滿足程序的特定需要。下面簡單地敘述了您能建立的主要數據類型,如枚舉型、子界型、數組型、集合型、記錄型、對象型等。
2.1.9.1 枚舉類型
一個枚舉型的說明列出了所有這種類型可以包括的值:
type
Tdays=( Sunday ,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday);
可以定義上述枚舉類型的變量:
var
DayOfWeek:TDays;
在枚舉型中,括號中的每一個值都有一個由說明它的位置決定的整形值。例如Sunday有整形值0,Monday有整形值1等。您可以把DayOfWeek說明為一個整形變量,並將一星期的每一天賦一個整形值以達到相同的效果,但用枚舉型會使得程序可讀性好,編寫容易。當您在枚舉型中列出值時,您同時說明了這個值是一個標識符。例如您的程序中如果已經含有TDays類型且說明了DayOfWeeks變量,則程序中便不能使用Monday變量,因為它已經被說明為標識符了。
2.1.9.2 子界類型
子界型是下列這些類型中某范圍內的值:整形、布爾量、字符型或枚舉型。在您想限制一個變量的取值范圍時,子界型是非常有用的。
type
Thours = 0..23;
TValidLetter = 'A' .. 'F';
TDays = ( Sunday ,Monday,Tuesday,Wednesday,Thursday,
Friday,Saturday); {枚舉型}
TWorkDay = Monday..Friday; {一個TDays型的子界}
子界型限定了變量的可能取值范圍。當范圍檢查打開時,(在庫單元的Implementation後面有{$R*.DFM}字樣表示范圍檢查打開,否則您可以在Options|Project|Complier Options中選擇Range Cheking來打開范圍檢查),如果變量取到子界以外的值,會出現一個范圍檢查錯誤。
2.1.9.3 數組類型
數組是某種數據類型的有序組合,其中每一個元素的值由其相對位置來指定,您可以在數組的某個位置上放置數據,並在需要時使用這些數據。下面的類型說明了一個Double型的數組變量:
var
Check : array [1..10] of Double;
它表示Check指向一個含有10個Double型元素的數據串列,代表每一個元素的是1到10之間的數字,稱為索引。數組的每一項由數組名稱加上[]中的索引來表示。Check包含10個變量,Check[1]表示第一個變量。您也可以把數組定義成類型:
type
TCheck = array[1..10] of Double;
則變量說明改為:
var
Check :TCheck;
您可以通過給數組賦值等方法來使用數組。下面的語句將0.0賦給Check數組中的所有元素:
for J := 1 to 10 do
Check[J] := 0.0;
數組也可以是多維的,下面的類型定義了一個20行、20列的數組。
type
Ttable = array[1..20,1..20] of Double;
var
table1:TTable;
想將這一表格的所有數據初始化為0.0,您可以使用for循環:
var
Col,Row:Integer;
…
for Col :=1 to 20 do
for Row := 1 to 20 do
Table1[Col,Row] := 0.0;