Archived

This topic is now archived and is closed to further replies.

ittirating through record fields

This topic is 5894 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

I have this situation where I would like to run through the fields of my record and set all the integer types to zero. At the moment I am doing the following type TStock = record wood : integer; stone : integer; grain : integer; end; == stock is type Tstock == stock.stone := 0; stock.grain := 0; etc There must be a more elegant way. The stock type is going to increase and there must be a way that I can run through an unknown amount of fields programmatically. I have tried searching on dejanews but I don''t even know the terminology for what I am trying to achieve so I just run into blind alleys. Can anyone point in me in the right direction with some pointers, code, terminology or URLs where I can get more info? help is much regarded.

Share on other sites
FillChar(Stock, SizeOf(TStock), 0);

EDIT:
(alternative)
var i: Integer;begin for i:= 0 to SizeOf(TStock) -1 do  Byte(Pointer(Integer(@Stock) + i)^):= 0;end;

[edited by - Lifepower on July 30, 2002 11:47:03 AM]

Share on other sites
sweet. Thats works nicely.

Just another question is there a way to tell what type each field is? i.e. say that Tstock was

type TStock = record
grain : integer;
flour : integer;
NameofBuilding : string;

What would I need to do if I only wanted to do some operation with the integers but I want to leave the string(s) alone? Can that be done? If so how? I had a play around with the code that LifePower provided but I couldn't get it to stop reseting NameOfBuilding.

==============

Coupled with this is the question is it possible to return the name of the field?

For example if I do the following,

for i:= 0 to SizeOf(TStock) -1 do

I would like to grab the name/label of each field. Then it would be possible for me to print on the screen the contents of the fields without having to know the name of each field. i.e.

The current stock contained in the "nameofBuilding" is
Current "grain" is "0"
Current "gold" is "20"

where the ".." is taken from the record.

I hope this doesn't sound too confusing, its just that an answer to question has a tendency to generate more questions

Ralph

[edited by - czar on July 30, 2002 6:01:28 PM]

Share on other sites
No such luck for when you add strings, dynamic arrays, or interfaces. Those are all referanced counted, and zeroing a reference in such a manner defeats the reference counting used by Delphi.

The only way to do the last part is to use RTTI for properties. To use RTTI you have toinclude the typinfo unit (helper routines to maniuplate properties). Make sure you add the Compiler directive {\$TYPEINFO ON} before the class declaration.

Use "Function GetPropvalue(Instance : Tobject; const PropName : string; PreferStrings : boolean) : Variant"
Call this with PreferStrings as true(sets & enums get returned as strings), and assign the variant to a string variable to force its contents to be converted into a string.
There is also "Procedure SetPropValue(Instance : Tobject; const PropName : string; const value: Variant);"
Note: At runtime you can change the boolean Identifiers & the dot sperator (ie 1.5 -one point five).

To itterate through the list of properties you need to use
GetPropList or GetPropInfos;
In this example I will use option b).

    Type  TProperty = record   Name : string;   Value : string;   Kind : TTypeKind;   end;  TPropArray = array of TProperty;Function GetProperties(Instance : Tobject;                       AKinds : TTypeKinds = [tkString]) : TPropArray;var  count,RealCount,Index : Integer;  p : PPropList;  PropInfo : PPropInfo;beginif (Instance = nil) or (Instance.ClassInfo = nil) then exit;Count := GetTypeData(Instance.ClassInfo)^.PropCount;if count = 0 then exit;setLength(Result,count);GetMem(p,Count * sizeof(pointer));try  GetPropInfos(Instance.ClassInfo,p);  RealCount :=  0;  For Index := pred(count) downto 0 do    begin    PropInfo := p^[index];    If PropInfo^.PropType^.Kind in AKinds then      begin      Result[RealCount].Name := PropInfo^.Name;      Result[RealCount].Kind := PropInfo^.PropType^.Kind;      Result[RealCount].Value := GetPropvalue(Instance,Result[RealCount].Name,true);      inc(RealCount);      end;    end;  SetLength(Result,RealCount);finally  FreeMem(p);end;end; {GetProperties}Procedure SetProperties(Instance : Tobject;const values : TPropArray);var  Index : integer;beginif (Instance <> nil) and (values <> nil) thenFor Index := High(values) downto 0 do  SetPropValue(Instance,values[index].name,values[index].value);end; {SetProperties}

That _should_ work. I'm using a dynamic array as they are a much nicer way to wok with dynamic memory than manually allocated & deallocated arrays.

[edited by - ggs on July 31, 2002 2:26:17 AM]

1. 1
2. 2
3. 3
frob
20
4. 4
Rutin
19
5. 5

• 32
• 13
• 10
• 11
• 9
• Forum Statistics

• Total Topics
632558
• Total Posts
3007075

×