Gamba
asked on
Save dfifferent variable-types on stack?
Is there any way to save different types
of variables (objects of various size, integer, doubles,
strings)
on a stack, like this:
var stack : array[..MAXSTACKSIZE] of pointer;
procedure push(obj:pointer)
var newstackcontent:pointer;
begin
newstackcontent:=somekinde of_allocat emem(obj,g etsizeof(o bj));
somekindeof_copy(obj,newst ackcontent );
stack[stackptr]:=newstackc ontent;
inc(stackptr);
end;
and restore them:
procedure pop(var obj:pointer);
var stackcontent:pointer;
begin
stackcontent:=stack[stackp tr];
somekindeof_copy(stackcont ent,obj);
dec(stackptr);
somekindeof_freemem(stackc ontent);
end;
More specific:
Is there a general working way to implement
somekindeof_copy, somekindof_allocatemem and
somekindof_freemem without doing the
type conversions??
Thanks for help (implementations??),
Gamba
of variables (objects of various size, integer, doubles,
strings)
on a stack, like this:
var stack : array[..MAXSTACKSIZE] of pointer;
procedure push(obj:pointer)
var newstackcontent:pointer;
begin
newstackcontent:=somekinde
somekindeof_copy(obj,newst
stack[stackptr]:=newstackc
inc(stackptr);
end;
and restore them:
procedure pop(var obj:pointer);
var stackcontent:pointer;
begin
stackcontent:=stack[stackp
somekindeof_copy(stackcont
dec(stackptr);
somekindeof_freemem(stackc
end;
More specific:
Is there a general working way to implement
somekindeof_copy, somekindof_allocatemem and
somekindof_freemem without doing the
type conversions??
Thanks for help (implementations??),
Gamba
ASKER
This means, I would still have to know,
which element of the record I would have to allocate
(matrixstack[0] or matrixstack[1]).
So, I don't really need the matrix, I could also
use this:
case (obtype) of
0: new(FPointer);
1 :new(FInteger);
end;
My problem is, that I don't know objtype.
which element of the record I would have to allocate
(matrixstack[0] or matrixstack[1]).
So, I don't really need the matrix, I could also
use this:
case (obtype) of
0: new(FPointer);
1 :new(FInteger);
end;
My problem is, that I don't know objtype.
See contnrs.pas - standard Delphi containers
ASKER
Sorry, this file is not present in Delphi Standard...
try something like this (not tested):
type
PMyData = ^TMyData;
TMyData = record
case Kind: Byte of
0: (AsInteger: Integer);
1: (AsDouble: Double);
2: (AsString: ShortString);
end;
TMyDataStack = class
private
FList: TList;
public
constructor Create;
destructor Destroy; override;
function Count: Integer;
function Peek: TMyData;
function Pop: TMyData;
procedure Push(Value: Integer); overload;
procedure Push(Value: Double); overload;
procedure Push(Value: ShortString); overload;
end;
implementation
{ TMyDataStack }
constructor TMyDataStack.Create;
begin
inherited Create;
FList := TList.Create;
end;
destructor TMyDataStack.Destroy;
begin
FList.Free;
inherited Destroy;
end;
function TMyDataStack.Count: Integer;
begin
Result := FList.Count;
end;
function TMyDataStack.Peek: TMyData;
begin
Result := PMyData(FList[FList.Count - 1])^;
end;
function TMyDataStack.Pop: TMyData;
var
P: PMyData;
begin
P := FList[FList.Count - 1];
Result := P^;
FreeMem(P);
FList.Delete(FList.Count - 1);
end;
procedure TMyDataStack.Push(Value: Integer);
var
P: PMyData;
begin
P := AllocMem(SizeOf(TMyData));
try
P^.Kind := 0;
P^.AsInteger := Value;
FList.Add(P);
except
FreeMem(P);
raise;
end;
end;
procedure TMyDataStack.Push(Value: Double);
var
P: PMyData;
begin
P := AllocMem(SizeOf(TMyData));
try
P^.Kind := 1;
P^.AsDouble := Value;
FList.Add(P);
except
FreeMem(P);
raise;
end;
end;
procedure TMyDataStack.Push(Value: ShortString);
var
P: PMyData;
begin
P := AllocMem(SizeOf(TMyData));
try
P^.Kind := 2;
P^.AsString := Value;
FList.Add(P);
except
FreeMem(P);
raise;
end;
end;
HTH
TOndrej
type
PMyData = ^TMyData;
TMyData = record
case Kind: Byte of
0: (AsInteger: Integer);
1: (AsDouble: Double);
2: (AsString: ShortString);
end;
TMyDataStack = class
private
FList: TList;
public
constructor Create;
destructor Destroy; override;
function Count: Integer;
function Peek: TMyData;
function Pop: TMyData;
procedure Push(Value: Integer); overload;
procedure Push(Value: Double); overload;
procedure Push(Value: ShortString); overload;
end;
implementation
{ TMyDataStack }
constructor TMyDataStack.Create;
begin
inherited Create;
FList := TList.Create;
end;
destructor TMyDataStack.Destroy;
begin
FList.Free;
inherited Destroy;
end;
function TMyDataStack.Count: Integer;
begin
Result := FList.Count;
end;
function TMyDataStack.Peek: TMyData;
begin
Result := PMyData(FList[FList.Count - 1])^;
end;
function TMyDataStack.Pop: TMyData;
var
P: PMyData;
begin
P := FList[FList.Count - 1];
Result := P^;
FreeMem(P);
FList.Delete(FList.Count - 1);
end;
procedure TMyDataStack.Push(Value: Integer);
var
P: PMyData;
begin
P := AllocMem(SizeOf(TMyData));
try
P^.Kind := 0;
P^.AsInteger := Value;
FList.Add(P);
except
FreeMem(P);
raise;
end;
end;
procedure TMyDataStack.Push(Value: Double);
var
P: PMyData;
begin
P := AllocMem(SizeOf(TMyData));
try
P^.Kind := 1;
P^.AsDouble := Value;
FList.Add(P);
except
FreeMem(P);
raise;
end;
end;
procedure TMyDataStack.Push(Value: ShortString);
var
P: PMyData;
begin
P := AllocMem(SizeOf(TMyData));
try
P^.Kind := 2;
P^.AsString := Value;
FList.Add(P);
except
FreeMem(P);
raise;
end;
end;
HTH
TOndrej
Hi all,
there is Variant type that able to keep integer, string, double etc.
Here is a sample:
uses
..., contnrs, .... // contnrs unit shipped with all of Delphi (standard, prof, ent.)
type
TSomeData = class(TObject)
Data: Variant;
end;
TSomeStack = class(TObjectList)
procedure Push(AValue: Variant);
function Pop: Variant;
end;
.....
procedure TSomeStack.Push(AValue: Variant);
var
D: TSomeData;
begin
D := TSomeData.Create;
D.Data := AValue;
Add(D);
end;
function TSomeStack.Pop: Variant;
begin
if Count > 0 then
begin
Result := TSomeData(Items[Count-1]). Data;
Delete(Count-1);
end
else
raise Exception.Create('stack is empty');
end;
.....
var
Stack: TSomeStack;
S: String;
I: Integer;
Z: Double;
begin
Stack := TSomeStack.Create;
Stack.Push('12345');
Stack.Push(12345);
Stack.Push(123.45);
Z := Stack.Pop;
I := Stack.Pop;
S := Stack.Pop;
Stack.Free;
end;
----
Igor.
there is Variant type that able to keep integer, string, double etc.
Here is a sample:
uses
..., contnrs, .... // contnrs unit shipped with all of Delphi (standard, prof, ent.)
type
TSomeData = class(TObject)
Data: Variant;
end;
TSomeStack = class(TObjectList)
procedure Push(AValue: Variant);
function Pop: Variant;
end;
.....
procedure TSomeStack.Push(AValue: Variant);
var
D: TSomeData;
begin
D := TSomeData.Create;
D.Data := AValue;
Add(D);
end;
function TSomeStack.Pop: Variant;
begin
if Count > 0 then
begin
Result := TSomeData(Items[Count-1]).
Delete(Count-1);
end
else
raise Exception.Create('stack is empty');
end;
.....
var
Stack: TSomeStack;
S: String;
I: Integer;
Z: Double;
begin
Stack := TSomeStack.Create;
Stack.Push('12345');
Stack.Push(12345);
Stack.Push(123.45);
Z := Stack.Pop;
I := Stack.Pop;
S := Stack.Pop;
Stack.Free;
end;
----
Igor.
As long as you're dealing with object referenced, there is no need for "dirty" tricks. Then, it is always possible to "box" data types into objects, which then allows the use of IS and AS operators (just as with any other object type). If you don't want to use TObject descendands as carriers for simple data types (which is the most generic approach), stick to one of the other suggestions here.
procedure TForm1.Button6Click(Sender : TObject);
var
v:variant; //this is a great type.
i:integer;
b:boolean;
begin
v:=true;
i := v;
v := i+100;
i := v;
b := v;
if b then showmessage(IntToStr(i));
end;
var
v:variant; //this is a great type.
i:integer;
b:boolean;
begin
v:=true;
i := v;
v := i+100;
i := v;
b := v;
if b then showmessage(IntToStr(i));
end;
ASKER
So many comments! Thank you.
Sorry for late answering, but e-mail-notification in EE
seems not to work correct (I received 4 mails today).
I know the variant type, but the problem indeed is
- as AvonWyss says - to generate copies of objects,
which should have various size and many different
object types.
So I would need the mentioned functions:
somekindeof_copy(stackcont ent,obj);
and
somekindeof_freemem(stackc ontent);
to allocte memory, cause the copies should be modified
without modifying the original object.
Sorry for late answering, but e-mail-notification in EE
seems not to work correct (I received 4 mails today).
I know the variant type, but the problem indeed is
- as AvonWyss says - to generate copies of objects,
which should have various size and many different
object types.
So I would need the mentioned functions:
somekindeof_copy(stackcont
and
somekindeof_freemem(stackc
to allocte memory, cause the copies should be modified
without modifying the original object.
procedure TForm1.Button1Click(Sender : TObject);
var a,b : variant;
i,j:integer;
begin
i:=100;
a:=i;
i:=120;
j:=a;
showmessage( IntToStr (j) );
b:=a;
a:=i;
j:=b;
showmessage( IntToStr (j) );
j:=a;
showmessage( IntToStr (j) );
end;
so
function TSomeStack.Pop_copy: Variant;
begin
if Count > 0 then
begin
Result := TSomeData(Items[Count-1]). Data;
end
else
raise Exception.Create('stack is empty');
end;
object still exsists.
elaborate:
somekindeof_copy(stackcont ent : Integer??; obj: Pointer???);
var a,b : variant;
i,j:integer;
begin
i:=100;
a:=i;
i:=120;
j:=a;
showmessage( IntToStr (j) );
b:=a;
a:=i;
j:=b;
showmessage( IntToStr (j) );
j:=a;
showmessage( IntToStr (j) );
end;
so
function TSomeStack.Pop_copy: Variant;
begin
if Count > 0 then
begin
Result := TSomeData(Items[Count-1]).
end
else
raise Exception.Create('stack is empty');
end;
object still exsists.
elaborate:
somekindeof_copy(stackcont
ASKER
Sorry, God_Ares, could you explain this a little more?
What is TSomeData().Date.
What does this mean:
object still exsists.
elaborate:
somekindeof_copy(stackcont ent : Integer??; obj: Pointer???);
(maybe you could say this in simple words, my English
is not the very best...)
Thanks,
Gamba
What is TSomeData().Date.
What does this mean:
object still exsists.
elaborate:
somekindeof_copy(stackcont
(maybe you could say this in simple words, my English
is not the very best...)
Thanks,
Gamba
>Sorry, God_Ares, could you explain this a little more?
What is TSomeData().Date.
TSomeData(Items[Count-1]).
Cast a variable to an TSomeData TSomeData has a Data property of the type variant.
>What does this mean:
>object still exsists.
after using pop_copy there will be copy of the top item on the stack. The object on there will still exsist.
>elaborate:
>somekindeof_copy(stackcon
what parameters should be given to this function? what is it's goal?
Hope this is more understandable english for you.
Regards
...
ASKER
Thank you for explanation.
somekindof_copy should make a copy of an object
(this is stackcontent, the defintiion has an error;
it must be stackcontent:pointer, not integer)
and fill var obj:pointer with the adress of
the new object.
I'm not quite sure about
>> TSomeData(Items[Count-1]). Data
Will this work for objects or only for
numbers (int, double) and strings?
Gamba
somekindof_copy should make a copy of an object
(this is stackcontent, the defintiion has an error;
it must be stackcontent:pointer, not integer)
and fill var obj:pointer with the adress of
the new object.
I'm not quite sure about
>> TSomeData(Items[Count-1]).
Will this work for objects or only for
numbers (int, double) and strings?
Gamba
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Yes, but also like this:
type class1 = class
el1 : integer
el2 : string;
end;
type class2 = class
el1 : string;
el2 : word;
el3 : double;
end;
procedure DoSomething;
var cl1:class1;
cl2:class2;
begin
cl1 = new class1;
cl1.el1 := 3;
cl1.el2 := 'string1';
cl2.el1 := 'string2;
cl2.el2 := 12345;
push(cl1);
x:=somekindofcopy(1);
ShowMessage('el1 = ' + inttostr(x.el1));
ShowMessage('el2 = ' + x.el2);
pop(cl1);
push(cl2);
y:=somekindofcopy(1);
ShowMessage('el1 = ' + y.el1);
ShowMessage('el2 = ' + inttostr(y.el2));
ShowMessage('el3 = ' + floattostr(y.el3));
pop(cl2);
end;
??
Gamba
type class1 = class
el1 : integer
el2 : string;
end;
type class2 = class
el1 : string;
el2 : word;
el3 : double;
end;
procedure DoSomething;
var cl1:class1;
cl2:class2;
begin
cl1 = new class1;
cl1.el1 := 3;
cl1.el2 := 'string1';
cl2.el1 := 'string2;
cl2.el2 := 12345;
push(cl1);
x:=somekindofcopy(1);
ShowMessage('el1 = ' + inttostr(x.el1));
ShowMessage('el2 = ' + x.el2);
pop(cl1);
push(cl2);
y:=somekindofcopy(1);
ShowMessage('el1 = ' + y.el1);
ShowMessage('el2 = ' + inttostr(y.el2));
ShowMessage('el3 = ' + floattostr(y.el3));
pop(cl2);
end;
??
Gamba
ASKER
Are there no further comments?
Would it be o.k. for you, if I
would let delete this question?
Gamba
Would it be o.k. for you, if I
would let delete this question?
Gamba
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:
Accept answer from God_Ares
Please leave any comments here within the next seven days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
Paul (pnh73)
EE Cleanup Volunteer
I will leave a recommendation in the Cleanup topic area that this question is:
Accept answer from God_Ares
Please leave any comments here within the next seven days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
Paul (pnh73)
EE Cleanup Volunteer
type
TMatrix = RMatrix ;
Rmatrix = Record
FPointer : Pointer ;
FInteger : Integer ;
FString : Pointer ;
FStringList : TStringList ;
end;
var
MatrixStack = array [0..TMSLeanght]of TMatrix ;
1. you have to allocate memory of some TMatrixStack you will use like
new( matrixstack[0] );
new( matrixstack[1] );