Searching for a Corresponding Value in a TList Delphi7 - delphi-7

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;

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.

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.

Extend table of varchar with a varchar

I'm trying to create a table of varchar array like this:
DECLARE
lna_poi_list fls_number_table := fls_number_table();
lsa_poi_list fls_varchar_table := fls_varchar_table();
ls_poi_list varchar;
BEGIN
FOR i IN 1..lna_poi_list.COUNT
LOOP
ls_poi_list := calling a function that returns a varchar and takes
lna_poi_list(i) as param;
lsa_poi_list.extend(ls_poi_list);
END LOOP
END;
After this I just want to return lsa_poi_list array but I'm getting some
character to number conversion error
Any ideas is much appreaciated
As documented, extend takes optional numeric arguments:
The EXTEND method has these forms:
EXTEND appends one null element to the collection.
EXTEND(n) appends n null elements to the collection.
EXTEND(n,i) appends n copies of the ith element to the collection.
To assign a new element, extend the collection, and then assign the value:
lsa_poi_list.extend;
lsa_poi_list(lsa_poi_list.COUNT) := ls_poi_list;
Referencing count means you're populating the last (new, null) element in the array.
If you're always adding one varhar (varchar2?) element for each element in the number array, you can size it once before the loop instead, which would be slightly more efficient, e.g:
DECLARE
lna_poi_list sys.odcinumberlist := sys.odcinumberlist();
lsa_poi_list sys.odcivarchar2list := sys.odcivarchar2list();
ls_poi_list varchar2(10);
BEGIN
lna_poi_list.extend(3);
lsa_poi_list.extend(lna_poi_list.COUNT);
FOR i IN 1..lna_poi_list.COUNT
LOOP
ls_poi_list := 'x'; -- from some function
lsa_poi_list(i) := ls_poi_list;
END LOOP;
END;
/
PL/SQL procedure successfully completed.

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