Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Paso de Array Dinamico a Procedimiento por Referencia. (https://www.clubdelphi.com/foros/showthread.php?t=61443)

eLYaN 07-11-2008 18:07:09

Paso de Array Dinamico a Procedimiento por Referencia.
 
Hola, tengo el siguiente problema y no encuentro solución:
Necesito pasar a un procedimiento un array dinamico y que este me lo devuelva relleno, para ello tengo un array dinamico de registros. El problema es que no se como devolver el array dinamico, dentro del procedure lo relleno bien y lo voy redimensionando pero no logro devolverlo :

Código Delphi [-]
Type TReg=Record
  X, Y: string;
end;

La llamada al procedimiento:

Código Delphi [-]
 
procedure TForm1.Button1Click(Sender: TObject);
var Reg: array of Treg;
begin
  SetLength(Reg, 0);  //0 registros
  MiProcedure(Reg);
  ShowMessage(Reg[0].x+', '+Reg[1].x);  //Aqui salta el error
end;

y el procedimiento seria:

Código Delphi [-]
Procedure TForm1.MiProcedure(var Reg: array of Treg);
var a: array of Treg;
begin
  a := Pointer(@reg);
  SetLength(a, 2);  //2 registros
  a[0].x := '0';
  a[1].x := '1';
end;

Mil Gracias.

droguerman 07-11-2008 18:41:31

Has pensado obviar el puntero, es decir trabajar directamente con la variable reg?

eLYaN 07-11-2008 22:29:56

El problema es que si no me equivoco esa variable es un puntero a la variable, no es la propia variable. Por tanto no puedo redimensionarla con SetLenght me da error de tipo Invalido. Con este codigo obtengo la variable la utilizo pero no se como devolversela al procedimiento que la pasa.

Gracias, de todas maneras.

eLYaN 07-11-2008 23:08:01

El problema que tengo es que no puedo redimensionar añadiendo nuevos registros con SetLength al array dinamico desde el procedimiento y pasarselo como parametro de salida.

He hecho mil pruebas y no encuentro la solucion si es que existe.

Gracias.

coso 07-11-2008 23:52:47

Hola

Código Delphi [-]
type TReg = record
     X,
     Y: string;
end;
type TRegArray = array of TReg;
 
...
 
procedure TForm1.Button1Click(Sender: TObject);
var Reg: TregArray;
begin
  SetLength(Reg, 0);  //0 registros
  MiProcedure(Reg);
  ShowMessage(Reg[0].x+', '+Reg[1].x);  //
end;

procedure TForm1.MiProcedure(var Reg: TRegArray);
begin
  SetLength(Reg, 2);  //2 registros
  Reg[0].x := '0';
  Reg[1].x := '1';
end;

asi funciona. Lei en algun sitio que delphi tiene ciertos inconvenientes al pasar arrays dinamicos como parametros. Quizas deba ser por eso que te fallase tu codigo (en principio no le veia fallo). saludos.

Lepe 08-11-2008 12:45:23

Delphi es un lenguaje de programación altamente tipificado, esto es, los tipos pasados por parámetros deben coincidir exactamente para que deje compilar.

Esto te obliga a usar buenas prácticas de programación como ha hecho coso
Código Delphi [-]
type TRegArray = array of TReg;

Al crear el tipo de datos en la zona interface, ya puedes usar ese tipo en todos los procedimientos de la unidad, y como el tipo de datos es el mismo, delphi te deja compilar perfectamente.

Incluso te ayuda a no cometer errores, es decir, en un lado del programa defines un array de una forma, y después intentas pasarle un array de otra forma distinta, eso provocaría errores en ejecución. Si delphi fuerza a que declares los tipos iguales, minimiza los errores de tu programa.

En cuanto a punteros y direcciones, debes saber que un array es ya un puntero a la primera posición de tu tabla, igual que tu "Form1" es un puntero a tu ventana TForm1. Delphi usa mucho los punteros, aunque los camufla de una forma elegante ;).

Saludos

eLYaN 08-11-2008 14:28:24

Muchisimas gracias, ha funcionado a la perfección.

Saludos.

Al González 08-11-2008 23:40:39

¡Hola a todos!

Un par de cosas:

No es necesario llamar al procedimiento SetLength con una longitud de 0 cuando la variable de arreglo dinámico todavía no tiene asignación de memoria alguna. Aunque se trate de variables locales, Delphi inicializa en ceros / Nil todas las variables que usan contadores de referencia, como es el caso de las cadenas largas y los arreglos dinámicos.

Por otra parte, también podría definirse la rutina del ejemplo a manera de función en lugar de procedimiento:
Código Delphi [-]
Function TForm1.MiFuncion :TRegArray;
Begin
  SetLength (Result, 2);  //2 registros
  Result [0].X := '0';
  Result [1].X := '1';
End;

procedure TForm1.Button1Click(Sender: TObject);
Var
  Reg :TRegArray;
begin
  Reg := MiFuncion;
  ShowMessage (Reg [0].X + ', ' + Reg [1].X);
end;

Saludos.

Al González. :)


La franja horaria es GMT +2. Ahora son las 20:49:26.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi