PDA

Ver la Versión Completa : Recorrer Array de variables...


geolife
22-01-2014, 23:01:39
Hola Amigos!

Estoy atascado con un asunto. ¿Es posible crear un Array de variables predefinidas de un tipo X?, lo intento ilustrar.

Por ejemplo tenemos 7 variables del mismo tipo:

Var

a,b,c,d,e,f,g: Word;


¿Habría alguna forma de crear un vector que contenga las 7 variables? para posteriormente hacer asignaciones en masa a las mismas con un For .. To, en vez de llevarlo a cabo de forma separada: a:= 1; b:= 2; c:= 3; d := 4,....

Muchas gracias! :confused:

Caminante
22-01-2014, 23:18:23
Algo asi???

Var
i:integer;
MyArray:Array[1..7]of word;
begin
for i:=1 to 7 do
MyArray[i]:=i;
end;

Espero te sirva.

Saludos

geolife
22-01-2014, 23:27:31
Gracias Caminante!

Pero no era esto lo que quería ilustrar, quizás no lo explique demasiado bien... Se trataría de crear un vector o array que contenga a las variables (a,b,c,d,e,f,g) y luego mediante un bucle recorrerlas desde el inicio al final para asignarles un valor determinado.

No se trataría de crear una variable Miarray de 7 enteros, sino una variable de array que contenga 7 variables independientes y ya predefinidas...Imagina que tienes un programa con 50 variables de un mismo tipo con "nombres diferentes" y deseas iniciarlas de un tirón mediante un bucle...: Confused:

Algo asi???

Var
i:integer;
MyArray:Array[1..7]of word;
begin
for i:=1 to 7 do
MyArray[i]:=i;
end;

Espero te sirva.

Saludos

ecfisa
22-01-2014, 23:47:00
...
Se trataría de crear un vector o array que contenga a las variables (a,b,c,d,e,f,g) y luego mediante un bucle recorrerlas desde el inicio al final para asignarles un valor determinado.
...

Hola geolife.

Sin dudas lo que mencionas se soluciona usando un arreglo de punteros a Word, pero el trabajo de asignar a cada posición del arreglo la variable respectiva, se equipara al trabajo de inicializarlas una a una...

Una opción que podría reducir un poco la tarea podría ser:

procedure InitVar(VecWord: array of PWord; const Values: array of Word);
var
i: Integer;
begin
for i := Low(VecWord) to High(VecWord) do
VecWord[i]^ := Values[i];
end;


Ejemplo de uso:

var
a,b,c,d,e,f,g: Word;
begin
InitVar([@a,@b,@c,@d,@e,@f,@g], [300, 101, 502, 203, 904, 705, 406]);
...


Saludos :)

ecfisa
23-01-2014, 12:22:36
Hola geolife.

¿Se podría hacer esto creando una clase con objetos tipo variable y luego recorrer todos los objetos de la clase de inicio a fin?
Si claro. Se complica un poco debido a que el compilador convierte los nombres de variables en direcciones de memoria, por lo que no es posible acceder a ellas por su nombre en tiempo de ejecución.

Aunque se podría hacer con TList o TObjectList] usando un puntero a [I]record, pero me parece mas simple usar TStrings ya que podemos aprovechar sus propiedades vectoriales String y Objects para almacenar el nombre de variable y el valor respectivamente.

Como para darte una pauta, te pongo un ejemplo no muy pulido aunque operativo :

unit Unit2;

interface

uses Classes, SysUtils;

type
TListDT = class(TStringList)
public
procedure InitList(VecArray: array of string; const InitValue: TDateTime);
function GetVarValue(const VarName: string): TDateTime;
procedure ChangeVarValue(const VarName: string; Value: TDateTime);
end;

implementation

type
TCDateTime = class(TObject)
Value : TDateTime;
end;

procedure TListDT.InitList(VecArray: array of string; const InitValue: TDateTime);
var
i: Integer;
dt: TCDateTime;
begin
if not Assigned(Self) then
raise Exception.Create('La lista aún no fue creada.');
Clear;
for i:= Low(VecArray) to High(VecArray) do
begin
dt := TCDateTime.Create;
dt.Value := InitValue;
AddObject(VecArray[i], TObject(dt));
end;
end;

function TListDT.GetVarValue(const VarName: string): TDateTime;
var
ix: Integer;
begin
if not Assigned(Self) then
raise Exception.Create('La lista aún no fue creada.');
ix := IndexOf(VarName);
if ix = -1 then
raise Exception.Create('Nombre de variable inexistente.');
Result := TCDateTime(Objects[ix]).Value;
end;

procedure TListDT.ChangeVarValue(const VarName: string; Value: TDateTime);
var
ix: Integer;
dt: TCDateTime;
begin
if not Assigned(Self) then
raise Exception.Create('La lista aún no fue creada.');
ix := IndexOf(VarName);
if ix = -1 then
raise Exception.Create('Nombre de variable inexistente.');
dt := TCDateTime.Create;
dt.Value := Value;
Objects[ix] := TObject(dt);
end;
end.


Ejemplo de uso:

...
type
TForm1 = class(TForm)
btnShowAll: TButton;
ListBox1: TListBox;
btnShowtByName: TButton;
Edit1: TEdit;
btnChangeValue: TButton;
procedure FormCreate(Sender: TObject);
procedure btnShowAllClick(Sender: TObject);
procedure btnShowtByNameClick(Sender: TObject);
procedure btnChangeValueClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
public
end;

var
Form1: TForm1;

implementation {$R *.dfm}

uses Unit2;

var
List: TListDT;

procedure TForm1.FormCreate(Sender: TObject);
begin
List:= TListDT.Create;
List.InitList(['fec1','fec2','fec3','fec4','fec5'], // ,'fec6',...'fecN'],
StrToDate('01/01/2014'));
end;

procedure TForm1.btnShowAllClick(Sender: TObject);
var
i: Integer;
begin
ListBox1.Clear;
for i:= 0 to List.Count-1 do
ListBox1.Items.Add(Format('%s = %s',
[List[i],DateTimeToStr(List.GetVarValue(List[i]))]));
end;

procedure TForm1.btnShowtByNameClick(Sender: TObject);
begin
ShowMessage(Format('%s = %s',
[Edit1.Text, DateTimeToStr(List.GetVarValue(Edit1.Text))]));
end;

procedure TForm1.btnChangeValueClick(Sender: TObject);
begin
List.ChangeVarValue(Edit1.Text, StrToDate('31/12/2015'));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
List.Free;
end;
end.


Saludos :)

geolife
23-01-2014, 13:18:03
Nota: A la pregunta de si la implementación se podía llevar cabo mediante programación a través de objetos, de forma que recorriéramos una lista de variables en memoria para su inicialización y/o asignación, evitando hacerlo con un esquema "una a una". Se elimino por accidente la pregunta en el hilo anterior!

Apreciado ecfisa!

Que puedo decirte,...:eek: esto es una muestra de amor a la programación. Voy probar tu esquema.
Muchísimas gracias por tomarte la molestia de ofrecer esta gran porción de código y una solución al problema planteado.
Es un verdadero y encomiable regalo el tiempo que dedicáis en Clubdelphi a las personas que estamos aprendiendo.

Muchas gracias de nuevo! :):):)


Hola geolife.

Si claro. Se complica un poco debido a que el compilador convierte los nombres de variables en direcciones de memoria, por lo que no es posible acceder a ellas por su nombre en tiempo de ejecución.

Aunque se podría hacer con TList o TObjectList] usando un puntero a [I]record, pero me parece mas simple usar TStrings ya que podemos aprovechar sus propiedades vectoriales String y Objects para almacenar el nombre de variable y el valor respectivamente.

Como para darte una pauta, te pongo un ejemplo no muy pulido aunque operativo :

Saludos :)

nlsgarcia
24-01-2014, 06:30:11
ecfisa,

^\||/ :)

Nelson.