Variants - czemu a?ż 16KB?

0

Trochę mnie irytuje wielkość zmiennych typu Variant. Rozumiem, że to musi być wiele typów, ale 16 kb to przesada (wyobraźcie sobie coś takiego: array[1..10000] of Variant - ile trzeba by było pamięci RAM? 1024MB? Może troszkę więcej? :)). Nie zna ktoś sposobu, żeby zrobić varianta mogącego zawierać TYLKO wartości string, real i boolean - chyba zajmowałby CIUT mniej. A coś takiego jest mi potrzebne do systemu zmiennych wewnętrznych - coś, co jest często używane przez enginy do gier. Już to prawie skończyłem, ale jest trochę "łopatologicznie" zrobione. Jak ktoś chce, oto kodzik:

[code]unit Variables;

interface

uses SysUtils;

type
EVarType = (evtString, evtNumeric, evtBool);

EngineVariable = record
VarName: string;
StringContent: string;
NumericContent: real;
BoolContent: boolean;
VarType: EVarType;
end;

function AddVar(VarName, VarContent: string; VarType: EVarType): boolean;
function DelVar(VarName: string; Rebuild: boolean = true): boolean;
function GetVarName(VarIndex: integer): string;
function GetVarIndex(VarName: string): integer;
function SetVar(VarName, NewContent: string; NewType: EVarType; CreateIfNotEx: boolean = true): boolean;
procedure RebuildVarArray;

var engineVariables: array of EngineVariable;

implementation

function AddVar(VarName, VarContent: string; VarType: EVarType): boolean;
begin
Result:=false;
if GetVarIndex(VarName)>-1 then Exit;
Result:=true;
SetLength(engineVariables,Length(engineVariables)+1);
engineVariables[Length(engineVariables)-1].VarName:=VarName;

engineVariables[Length(engineVariables)-1].VarType:=VarType;
case VarType of
evtString:engineVariables[Length(engineVariables)-1].StringContent:=VarContent;
evtNumeric:engineVariables[Length(engineVariables)-1].NumericContent:=StrToFloat(VarContent);
evtBool:engineVariables[Length(engineVariables)-1].BoolContent:=StrToBool(VarContent);
end;
end;

function DelVar(VarName: string; Rebuild: boolean = true): boolean;
var varIndex: integer;
begin
Result:=false;
varIndex:=GetVarIndex(VarName);
if varIndex=-1 then Exit;
Result:=true;
engineVariables[varIndex].VarName:='';
if Rebuild then RebuildVarArray;
end;

function SetVar(VarName, NewContent: string; NewType: EVarType; CreateIfNotEx: boolean = true): boolean;
begin
Result:=false;
if GetVarIndex(VarName)=-1 then
if CreateIfNotEx then
Result:=AddVar(VarName,NewContent,NewType)
else
Exit;
engineVariables[GetVarIndex(VarName)].VarType:=NewType;
case NewType of
evtString:engineVariables[GetVarIndex(VarName)].StringContent:=NewContent;
evtNumeric:engineVariables[GetVarIndex(VarName)].NumericContent:=StrToFloat(NewContent);
evtBool:engineVariables[GetVarIndex(VarName)].BoolContent:=StrToBool(NewContent);
end;
Result:=true;

end;

function GetVarIndex(VarName: string): integer;
var j: integer;
begin
Result:=-1;
if Length(engineVariables)=1 then
begin
if Uppercase(engineVariables[0].VarName)=Uppercase(VarName) then Result:=0;
Exit;
end;
for j:=0 to High(engineVariables) do
begin
if Uppercase(engineVariables[j].VarName)=Uppercase(VarName) then Result:=j;
end;
end;

function GetVarName(VarIndex: integer): string;
begin
Result:='';
if VarIndex>High(engineVariables) then Exit;
Result:=engineVariables[VarIndex].VarName;
end;

procedure RebuildVarArray;
var tmpTable: array of EngineVariable;
j: integer;
begin
for j:=0 to High(engineVariables) do
begin
if engineVariables[j].VarName='' then continue;
SetLength(tmpTable,Length(tmpTable)+1);
tmpTable[High(tmpTable)].VarName:=engineVariables[j].VarName;
tmpTable[High(tmpTable)].VarType:=engineVariables[j].VarType;
tmpTable[High(tmpTable)].StringContent:=engineVariables[j].StringContent;
tmpTable[High(tmpTable)].NumericContent:=engineVariables[j].NumericContent;
tmpTable[High(tmpTable)].BoolContent:=engineVariables[j].BoolContent;
end;
SetLength(engineVariables,Length(tmpTable));
engineVariables:=tmpTable; //tu coś nie idzie, nie wiem czemu
end;

end.[/code]

z wariantami wyszłoby znacznie lepiej, ale przy kilkudziesięciu zmiennych program by się wysypał. No i przy przebudowie tablicy coś jest nie tak. Mam nadzieję, że ten kod komuś pomoże, starałem się, żeby był jaknajczytelniejszy.

Żeby nie zaśmiecać forum, zadam tu też jeszcze jedno pytanko: jak zmusić zmienną typu Extended, żeby się wyświetlała w całości, nie w wykładniku, po konwersji do stringa? W końcu po co wykładnik przy szóstym miejscu po przecinku. Przy setnym - to rozumiem, ale szóste mogłoby wyświetlić. (jest mi to potrzebne żeby nieco poprawić program do kalkulowania oporu rezystorów na podst. kolorowych paseczków. [Chodziaż po cholerę wyświetlać wartości np. czteroomowe w megaomach, ale cóż...] Jakby komuś był taki program potrzebny, niech napisze, chętnie wyślę razem ze źródłem.)

PS. Skąd wziąć źródła modułu SysUtils? Nie są mi potrzebne wszystkie funkcje, tylko kilka, a zależy mi na tym, żeby robić małe objętościowo programy (WinAPI rządzi, won z VCL!).

0

Trochę mnie irytuje wielkość zmiennych typu Variant. Rozumiem, że to musi być wiele typów, ale 16 kb to przesada

Coś pomyliłeś:
A variant occupies 16 bytes of memory and consists of a type code and a value, or pointer to a value, of the type specified by the code. (Delphi help)
Gdzie kilo?

jak zmusić zmienną typu Extended, żeby się wyświetlała w całości, nie w wykładniku, po konwersji do stringa?

var
a: extended;
begin
a:=1/(12345);
Edit1.Text:=FloatToStr(a); // 8.10044552450385E-5
Edit2.Text:=Format('%1.18f',[a]); // 0.000081004455245038
end;

PS. Skąd wziąć źródła modułu SysUtils?

O ile wiem, nie-Personal wersje Delphi zawierają źródła całego VCL

0

A może record z sekcją case?? (patrz kurs na mojej stronie).

0

SysUtils - jedyne 392 KB :)

0

Qrczę, co za bzdury napisałem. Ale i tak nawet 16 BAJTÓW to lekka przesada. (I proszę o wyrozumiałość, posałem to o 23:20 po całym dniu odrabiania zaległych zadań domowych :)).

O ile wiem, nie-Personal wersje Delphi zawierają źródła całego VCL

Hehehehe, ja mam personal. Możesz mi to podesłać? (W razie czego - napisałem sam w notatniku, w nocy, jak lunatykowałem ;-))

Vogel -> w rekordzie można umieścić kod? Nie chcę tego robić na obiektach, są zbyt toporne i powolne, ale reordy mogą chyba tylko przechowywać. (wiem że rekord to rodzaj obiektu, ale na tyle okrojony że szybko działa).

0

Nie kod. Po prostu rekord z sekcją case to znana z C unia.
Patrz:

type
TPunkt = record
X, Y: Word
end;
TRodzajFigury = (rfKolo, rfElipsa, rfTrojkat, rfProstokat);
TFigura = record
case Rodzaj: TRodzajFigury of
rfKolo: (
r: Real;
S: TPunkt
);
rfElipsa: (
r1, r2: Real;
F1, F2: TPunkt
);
rfTrojkat, rfProstokat: (
a, b, c: Real
)
end;

Opis dokładniejszy na mojej stronce.

1 użytkowników online, w tym zalogowanych: 0, gości: 1