Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   redimensionar varias veces un array (https://www.clubdelphi.com/foros/showthread.php?t=86272)

Manuel 11-07-2014 06:50:08

redimensionar varias veces un array
 
Hola amigos del club, por favor si me pueden ayudar con este problema que se presento, tengo lo siguiente, un array dinámico el cual lo dimensiono de la siguiente manera:

Código Delphi [-]
procedure calcular;
var
   Numeros: array of double;
   largo, i: integer;
begin
    i:=i;
    while i < 6 do
       begin
            SetLength(Numeros,i); 
            carga_datos(numeros);
            inc(i);
       end;
end;


Delphi 7 me acusa error de violación de memoria cuando al hacer por segunda vez el

Código Delphi [-]
SetLength(Numeros,i);

en el array numeros, como se puede hacer para redimensionar varias veces sin que se produzca el error?

ecfisa 11-07-2014 07:52:16

Hola Manuel.

Dos detalles, la inicialización de la variable de control y la forma que aumentas el tamaño del arreglo dinámico.
Código Delphi [-]
procedure calcular;
var
  Numeros: array of double;
  i: integer;
begin
  // i:=i; ( mal, el valor de 'i' no está definido )
  i:= 0;
  while i < 6 do
  begin
    // Tamaño anterior del arreglo dinámico, incrementado en uno
    SetLength(Numeros, Length(Numeros) + 1);
    carga_datos(Numeros);
    Inc(i);
  end;
end;
Aunque es mas simple:
Código Delphi [-]
procedure Calcular;
var
  Numeros: array of Double;
  i: Integer;
begin
  for i:= 0 to 5 do
  begin
    SetLength(Numeros, Length(Numeros)+1);
    carga_datos(Numeros);
  end;
end;
O como en estos casos, que sabemos de antemano que serán 6 elementos, mas simple todavía:
Código Delphi [-]
procedure Calcular;
var
  Numeros: array of Double;
  i: Integer;
begin
  SetLength(Numeros, 5);
  for i:= Low(Numeros) to High(Numeros) do  // o: for i:= 0 to 5 do ...
    carga_datos(Numeros);
end;

Saludos :)

Manuel 11-07-2014 14:31:29

Gracias daniel, en todo caso es un ejemplo que puse solamente, el real es mucho mas complejo, la idea central que la función SetLength no deja ridemensionar varias veces el mismo array con diferentes posiciones por ejemplo:


Código Delphi [-]
SetLength(Numeros,10); 
..
//otras intrucciones
..
..


SetLength(Numeros,20); /// Acá se produce el error de violación de posición de memoria.

Una vez gracias Daniel.

ecfisa 11-07-2014 15:10:35

Hola Manuel.

Si no te entiendo mal es lógico, por que la segunda asignación del arreglo anula la primera. En tu ejemplo la cantidad de elementos no termina siendo 30 sino 20 ya que la última sentencia fija el tamaño del arreglo en esa cifra.

Tal vez con estos ejemplos pueda explicar mejor a que me refiero:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
var
  v: array of Integer;
  i: Integer;
begin
  // agregar 5 enteros
  for i:= 0 to 4 do
  begin
    SetLength(v, Length(v)+1);
    v[Length(v)-1]:= i;  
  end;

  // agregar diez enteros mas
  for i:= 500 to 509 do
  begin
    SetLength(v, Length(v)+1);
    v[High(v)]:= i;  // igual que: v[Length(v)-1]
  end;

  // mostrar
  for i:= Low(v) to High(v) do
    ListBox1.Items.Add(IntToStr(v[i]))
end;


Código Delphi [-]
procedure TForm1.Button2Click(Sender: TObject);
var
  v: array of Integer;
  i: Integer;
begin
  // agregar 5 enteros
  SetLength(v, 5);
  for i:= 0 to 5 do v[i]:= i;

  // agregar 10 mas
  SetLength(v, Length(v)+10);
  for i:= 0 to 9 do v[5+i]:= 500+i;

  // mostrar
  for i:= Low(v) to High(v) do
    ListBox1.Items.Add(IntToStr(v[i]));
end;

Saludos :)

Manuel 11-07-2014 16:56:52

Gracias Daniel nuevamente, me he dado cuenta que cuando aumento la cantidad de elementos no hay problemas , pero si cuando se redimensiona a menos elementos se produce el error.

nlsgarcia 11-07-2014 20:15:03

Manuel,

Cita:

Empezado por Manuel
...¿como se puede hacer para redimensionar varias veces?...me he dado cuenta que cuando aumento la cantidad de elementos no hay problemas , pero si cuando se redimensiona a menos elementos se produce el error...

:confused:

Revisa este código:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
var
   A1 : Array of Integer;
   i : Integer;
   Msg : String;

begin

   // Muestra Longitud de A1 la cual esta en Cero dado que no ha sido Redimensionado
   ShowMessage('Longitud de A1 = ' + IntToStr(Length(A1)));

   // Redimensiona a 10, Carga 10 Elementos y Muestra el Primer y Último Elemento de A1
   SetLength(A1,10);
   ShowMessage('Longitud de A1 = ' + IntToStr(Length(A1)));
   for i := Low(A1) to High(A1) do
      A1[i] := i+1;
   Msg := 'Primer y Último Elemento de A1 = ' + IntToStr(A1[Low(A1)]) + ',' + IntToStr(A1[High(A1)]);
   ShowMessage(Msg);

   // Redimensiona a 20, Carga 20 Elementos y Muestra el Primer y Último Elemento de A1
   SetLength(A1,20);
   ShowMessage('Longitud de A1 = ' + IntToStr(Length(A1)));
   for i := Low(A1) to High(A1) do
      A1[i] := i+1;
   Msg := 'Primer y Último Elemento de A1 = ' + IntToStr(A1[Low(A1)]) + ',' + IntToStr(A1[High(A1)]);
   ShowMessage(Msg);

   // Redimensiona a 30, Carga 30 Elementos y Muestra el Primer y Último Elemento de A1
   SetLength(A1,30);
   ShowMessage('Longitud de A1 = ' + IntToStr(Length(A1)));
   for i := Low(A1) to High(A1) do
      A1[i] := i+1;
   Msg := 'Primer y Último Elemento de A1 = ' + IntToStr(A1[Low(A1)]) + ',' + IntToStr(A1[High(A1)]);
   ShowMessage(Msg);

   // Redimensiona a 20, Carga 20 Elementos y Muestra el Primer y Último Elemento de A1
   SetLength(A1,20);
   ShowMessage('Longitud de A1 = ' + IntToStr(Length(A1)));
   for i := Low(A1) to High(A1) do
      A1[i] := i+1;
   Msg := 'Primer y Último Elemento de A1 = ' + IntToStr(A1[Low(A1)]) + ',' + IntToStr(A1[High(A1)]);
   ShowMessage(Msg);

   // Redimensiona a 10, Carga 10 Elementos y Muestra el Primer y Último Elemento de A1
   SetLength(A1,10);
   ShowMessage('Longitud de A1 = ' + IntToStr(Length(A1)));
   for i := Low(A1) to High(A1) do
      A1[i] := i+1;
   Msg := 'Primer y Último Elemento de A1 = ' + IntToStr(A1[Low(A1)]) + ',' + IntToStr(A1[High(A1)]);
   ShowMessage(Msg);

end;
El código anterior en Delphi 7 bajo Windows 7 Professional x32, redimensiona un arreglo de enteros en forma creciente y decreciente y efectúa operaciones sobre sus elementos.

Revisa esta información:
Espero sea útil :)

Nelson.

ecfisa 11-07-2014 22:03:14

Hola Manuel.

Hola Manuel
Cita:

Empezado por Manuel (Mensaje 478887)
..., pero si cuando se redimensiona a menos elementos se produce el error.

Te pongo un ejemplo que inicializa, aumenta y por último disminuye el tamaño de un arreglo dinámico:
Código Delphi [-]
type
  TDynArray = array of Integer;

procedure TForm1.Button1Click(Sender: TObject);

  procedure Mostrar(v: TDynArray);
  var
    i: Integer;
  begin
    for i:= Low(v) to High(v) do Memo1.Lines.Add(Format('%d',[i]));
    Memo1.Lines.Add(Format('  Elementos: %d',[Length(v)]));
    Memo1.Lines.Add('--------------------');
  end;

var
  da: TDynArray;
  i: Integer;
begin
  Memo1.Lines.Clear;
  Memo1.ScrollBars:= ssVertical;
  // Inicializar en 4 elementos
  SetLength(da, 4);
  for i:= 0 to 3 do da[i]:= i;
  Mostrar(da);

  // Aumentar en 4 elementos
  SetLength(da, Length(da) + 4);
  for i:= 0 to 3 do da[High(da)]:= High(da)+1;
  Mostrar(da);

  // Reducir a dos elementos
  SetLength(da, 2);
  Mostrar(da);

  // Desasignar memoria asociada 
  Finalize(da);
end;
El resultado:
Código:

0
1
2
3
  Elementos: 4
--------------------
0
1
2
3
4
5
6
7
  Elementos: 8
--------------------
0
1
  Elementos: 2
--------------------

Saludos :)

mamcx 11-07-2014 22:11:23

Cita:

Empezado por Manuel (Mensaje 478876)
Delphi 7 me acusa error de violación de memoria cuando al hacer por segunda vez el

Código Delphi [-]
SetLength(Numeros,i);

Cuando te ocurran estas cosas, busca en google. Con "Acces violation SetLength" encontre varios links con posibles causas.

Ademas, para poder determinar que pasa con un error, el que sea, debes volverlo reproducible. No basta con simplemente mostrar codigo, debes mostrar el conjunto de pasos EXACTOS que genera el error, de lo contrario uno puede quedarse una eternidad adivinando estos casos.

Manuel 12-07-2014 01:58:15

Mil Gracias Daniel por tu ayuda, solucionado el problema después de cada SetLength(arreglo), coloque un Finalize(arreglo) y error se eliminó. Gracias una vez más.

nlsgarcia 12-07-2014 03:44:07

Manuel,

Cita:

Empezado por Manuel
...después de cada SetLength(arreglo), coloque un Finalize(arreglo)...

:confused:

Nelson.

Manuel 12-07-2014 04:11:04

Que cosa no entiendes?

nlsgarcia 12-07-2014 04:38:07

Manuel,

Cita:

Empezado por Manuel
...¿Que cosa no entiendes?...

:rolleyes:

Sería conveniente que publicaras el código en cuestión, en general no es necesario colocar un Finalize después de cada SetLength de un Arreglo Dinámico, como se puede ver en los códigos de los Msg #6 y Msg #7.

Cita:

Empezado por mamcx
...para poder determinar que pasa con un error, el que sea, debes volverlo reproducible. No basta con simplemente mostrar código, debes mostrar el conjunto de pasos EXACTOS que genera el error...

^\||/

Nelson.

Manuel 14-07-2014 04:04:29

Cita:

Empezado por nlsgarcia (Mensaje 478902)
Manuel,


:rolleyes:

Sería conveniente que publicaras el código en cuestión, en general no es necesario colocar un Finalize después de cada SetLength de un Arreglo Dinámico, como se puede ver en los códigos de los Msg #6 y Msg #7.


^\||/

Nelson.

Nelson, mi sistema tenía bucle que redimensiona una y otra ves el mismo arreglo dinámico , el proble se presentaba cuando la redimensión era de menos elementos con respecto al último, al colocar Finalize se solucionó el problema.

nlsgarcia 14-07-2014 04:49:40

Manuel,

Cita:

Empezado por Manuel
...mi sistema tenía bucle que redimensiona una y otra ves el mismo arreglo dinámico...

:rolleyes:

Revisa este código:
Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Math;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
   A1 : Array of Integer;
   i,j : Integer;
   Delta : Integer;
   Msg : String;

begin

   Randomize;

   for i := 1 to 1000 do
   begin
      Delta := RandomRange(1,100);
      SetLength(A1,Delta);
      for j := Low(A1) to High(A1) do
         A1[j] := Random(500);
   end;

   ShowMessage('Longitud de A1 = ' + IntToStr(Length(A1)));
   Msg := 'Primer y Último Elemento de A1 = ' + IntToStr(A1[Low(A1)]) + ',' + IntToStr(A1[High(A1)]);
   ShowMessage(Msg);

end;

end.
El código anterior en Delphi 7 bajo Windows 7 Professional x32, redimensiona aleatoriamente en un loop un arreglo de enteros y efectúa operaciones sobre sus elementos.

Suerte en tu proyecto ^\||/

Nelson.


La franja horaria es GMT +2. Ahora son las 14:54:08.

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