You are on page 1of 6

SELF ASSIGNMENT

Chapters 1 13 (Events, methods, procedures, functions and parameters)


The following user interface and code calculates and displays the total cost of
items selected. Implement this code and then answer the questions that follow.

unit CalculateDisplayCost;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, StdCtrls, Spin, ExtCtrls;
type
TfrmCalculateDisplay = class(TForm)
btnCalculateDisplay: TButton;
rgpProducts: TRadioGroup;
sedNumber: TSpinEdit;
lblNumber: TLabel;
lblCost: TLabel;
procedure btnCalculateDisplayClick(Sender: TObject);
private
{ Private declarations }
procedure CalculateTotalCost (nNumber : Integer;
rCost
: Double;
var rTotalCost : Double);
procedure DisplayTotalCost (sProduct : String;
rTotalCost : Double);
public
{ Public declarations }
end;
var
frmCalculateDisplay: TfrmCalculateDisplay;
implementation
{$R *.dfm}
procedure TfrmCalculateDisplay.CalculateTotalCost (nNumber : Integer;
rCost
: Double;
var rTotalCost : Double);
begin
rTotalCost := nNumber * rCost;

end;
procedure TfrmCalculateDisplay.DisplayTotalCost (sProduct : String;
rTotalCost : Double);
begin
lblCost.Caption := IntToStr(sedNumber.value) + ' ' + sProduct + '
costs ' + FloatToStrF(rTotalCost, ffCurrency, 15,2);
end;
procedure TfrmCalculateDisplay.btnCalculateDisplayClick(Sender:
TObject);
var
sProduct
: String;
rTotalCost : Double;
const
rCost = 5.00;
begin
CalculateTotalCost(sedNumber.Value, rCost, rTotalCost);
sProduct := rgpProducts.Items[rgpProducts.ItemIndex];
DisplayTotalCost(sProduct, rTotalCost);
end;
end.

1.1

Discuss the procedure CalculateTotalCost in terms of the structure of a


simple procedure (see page 296). (3)
Procedure tells Delphi that it is a procedure.
The class name for this procedure is TfrmCalculateDisplay
The fullstop connects that class name to the procedure name, in this case
CalculateTotalCost.
After the procedure name, a list of parameters are included in the brackets, in
this case (nNumber : Integer; rCost : Double; var rTotalCost : Double)
There are three parameters: there are two value parameters (nNumber is of
type integer, and rCost is of type double), and one var (or reference) parameter
(rTotalCost is of type Double).
The begin statement tell Delphi that the program statements of the procedure
are about to begin. In this case, there is only one line of code between the begin
and the end statements.
The code that is executed takes the two input parameter values, calculates the
product and then assigns the answer of the calculation to the reference
parameter (i.e. the value is passed back to the calling program!)

1.2

Explain how the use of procedures contributes to a well structured


program and the advantages thereof. (see page 297 and 306) (3)
Procedures are used when the same code can be used more than once, when the
details of the implementation are hidden, when program statements can be
consolidated, and when the code can be re-used. In this case, the program is
consolidated and the implementation details are hidden. The use of procedures

contributes to a better structured program.


A better structured keep the code simpler, thus programs do not become too
complicated.
A better structured program has fewer errors.
A better structured program is more understandable. The use of procedures can
hide implementation details.
A better structured program allows for the re-use of code sections, in different
programs.
1.3

Explain what a parameter is. How many parameters does the procedure
DisplayTotalCost have? (2)
A parameter provides the communication between the subroutine (procedure or
function) and the calling program. The procedure DisplayTotalCost has two
parameters. These values are passed into the procedure. No values (note that
the values passed into the procedure remained unchanged!) are returned from
the procedure.
1.4

With reference to the above code, explain some of the important points
to remember when using subroutines (see page 298). (2)
The parameter lists of the header and the subroutine call must match in
NUMBER, ORDER and TYPE (else the call will NOT work)
Within a subroutine, parameter matching is by name.
Subroutines must be declared in the classs type declaration.
The values that are passed to the subroutine can either be constants or
variables.
A subroutine may either be general or bound to the form class.
1.5

Name four kinds of parameters used in Delphi subroutines, and explain


briefly when they should be used. (4)
See page 323-325 in prescribed book.
Constant parameter
Out parameter
Value parameter
Variable parameter
1.6
Why does procedure CalculateTotalCost have a var parameter? (1)
The value that is calculated in the procedure needs to be passed from the
procedure back to the calling program.
1.7

Why are the procedures CalculateTotalCost and DisplayTotalCost


declared in the private section? Can these procedures be declared in the
public section? Motivate. (2)
These procedures are private to this class (program), and can therefore only be
used within the scope if this program (unit). If the procedures were declared
public, they could be called by other units in the project. CalculateTotalCost may

be used by other units, but DisplayTotalCost is form specific as it contains a


reference to a label and a SpinEdit component on the form.
1.8

Can the procedure DisplayTotalCost be replaced by a function


DisplayTotalCost? Motivate your answer. (1)
No, functions return a single value. DisplayTotalCost does not return any values,
thus a function cannot be used.
1.9
Why does the procedure DisplayTotalCost have no var parameters? (1)
Because no values are returned from the procedure.
1.10

What would happen if the var was removed from the header of the
procedure CalculateTotalCost? (1)
The calculated value would not be returned.
1.11
Explain what happens when the procedure DisplayTotalCost is called. (2)
The procedure DisplayTotalCost is called from the event handler
btnCalculateDisplayClick.
After the name of the product has been assigned to the variable sProduct, the
procedure is called.
The value parameters (the sProduct and rTotalCost) are passed into the
procedure.
The procedure call has the form DisplayTotalCost(sProduct, rTotalCost);
The parameter listing matches the declaration in Number, Order and Type of
parameters.
The values are used in the concatenation of the string that is then assigned to
the caption of the required label for the display.
1.12
Explain what happens when the execution of a procedure is completed. (2)
The execution of the program ends when the end (the reserved word) is
encountered.
If required, the var parameter values are returned, and the execution of the
program returns to the line of code that follows the procedure calling.
1.13
How would you ensure that a product is always selected? (2)
During design time, change the value of the ItemIndex of the RadioGroup. When
nothing is selected the value of the ItemIndex is -1. If this value is changed to
0, then the first item is selected by default.
1.14

How would you change the program to ensure that the item Scones is
selected as the default? (2)
Scones is the third item in the RadioGroup, thus the ItemIndex of this item is
2. During design time, change the value of the ItemIndex.

1.15
How would you ensure that a minimum of one product is purchased? (2)
During design time, change the minimum value property of the SpinEdit to 1.
1.16

Rewrite the procedure CalculateTotalCost as a function


CalculateTotalCost. (3)

function TfrmCalculateDisplay.CalculateTotalCost (nNumber : Integer;


rCost
: Double) :
Double;
var rTotalCost : Double;
begin
rTotalCost := nNumber * rCost;
Result
:= rTotalCost;
end;

1.17

Add a button to reset the user interface. Write the code for this event
handler. (3)

procedure TfrmCalculateDisplay.bmbResetClick(Sender: TObject);


begin
rgpProducts.ItemIndex := 0;
lblCost.Caption := 'The cost ';
sedNumber.Value := 1;
end;

1.18

Give reasons for the use of incremental development. With reference to


the above code, give an example of an increment that may be used in the
development of this program. (4)

Reasons (3)
Incremental development is used to solve the problem in stages.
Each stage considers a smaller easy to write program.
Each stage may be tested thoroughly. There is thus less chance of making mistakes, and
it is easier to test and correct code.
A new increment is added to the existing code. This can be re-tested, thus reducing the
chance of introducing many errors all at once.
Once this code is working give one of the following (1)
This code could be incremented to include different prices for each product.
This code could be incremented to allow for the selection of multiple items.
This code could be incremented to include some discount structure.

1.19

An increment is required to produce a new


version of the program. Modify the program
(that you have already implemented and tested)
so that the cost of the item is determined by
the size of
the portion.
Add
a
RadioGroup
to the user
interface. A small portion costs
R5.00, a medium portion R7.80, and a

large portion R11.20. The default option is a small portion. Remove the
const declaration from the previous version, to include the size of the
portion in the display of the total cost (need to modify the header of the
procedure), and to reset the ItemIndex of the PortionSize RadioGroup!
Function CalculateTotalCost remains unchanged. Show code changes to
DisplayTotalCost, btnCalculateDisplayClick, and bmbResetClick. (10)
procedure TfrmCalculateDisplay.DisplayTotalCost (sProduct : String;
sSize
: String;
rTotalCost :
Double);
begin
lblCost.Caption := IntToStr(sedNumber.value) + ' ' + sProduct + '
( ' +
sSize + ' ) costs ' + FloatToStrF(rTotalCost,
ffCurrency, 15,2);
end;
procedure TfrmCalculateDisplay.btnCalculateDisplayClick(Sender:
TObject);
var
sProduct
: String;
sSize
: String;
rCost
: Double; //this was added for this version of the
program
rTotalCost : Double;
{const
rCost = 5.00; this is removed for the next version of the program}
begin
case rgpPortionSize.ItemIndex of
//the case was added
0 : rCost := 5.00;
1 : rCost := 7.80;
2 : rCost := 11.20;
else
ShowMessage('Ensure that portion size is selected');
end;
rTotalCost := CalculateTotalCost(sedNumber.Value, rCost);
sProduct := rgpProducts.Items[rgpProducts.ItemIndex];
sSize
:= rgpPortionSize.Items[rgpPortionSize.ItemIndex]; //added
DisplayTotalCost(sProduct, sSize, rTotalCost); //modified to
include size
end;
procedure TfrmCalculateDisplay.bmbResetClick(Sender: TObject);
begin
rgpProducts.ItemIndex
:= 0;
rgpPortionSize.ItemIndex := 0; //added
lblCost.Caption
:= 'The cost ';
sedNumber.Value
:= 1;
end;
unisa 2010