Modification de la taille d'un tableau dynamique pré-déclaré dans une classe

olemtiri Messages postés 8 Date d'inscription vendredi 19 novembre 2004 Statut Membre Dernière intervention 3 décembre 2006 - 26 nov. 2006 à 16:54
olemtiri Messages postés 8 Date d'inscription vendredi 19 novembre 2004 Statut Membre Dernière intervention 3 décembre 2006 - 3 déc. 2006 à 22:16
Slt à vous, j'ai un petit problème en ce qui concerne la modification de la taille d'un tableau(pas n'importe quel tableau dynamique mais un tableau déclaré comme propriété d'une classe). Voici un exemple de code :

type
ByteArray=array of Byte;
TEssai=class(TObject)
private
Fvar1:ByteArray;
public
property var1:ByteArray read Fvar1 write Fvar1;
end;

Je crée ensuite un bouton standard et j'ajoute le code suivant :

procedure TForm1.Button1Click(Sender: TObject);
var Essai:TEssai;
begin
SetLength(Essai.var1,2);
end;

mais là ca ne marche pas et je reçois l'erreur : "Un objet constante ne peut être passé comme paramètre Var".

Je sais qu'il y a une solution c'est de créer une méthode associée à cette classe pour modifier la taille de ce tableau, mais le problème c'est qu'en pratique j'ai plusieurs tableaux dynamiques (même beaucoup) donc ça ne serait pas efficace de créer 10 ou 11 fonctions pour changer la taille des tableaux.

Quelqu'un aurait-il une solution pour ce problème?

Merci d'avance.

11 réponses

DRJEROME Messages postés 436 Date d'inscription jeudi 9 janvier 2003 Statut Membre Dernière intervention 5 février 2015
26 nov. 2006 à 18:32
Salut,
je me suis amusé à mettre 2 propriétés (pour compliquer), ça a l'air de marcher :

<hr />
type ByteArray=array of Byte;
 TEssai=class(TObject)
 private Fvar1:ByteArray;Fvar2:ByteArray;
 public
       property var1:ByteArray read Fvar1 write Fvar1;
       property var2:ByteArray read Fvar2 write Fvar2;
 end;





implementation
{$R *.DFM}


procedure TForm1.Button1Click(Sender: TObject);
var
Essai:TEssai;
BA1,BA2:ByteArray;
begin
     Setlength(BA1,3); Setlength(BA2,3);
     BA1[0]:=8;BA1[1]:=16;BA1[2]:=32;
     BA2[0]:=6;BA2[1]:=14;BA2[2]:=30;
     Essai:=TEssai.Create;
     Essai.var1:=BA1;
     Essai.var2:=BA2;
     showmessage(inttostr(Essai.var1[2]));
     showmessage(inttostr(Essai.var2[2]));
     Essai.Free;//nécessaire ?
end;


<hr />



Maintenant, je ne sais pas si c'est la meilleure solution

DrJerome
0
DRJEROME Messages postés 436 Date d'inscription jeudi 9 janvier 2003 Statut Membre Dernière intervention 5 février 2015
26 nov. 2006 à 18:47
tu peux écrire "Fvar1" à la place de "var1" et "Fvar2" à la place de "var2" dans la procédure "Button1Click"
(pour la justesse du code) sinon le raisonnement reste valable

DrJerome
0
olemtiri Messages postés 8 Date d'inscription vendredi 19 novembre 2004 Statut Membre Dernière intervention 3 décembre 2006
26 nov. 2006 à 20:08
J'ai déjà essayé ce truc, merci tt de même. J'ai remarqué d'ailleurs qu'il était possible de manipuler les tableaux dynamiques en leur affectant d'autres tableaux dynamiques. Comme solution c'est bien pour de petites applications mais je parle là d'un projet un peu volumineux et mettre en place cette solution veut dire doubler le nombre de variables à utilser. N'y aurait-il pas une autre alternative?
0
DRJEROME Messages postés 436 Date d'inscription jeudi 9 janvier 2003 Statut Membre Dernière intervention 5 février 2015
26 nov. 2006 à 20:59
Humm... excuse-moi

j'avais pas saisi,

...donc :





<hr />
type ByteArray=array of Byte;
 TEssai=class(TObject)
 private Fvar1:ByteArray;Fvar2:ByteArray;
 public
       property var1:ByteArray read Fvar1 write Fvar1;
       property var2:ByteArray read Fvar2 write Fvar2;
 end;



implementation
{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
Essai:TEssai;
BA:ByteArray;
begin
     Essai:=TEssai.Create;
     Setlength(Essai.Fvar1,3); Setlength(Essai.Fvar2,3);
     Essai.Fvar1[0]:=8;Essai.Fvar1[1]:=16;Essai.Fvar1[2]:=32;
     Essai.Fvar2[0]:=6;Essai.Fvar2[1]:=14;Essai.Fvar2[2]:=30;
     showmessage(inttostr(Essai.var1[2]));
     showmessage(inttostr(Essai.var2[2]));
     Essai.Free;//nécessaire ?
end;


<hr />




DrJerome  
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
DRJEROME Messages postés 436 Date d'inscription jeudi 9 janvier 2003 Statut Membre Dernière intervention 5 février 2015
26 nov. 2006 à 21:00
tu enlèves la ligne "BA:ByteArray;"... bien-entendu

DrJerome
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
26 nov. 2006 à 21:32
Salut,

une aute solution :

unit UEssai;

interface
uses
  Windows, Messages, SysUtils, Classes;

 type TByteArray = array of Byte;
 TEssai = class(TObject)
 private
   Fvar1:TByteArray;
   FDataByte : Byte;
   Procedure SetByteArray(Const Index: Integer; Value: Byte);
   Function  GetByteArray(Const Index: Integer): Byte;
 public
   Destructor Destroy; OverLoad;
   property DataByte[Const Index: Integer]: Byte read GetByteArray write SetByteArray;
 end;

implementation

{ TEssai }

destructor TEssai.Destroy;
begin
  Finalize(FVar1);
  Inherited Destroy;
end;

function TEssai.GetByteArray(const Index: Integer): Byte;
begin
  If Index < = High(FVar1) Then
  Result : = FVar1[Index];
end;

procedure TEssai.SetByteArray(const Index: Integer; Value: Byte);
begin
  If Index > High(FVar1) + 1 Then Exit;
  If Index > High(FVar1) Then SetLength(FVar1, Length(FVar1) + 1);
  FVar1[Index] := Value;
end ;

end.

Utilisation :

Uses UEssai;

procedure TForm1.Button1Click(Sender: TObject);
Var aTest : TEssai;
    I     : Integer;
begin
  Randomize;
  aTest : = TEssai.Create;
Try
  For I := 0 To 10 do
  aTest.DataByte[I]: = Random(256);

  For I := 0 to 10 do
  Memo1.Lines.Add(IntToStr(aTest.DataByte[I]));
Finally
  aTest.Free;
End;
end;

 
@+
Cirec

<hr size ="2" />
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
26 nov. 2006 à 23:23
Bon ben voilà une erreur c'est glissée dans le code

au lieu d'un Override j'avais mis un Overload et du coup le Destructeur n'était pas éxécuté

Du coup j'en prifité pour apporter un plus (petit) :
une procedure Clear ... qui devinez a quoi elle sert

Enfin voici le code :

unit UEssai;

interface
uses
  Windows, Messages, SysUtils, Classes;

 type TByteArray = array of Byte;
 TEssai = class(TObject)
 private
   Fvar1:TByteArray;
   Procedure SetByteArray(Const Index: Integer; Value: Byte);
   Function  GetByteArray(Const Index: Integer): Byte;
 public
   Procedure Clear;
   Destructor Destroy; override
   property DataByte [Const Index: Integer]: Byte read GetByteArray write SetByteArray;
 end;

implementation

{ TEssai }

{Mise à Zéro }
procedure TEssai.Clear;
begin
  SetLength(FVar1, 0);
end;

destructor TEssai.Destroy;
begin
  Clear;
  Finalize(FVar1);
  Inherited Destroy;
end;

function TEssai.GetByteArray(const Index: Integer): Byte;
begin
  Result : = 0;
  If Index < = High(FVar1) Then
  Result := FVar1[Index];
end ;

procedure TEssai.SetByteArray(const Index: Integer; Value: Byte);
begin
  If Index > High(FVar1) + 1 Then Exit;
  If Index > High(FVar1) Then SetLength(FVar1, Length(FVar1) + 1);
  FVar1[Index] : = Value;
end;

end.

La démo reste la même, le clear est la si tu réutilise l'objet TEssai tu peut remettre le tableau à zéro juste en faisant un Clear  :
 Ex. aTest.Clear;
voilà c'est la base si tu as besoin de plus il est facile de rejouter des procédure et/où fonction

 
@+
Cirec

<hr size="2" />
0
olemtiri Messages postés 8 Date d'inscription vendredi 19 novembre 2004 Statut Membre Dernière intervention 3 décembre 2006
2 déc. 2006 à 19:05
Merci, la solution a marché. Or un autre problème se pose, maintenant supposons que le tableau que je veux modifier est celui ci :
FVar1:array of record
Name:string;
Age:Byte;
Var2:array of Byte;
end;
alors comment faire pour modifier les différentes variables de FVar1. La complexité vient du fait qu'il y a un tableau à l'intérieur d'un autre tableau. Pour une généralisation,est-ce qu'il n y a pas une solution pour toutes les combinaisons possibles de array et record? Merci, j'apprécie votre aide.

P.S : Je ne cherche pas poser ces problèmes comme ça sans raison, mais c'est vraiment le projet sur lequel je travaille qui m'a imposé ces difficultés.
0
florenth Messages postés 1023 Date d'inscription dimanche 1 août 2004 Statut Membre Dernière intervention 17 août 2008 3
2 déc. 2006 à 21:17
Si tu as un array of record dans une classe, ça devient vite difficile d'y avoir accès simplement.
En effet, tu vas être contronté à des erreurs du type "partie gauche non affectable" et tout ça, à cause des propriétés.

La solution qui marche bien est de passer par un TObjectList et une classe au lieu du record.

Exemple:

<hr size= "2" width="100%" />TVar1 = class (TObject)
public
  Name: string;
  Age: Byte;
end;

TEssai = class(TObject)
private
  FVar1: TObjectList;
  function GetVar1(I: Integer): TVar1;
  function GetVar1Count: Integer;
public
  constructor Create;
  destructor Destroy; override;
  property Var1[I: Integer]: TVar1 read GetVar1;
  property Var1Count: Integer read GetVar1Count;
end;

constructor TEssai.Create;
begin
  inherited Create;
  FVar1 := TObjectList.Create(True);
end ;

destructor TEssai.Destroy;
begin
  FVar1.Free;
  inherited Destroy;
end;

function TEssai.GetVar1(I: Integer): TVar1;
begin
  Result : = FVar1[I] as TVar1;
end;

function TEssai.GetVar1Count: Integer;
begin
  Result := FVar1.Count;
end ;
<hr size ="2" width="100%" />
Bon, je n'ai pas inclus de fonction d'ajout ni autre chose ...
Mais l'idée est là, l'essentiel aussi.
Renseigne toi sur la classe TObjectList, elle est la clé de voûte de pas mal de problèmes du genre et ce serait dommage de passer à côté.

@ Cirec: l'utilité des paramètres "const" n'est justifiée que si le paramètre ne doit pas être modifié et que son occupation mémoire dépasse 32 bits. Elle indique à Delphi qu'il peut envoyer directement un pointeur sur la copie originale de la variable sans soucis. Pour un Integer, il n'y a aucun gain, voie même une perte puisque Delphi va passer l'adresse de l'Integer au lieu de sa valeur directement dans le registre EBX.

En gros: ''const'' est à utiliser (entendre bénéfique) pour les types chaînes, tableaux et record.

A+
Florent
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
3 déc. 2006 à 18:45
Merci pour l'infomation

encore un truc d'on je n'avais pas connaissance
 
@+
Cirec

<hr size="2" />
0
olemtiri Messages postés 8 Date d'inscription vendredi 19 novembre 2004 Statut Membre Dernière intervention 3 décembre 2006
3 déc. 2006 à 22:16
Merci cirec et Florent pour votre aide. J'ai trouvé une solution plus ou moins appropriée mais qui s'est adaptée facilement. J'ai juste remplacé quelques propriétés qui posaient problème avec des variables. Comme ca pas d'erreur, mais c'est bien de savoir le TObjectList et l'autre soluce par cirec.
Merci encore.
0
Rejoignez-nous