Procedurer och funktioner
Förord
Procedurer och funktioner måste användas vid all programmering. Här visas hur det används i Delphi. De procedurer som vi hanterat i tidigare avsnitt har alla varit händelseprocedurer som Delphi ställt i ordning en stomme till. Vi skall nu ge oss på att skapa några egna procedurer som inte nödvändigtvis behöver vara kopplade till någon komponent.Innehåll
»»
»
Relaterade artiklar
» Arraystrukturer» Händelser i Delphi
» Introduktion till Delphi # 1
» Iteration
» Räkna med Delphi
» Skapa program i Delphi
» Strängkonstanter och strängvariabler
Ett exempel på en procedur
Anta att vi har tillverkat ett program som innehåller tre editeringsrutor, som vi vill tömma vid olika tillfällen. Vi skulle kunna lösa det genom att lägga till en knapp på formuläret och sedan skriva kod för detta. Men denna metod förefaller lite överarbetad. Istället löser vi detta genom att skriva en fristående procedur.Vi börjar med att skriva in proceduren namn i formulärets Private-del.
private
{ private declarations }
procedure RensaTextrutor; //Detta lägger du till
public
{ public declarations }
end;
Vi lägger deklarationen i private-delen, därför att inga andra enheter som vi eventuellt använder oss av, skall kunna använda denna procedur. Detta är en allmän princip. Det som inte andra delar behöver känna till, skall de fortfarande vara ovetande om.
Detta räcker emellertid inte utan vi måste också tala om för kompilatorn vad proceduren skall utföra. Vi måste implementera proceduren. I enhetens implementationsdel, förslagsvis efter kompileringsdirektivet.
implementation
{$R *.DFM}
procedure TForm1.RensaTextrutor;
begin
Edit1.Text := '';
Edit2.Text := '';
Edit3.Text := '';
end;
Lägg märke till att vi måste tala om för kompilatorn att detta är en procedur som är knuten till formulärtypen TForm1. Det räcker alltså inte med att bara skriva
procedure RensaTextrutor;
Varje gång som vi nu behöver rensa de tre textrutorna räcker det med att skriva
RensaTextrutor;
Ett exempel på en funktion
Underprogram kan också utgöras av funktioner. En funktion fungerar precis som en procedur med enda undantaget att den returnerar ett värde. Detta värde kan man lagra i en variabel, använda den i ett beräkningsuttryck, skriva ut på skärmen etc.Observera att man i princip kan använda en funktion överallt där man annars använder en konstant. Till skillnad från en konstant, som har ett konstant värde, beräknar en funktion alltid det värde den returnerar.
Värdet som en funktion returnerar kan vara av olika datatyp. Funktionens värde måste därför deklareras vad beträffar datatypen, precis på samma sätt som man anger datatypen för en variabel.
Vi skall visa hur en funktion ser ut genom att skriva ett enkelt program där vi anger sidorna i en triangel.
Placera ut komponenter på ett formulär enligt bilden nedan.
Dubbelklicka på knappen och skriv in följande händelseprocedur.
procedure TForm1.BitBtn1Click(Sender: TObject);
var
a,b,c : double;
ok : boolean;
begin
a := StrToFloat(Edit1.Text);
b := StrToFloat(Edit2.Text);
c := StrToFloat(Edit3.Text);
ok := (a+b>c) and (a+c>b) and (b+c>a);
if ok then
Label4.caption := 'Detta kan vara sidor i en triangel'
else
Label4.caption := 'Detta är inga triangelsidor';
end;
Kör programmet och testa olika sidor. I händelseproceduren används en logisk variabel ok. Den skall innehålla värdet av testen att sidorna utgör triangelsidor, vilket den får i satsen
ok := (a+b>c) and (a+c>b) and (b+c>a);
Anta nu att vi utvidgar vårt program till en jätteprogram. På flera ställen i programmet får vi anledning till att testa om sidorna kan vara triangelsidor. I annat fall skrivs motsatsen ut. Vi lägger då nyss skrivna procedur i en funktion istället. Så här kan en sådan funktion se ut.
private
{ private declarations }
procedure RensaTextrutor; //Detta lägger du till
public
{ public declarations }
end;
implementation
{$R *.DFM}
function TForm1.SidorOK : boolean;
var a,b,c : double;
begin
a := StrToFloat(Edit1.Text);
b := StrToFloat(Edit2.Text);
c := StrToFloat(Edit3.Text);
SidorOK := (a+b>c) and (a+c>b) and (b+c>a);
end;
Sedan ändrar vi proceduren för knappen på följande sätt.
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
//SidorOK ger samma värde som ok tidigare.
if SidorOK then
Label4.caption := 'Detta kan vara sidor i en triangel'
else
Label4.caption := 'Detta är inga triangelsidor';
end;
När vi nu behöver testa våra triangelsidor räcker det med att anropa funktionen med att skriva SidorOK så får vi reda på det.
I deklarationen av funktionen kallas den första satsen
function TForm1.SidorOK : boolean;
för funktionshuvudet. Det börjar med det reserverade ordet function och följs av namnet på funktionen. Därefter anges datatypen på det värde som funktionen skall returnera. Eftersom vi knutit funktionen till formulärtypen måste vi kvalificera namnet på funktionen SidorOK med TForm1.
Det vanligaste felet vid funktioner är att man glömmer att returnera ett värde, dvs. man glömmer att sätta funktionsnamnet lika med det värde som skall returneras. Kompilatorn protesterar inte mot detta!
Beträffande händelseproceduren för OK-knappen behöver vi inga lokala variabler för att uföra några tester. Här överlåts alla tester till funktionen SidorOK.
Värdeparametrar till underprogram
Vi har tidigare tagit upp underprogram som använder sig av parametrar, t ex standardfunktionen Succ.Succ returnerar efterföljaren till det den anropas med.
Label1.Caption := Succ('A'); { Ett B skrivs ut på etiketten }
Efter Succ anger vi det vi vill att Succ skall arbeta med. Till funktionen överlämnas data, ett argument, via en inkanal som här utgörs av en värdeparameter. Hur kan deklarationen tänkas se ut? Låt oss se på ett exempel, där vi begränsar Succ till att arbeta enbart med bokstäver.
function Succ(x:char):char;
{Succ är deklarerat i och med att det står i funktionshuvudet.}
begin
Inc(x);
Succ := x;
end;
I funktionshuvudet deklareras i parentesen efter namnet på funktionen en värdeparameter x av datatypen char. Efter parentesen skriver vi ett kolon och datatypen på det värde som funktionen skall returnera.
Den datatyp som anges för parametrar måste vara deklarerad tidigare, dvs. vara en datatyp som är standard eller tidigare deklarerad i en type-deklaration. I parameterlistan får alltså inte ingå någon form av typbeskrivning.
Vid ett anrop av Succ kommer x att fungera som en inkanal, dvs ha ett värde som funktionen kan utnyttja. Alla värdeparametrar fungerar som lokala variabler som får sina värden vid anrop av underprogrammet. Man får funktionen att returnera ett värde genom att tilldela funktionsnamnet själva returvärdet, Succ := x.
0 Kommentarer