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!).