[fpc-pascal] sorting and merging array of records

Sven Barth pascaldragon at googlemail.com
Wed Jan 11 17:11:29 CET 2012


Am 11.01.2012 09:27, schrieb waldo kitty:
> On 1/10/2012 16:41, Sven Barth wrote:
>> On 10.01.2012 22:02, waldo kitty wrote:
>>> TList? hummm... better? smaller? faster? easier to use? small memory
>>> footprint? i'm game to try things as long as it works in the end ;)
>>
>> TList is basically an array wrapped in a class (though I would suggest
>> TFPList
>> as that is faster than TList (TList is based on TFPList)). Both can be
>> found in
>> unit Classes.
>>
>> The following you need to know: T(FP)List works on pointers, thus you
>> need to
>> 1. declare a pointer type to your record type (e.g. Pthree_line_data =
>> ^three_line_data)
>> 2. allocate a Pthree_line_data variable if you want to add a new entry
>> to the list
>
> i tried this but could only get so far and then not further so i backed
> up and punted the ball... now i'm trying this with a sortedcollection
> and while i can apparently insert items, i haven't figured out how to
> access them and print their contents... unless their contents are
> garbage like the following prints out...

You know that you're handling with pointer here as well? ;)

I never used TP's T(Sorted)Collection, so the following are mostly 
guesses, but I'll try.

Here is how you should (in my opinion) access an item at index Idx in 
the list:

var
   rec: PTLERec;
begin
   ...
   rec := PTLERec(aTLECollection^.At(Idx));
   // You can now access the record's contents by dereferencing:
   if rec^.catnbr > ... then
   ...
end;

> function TTLECollection.Compare(key1, key2: pointer): longint;
> begin
> if PTLERec(key1)^.catnbr = PTLERec(key2)^.catnbr then
> compare := 0
> else if PTLERec(key1)^.catnbr < PTLERec(key2)^.catnbr then
> compare := -1
> else
> compare := 1;
> end;

You declared TTLERec.catnbr as a string, so you can't use "<" or ">" for 
comparison. You'd need to convert it to a ordinal type first.

> Function Input_Satellite_List(var aInputFile: TextFile) : word;
>
> var
> data : PTLERec;
> sat_cnt : word;
> i,x : longint;
>
> begin
> sat_cnt := 0;
> while not EOF(aInputFile) do
> begin
> new(data);
> Readln(aInputFile,data^.satname);
> Readln(aInputFile,data^.satdata[1]);
> Readln(aInputFile,data^.satdata[2]);
> data^.catnbr := Copy(data^.satdata[1],3,5);
> data^.epoch := Real_Value(data^.satdata[1],19,14);
> inc(sat_cnt);
> aTLECollection^.insert(data);
> dispose(data);

Don't do this! You'll free the memory you allocated for your record. The 
collection will only contain a pointer to this data! (Many of the rules 
I mentioned for T(FP)List apply here as well)

> {$IFDEF DEBUG}
> writeln(PTLERec(aTLECollection)^.satname);
> writeln(PTLERec(aTLECollection)^.satdata[1]);
> writeln(PTLERec(aTLECollection)^.satdata[2]);
> writeln(PTLERec(aTLECollection)^.catnbr);
> writeln(PTLERec(aTLECollection)^.epoch);
> {$ENDIF}

Ehm... you know that it can't work if you cast a TTLECollection pointer 
to a TTLERec pointer? These are two different structures. No wonder why 
you only see garbage as you most likely see the contents of the 
Collection (which consists mostly of pointers). See at the top of the 
mail how you'd access the contents correctly. Normally I'd suggest you 
to simply guery the "Count - 1"th item, but in this exact case you'd 
need to search the item again as you're using a sorting list and the 
last inserted item might not be at the last position of the list (as 
Insert maintains the order of the list).

Regards,
Sven



More information about the fpc-pascal mailing list