Pascal multiple records being passed into a function - pascal

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.

Related

Functions and procedures that call other functions and procedures

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.

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;

Array not working correctly

I have a function that takes in 1 parameter, abc(parameter1 IN varchar2)
In the parameter I will be taking in a string that is comma delimited:
E.g Abc('1,2,a')
Type vartype is varray(10) of varchar2(50);
X1 vartype:= vartype (parameter1);
For X in X1.count loop
Dbms_output.put_line(x1(X));
End loop;
The DBMS Output gives me
1,2,a
Instead of
1
2
A
Is there anyway I can solve this?
For my understanding your function parameter will be single value.
If you are mentioned varray, you should give format like ('1','2','a','b')
For example :-
declare
Type vartype is varray(10) of varchar2(50);
X1 vartype:=vartype ('1','2','a','b');
begin
For X in 1..X1.count loop
Dbms_output.put_line(x1(x));
End loop;
end;
/
Above query will help you to understand concepts of Varray
You are passing a varchar2 variable to the varray and it's considered the first paramter; so your array contains only one element (the content of parameter1). You must split the string into substring before passing to the varray.
Here is an extract from Oracle documentation
DECLARE TYPE ProjectList IS VARRAY(50) OF VARCHAR2(16);
accounting_projects ProjectList;
BEGIN
accounting_projects := ProjectList('Expense Report', 'Outsourcing', 'Auditing');
END;
For splitting a string into substring you can check some solutions here

Why while loop in plsql not working?

Noob question, why this:
CREATE OR REPLACE FUNCTION Get_tipo_aula ( nm IN VARCHAR2, n IN NUMBER)
RETURN VARCHAR2
IS
type array_t is varray(3) of varchar2(11);
array array_t := array_t('Conferenze','Laboratorio','Aula');
Aula varchar2(11);
i NUMBER;
BEGIN
i:=1;
SELECT tipo_modulo
INTO Aula
FROM Modulo
WHERE Nome_modulo = nm;
--
WHILE Aula <> array_t(i)
LOOP
i := i+1;
END LOOP;
RETURN array_t(1 + mod(i+n-1,3));
END;
/
is giving me those errors :
15/1 PL/SQL: Statement ignored
15/12 PLS-00306: wrong number or types of arguments in call to '!='
19/1 PL/SQL: Statement ignored
19/8 PLS-00382: expression is of wrong type
knowing that the first select has the purpouse of loading into aula a string of the same value of the array above ? My desired result is to obtain from the while the index of first occurrence in the array of the string contained in Aula and then return the value of the array shifted of some position.
Ex :
input value ... , 2
selection result Aula
Expected result of the while : i = 3
Expected returned value : array_t(1+mod(3+2-1,3)) = array_t(2) = 'Laboratorio')
I don't know what kind of syntax mistake I'm doing honestly.
It's a simple typo. You need to use the variable name in your code, not the type. So, correct these two lines ...
WHILE Aula <> array(i)
....
RETURN array(1 + mod(i+n-1,3));
... and your code will compile.
By the way, array is a really poor name for a variable because it is so easy to confuse with a data type. Even with toy code it pays to use clear names. Even l_array would be an improvement.

read() strings of variable length

I've got rows of two values (input from console) that look likes this:
David 89000
Peter 99500
Jim 23999
END 1
is there a way to save the string and number into a variable other than to loop-read a char when you don't know the string length?
str:=''; salary:=0; i:=1;
while str<> 'END' do
begin
str:=''; salary:=0;
read(ch);
while ch <> ' ' do
begin
str:=str+ch;
read(ch);
end;
read(salary);
array[i].name:=str;
array[i].salary:=salary;
i:=i+1;
readln;
end;
You can do it with a single call to ReadLn and then parse the input yourself:
var
TextIn: string;
Person: string;
Salary: Integer;
begin
while true do
begin
ReadLn(TextIn); // Requires user to hit Enter
if Copy(TextIn, 1, 3) <> 'END' then
begin
Person := Copy(TextIn, 1, Pos(' ', TextIn) - 1);
Salary := StrToInt(Copy(TextIn, Pos(' ', TextIn) + 1, 255);
end
else
Exit;
end;
end;
I didn't include any error checking (which should be there), because your original code doesn't have any either.
Not with standard I/O functions. Of course you can put that code in a separate procedure, or split with tstringlist.

Resources