Functions and procedures that call other functions and procedures - pascal

I need to:
Write a function called ReadCar(): Car; that reads from the terminal values for each of the fields in a Car record and returns the completed record.
Write a procedure called WriteCar(c: Car); that takes a car record and writes each of the fields to the terminal with a description for the field as well as the field value.
Write a function called ReadAllCars(count: Integer): Cars; that calls your ReadCar() function count times and stores each car in Cars.
Write a procedure called WriteAllCars(carArray: Cars); that calls your WriteCar() procedure for each car in carArray.
So far I believe I have done steps 1 and 2 correctly but I am not sure how to do steps 3 and 4. How should I begin those steps? By the end of this program I am supposed to be able to enter data for 3 cars and it print the data properly.
program carDetails;
uses TerminalUserInput;
type Cars = Array of Car;
Car = record
ID : integer;
Manufacturer : string;
Model : string;
Registration : integer;
end;
function ReadCar(): Car;
begin
WriteLn(promt);
ReadCar.ID := readInteger('Please enter the Car ID ');
ReadCar.Manufacturer := readString('Please enter the manufacturer of car '+ ReadCar.ID);
ReadCar.Model := readString('Please enter the model of car '+ ReadCar.ID);
ReadCar.Registration := readInteger('Please enter the registration number for car '+ ReadCar.ID);
end;
procedure WriteCar(c: Car);
begin
WriteLn('ID - ', c.ID);
WriteLn('Manufacturer - ', c.Manufacturer);
WriteLn('Model - ', c.Model);
WriteLn('Registration - ', c.Registration);
end;
function ReadAllCars(count: integer): Cars;
begin
end;
procedure WriteAllCars(carArray: Cars);
begin
end;
procedure Main();
var cars: Array of Car;
index: Integer;
begin
cars := ReadAllCars(3);
WriteAllCars(cars);
end;
begin
Main();
end.

I'm not going to do your coursework (from Swinburne Uni?) for you, but here are a few points.
You need to declare your Car record before your Cars array.
type //Cars = Array of Car;
Car = record
ID : integer;
Manufacturer : string;
Model : string;
Registration : integer;
end;
Cars = Array of Car;
In ReadCar, your Prompt variable is undeclared (and mispelt). It should be
function ReadCar(const Prompt : String): Car;
begin
// WriteLn(promt);
WriteLn(Prompt);
Also in ReadCar, you need to convert Car.ID to a string before you can use it in your calls to readString, like so:
ReadCar.Manufacturer := readString('Please enter the manufacturer of car ' + IntToStr(ReadCar.ID));
ReadCar.Model := readString('Please enter the model of car ' + IntToStr(ReadCar.ID));
ReadCar.Registration := readInteger('Please enter the registration number for car ' + IntToStr(ReadCar.ID));
In ReadCars, you need to set the length of the array returned by it:
function ReadAllCars(count: integer): Cars;
begin
SetLength(Result, Count);
end;
Having done all that, writeCars is actually very simple. All you need is
procedure WriteAllCars(carArray: Cars);
var
i : Integer;
begin
for i:= Low(carArray) to High(carArray) do
WriteCar(carArray[i]);
end;
Using the Low() and High() functions sidesteps the issue of having to know the lower and upper bounds of an array declared the way your Cars one is (i.e. an array of record). Actually they are zero-based, not 1-based.
For some reason, SO's code-formatter doesn't do its normal stuff with the code in this answer, I'll try and tidy it up later.

Related

How do i read in a number to enter details with arrays and records?

I am having trouble reading the array of records using my ReadAllCars function. How do I get to read all 4 inputs of the Car records into the Cars array? I keep getting dynamic array error.
type
cars = record
model:String;
year:integer;
end;
car = array of cars;
function readCar(prompt: String): Cars;
begin
WriteLn(prompt);
result.model := ReadString('Car Model: ');
result.year := ReadInteger('Year: ');
end;
**(this is my problem)**
function ReadAllCars(count:integer): Cars;
var
carArray: array of cars;
i:integer;
begin
setLength(carArray, count);
for i := 0 to high(carArray)do
begin
result.carArray[i] := readCar('Enter Car Details');
end;
end;
procedure Main();
var
cars: Array of Car;
begin
cars := ReadAllCars(4);
end;
The problem is here:
function ReadAllCars(count:integer): Cars;
This function returns type cars, which is declared as a record, not an array.
You have mixed up type Cars = record ... with a declared variable cars : array of cars.
This is how ReadAllCars should look like:
function ReadAllCars(count:integer): Car;
var
i:integer;
begin
setLength(Result, count);
for i := 0 to high(Result)do
begin
result[i] := readCar('Enter Car Details');
end;
end;

Searching for a Corresponding Value in a TList Delphi7

I have a TList which I populate dynamically, from the database, it contains an ID and Name.
What I need to know is how to search for a certain Name in that TList by providing an ID without using for loop.
without using for loop
Unfortunately, that is exactly what you must use. A TList containing pointers only knows how to search for pointers, nothing else. To do what you are wanting, you must loop through the list dereferencing the pointers manually in order to compare their field values.
For example:
type
TDatabaseRecord = class
public
ID: Integer;
Name: String;
end;
function FindNameByID(ID: Integer): String;
var
I: Integer;
begin
Result := '';
for I := 0 to MyList.Count-1 do
begin
if TDatabaseRecord(MyList[I]).ID = ID then
begin
Result := TDatabaseRecord(MyList[I]).Name;
Exit;
end;
end;
end;

pascal adding tedit text to record

I am having problems with adding text I have entered into a tedit, into an record.
Here is the code i currently have:
procedure TForm7.AddNewQuestionClick(Sender: TObject);
var
w: integer;
QuestDesc, QuestAnsr: string;
begin
NewQuestID.text:=(GetNextQuestionID); //Increments QuestionID part of record
w:=Length(TQuestions);
SetLength(TQuestions, w+1);
QuestDesc:= NewQuestDesc.text;
QuestAnsr:= NewQuestAns.text;
TQuestionArray[w+1].Question:= QuestDesc; // Error on this line (No default property available)
TQuestionArray[w+1].Answer:= QuestAnsr;
end;
Here is the record I am trying to add to:
TQuestion = record
public
QuestionID: integer;
Question: shortstring;
Answer: shortstring;
procedure InitQuestion(anID:integer; aQ, anA:shortstring);
end;
TQuestionArray = array of TQuestion;
Any help solving this problem would be greatly appreciated.
You're missing a few things. You've declared a procedure to help initialize a new question - you should be using it.
This should get you going:
type
TQuestion = record
QuestionID: integer;
Question: ShortString;
Answer: ShortString;
procedure InitQuestion(anID: Integer; aQ, aAns: ShortString);
end;
TQuestionArray = array of TQuestion;
var
Form3: TForm3;
var
Questions: TQuestionArray;
procedure TForm7.AddNewQuestionClick(Sender: TObject);
begin
SetLength(Questions, Length(Questions) + 1);
Questions[High(Questions)].InitQuestion(GetNextQuestionID,
NewQuestDesc.Text,
NewQuestAns.Text);
end;
If you really want to do it individually setting the fields:
procedure TForm7.AddNewQuestionClick(Sender: TObject);
var
Idx: Integer;
begin
SetLength(Questions, Length(Questions) + 1);
Idx := High(Questions);
Questions[Idx].QuestionID := GetNextQuestionID;
Questions[Idx].Question := NewQuestDesc.Text;
Questions[Idx].Answer := NewQuestAns.Text;
end;

Pascal multiple records being passed into a function

This is my code:
type
TStudent = record
Firstname:string[15];
Surname:string[15];
dateofbirth:tdatetime;
gender: char;
ASmark: integer;
end;
var student: array [1..10] of tstudent;
option:integer;
...
function readrecord:tstudent;
var //dob:string;
i:integer;
begin
for i := 1 to 10 do
begin
Writeln('Enter Firstname for student ',i, ' : ');
readln(student[i].firstname);
Writeln('Enter Surname ',i, ' : ');
readln(student[i].Surname);
writeln('Enter Date of Birth ',i, ' : ');
//readln(dob);
//student[i].dateofbirth:=strtodate(dob);
Writeln('Enter Gender (M or F) ',i, ' : ');
readln(student[i].gender);
Writeln('Enter AS Mark ',i, ' : ');
readln(student[i].ASmark);
end;
end;
DOB is commented out for now, don't worry about that :)
procedure averagemark(var student:tstudent);
var mark:real;i:integer;
begin
mark:=0;
for i := 1 to 10 do
begin
mark:=mark+(student[i].asmark);
end;
mark:=(mark/10);
writeln('Average mark: ',mark:5:2);
end;
I am trying to get an average of the asmark, but I get errors for mark:=mark+(student[i].asmark); which are Error: no default property available and Fatal: Syntax error,")" expected but "[" found.
It would be much appreciated if someone could point me in the right direction as I have tried quite a lot of things and also researched.
I also created a data type called tstudenta which was an array of the tstudent record, then set student:tstudentr; but had no luck here either.
procedure averagemark(var student: tstudent);
You pass a single record here instead of an array. Use an open array:
procedure averagemark(const students: array of tstudent);
Loop from low(students) to high(students) rather than hard coding the array bounds.
If your Pascal dialect does not support open arrays, then you should use an array. If it suffices to use an array with a fixed length of 10 then you could define the array type like so:
type
TStudentArray = array [1..10] of TStudent;
You'd then use that type for the parameter of your procedure:
procedure averagemark(const students: TStudentArray);
It's a little tricky to be specific without more knowledge of your particular Pascal dialect. However, the essence is as I have said. You need to pass an array of records rather than a single record.

FreePascal adding elements on binaryTree

So im trying to add all 'spent' data, belonging to specific client number, on a binary tree.
Type
pointer_tree = ^bTree;
bTree = record
nclient: integer;
spent: integer;
big, small: pointer_tree
end;
{adder is 0}
function add (pT: pointer_tree; client_number: integer; adder: integer): integer;
begin
if pT <> nil then begin
if pT^.nclient = client_number then
adder:= pT^.spent + adder
add(pT^.big,client_number,adder);
add(pT^.small,client_number,adder);
end;
add:= adder;
end;
Function add will not return the added elements and will return a random number instead. Also is there a better way to add them all up?
I don't like the way that you're using the variable 'adder' as both a parameter to the function and also as a temporary store for the calculated value. I think it would be better if the function were written as follows, without the 'adder' variable:
function add (pT: pointer_tree; client_number: integer): integer;
begin
result:= 0;
if pT <> nil then
begin
if pT^.nclient = client_number then result:= pT^.spent;
inc (result, add (pT^.big, client_number));
inc (result, add (pT^.small, client_number));
end;
end;
Incidentally, your code is missing a semicolon after the 'adder:= pT^.spent + adder' line.

Resources