IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Delphi Discussion :

copier un tableau dynamique à deux dimensions


Sujet :

Delphi

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Février 2006
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 127
    Points : 49
    Points
    49
    Par défaut copier un tableau dynamique à deux dimensions
    Bonjour,

    Je souhaite bêtement copier un tableau dynamique à deux dimension dans un autre tableau dynamique à deux dimensions, il s'agit d'un tableau du type:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     array of array of Integer;
    J'ai expérimenté un peu avec MOVE et COPY sans grand succès.
    Avez-vous une suggestion pour résoudre mon problème (sans parcourir chaque élément du tableau bien évidement).

    Cordialement,

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 460
    Points : 24 877
    Points
    24 877
    Par défaut
    En théorie, avec le Move sur deux tableaux avec les mêmes dimensions, c'est osé, mais cela doit fonctionner !

    Sinon, Copy, doit fonctionner, c'est la fonction faite pour ...

    faire voir ton code
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 700
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 700
    Points : 13 138
    Points
    13 138
    Par défaut
    Ca ne fonctionnera pas sans boucle avec un tableau dynamique puisque ce ne sont que des pointeurs sur... d'autres tableaux.

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 460
    Points : 24 877
    Points
    24 877
    Par défaut
    Bien vu AndNotOr, Copy ne copie que les références, ce code démontre la vacherie de la chose !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    var
      A1, A2: array of array of Integer;
      I, J: Integer;
      S: string;
    begin
      SetLength(A1, 10, 100);
     
      for I := Low(A1) to High(A1) do
        for J := Low(A1[I]) to High(A1[I]) do
          A1[I, J] := I + J;
     
      A2 := Copy(A1); // Fait juste pointer A2 sur A1 ...
     
      S := '';
      for I := Low(A2) to High(A2) do
        for J := Low(A2[I]) to High(A2[I]) do
          S := S + #13 + IntToStr(A2[I, J]);
     
      ShowMessage(S);
     
      for I := Low(A1) to High(A1) do
        for J := Low(A1[I]) to High(A1[I]) do
          A1[I, J] := A1[I, J] * 10;
     
      S := '';
      for I := Low(A2) to High(A2) do
        for J := Low(A2[I]) to High(A2[I]) do
          S := S + #13 + IntToStr(A2[I, J]); 
     
      ShowMessage(S);
    end;
    la solution étant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      SetLength(A2, 10, 100);
      for I := Low(A2) to High(A2) do
        A2[I] := Copy(A1[I]);
    Valable pour des tableau dynamiques avec la même seconde dimension ...

    EDIT, j'ai fermé Delphi, ça donne quoi ça ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      SetLength(A2, 10);
      for I := Low(A2) to High(A2) do
         A2[I] := Copy(A1[I]);
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 700
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 700
    Points : 13 138
    Points
    13 138
    Par défaut
    Et encore, dans ton exemple, tu fixes toutes les dimensions du tableau en un seul SetLength. On pourrait imaginer que le données sont contiguës. Mais elles ne le seront certainement pas avec plus loin un SetLenth(A1[5], 101) (Réallocation).

    Il y a aussi ces 2 dword au pointeur -4 (-8) qui représente le compteur de référence et le nombre d'éléments dans le tableau (high). A prendre en compte dans Copy... avant de reseter le compteur de référence...

    Et j'en oublie surement !

    Je choisirais la facilité avec 2 petites boucles .

  6. #6
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Salut,

    Un simple CopyMemory (API windows) doit faire l'affaire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      CopyMemory(@Dest, @Src, SizeOf(Src));
    Akim Merabet

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 700
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 700
    Points : 13 138
    Points
    13 138
    Par défaut
    Move, CopyMemory, même combat !

    De plus, SizeOf sur un tableau dynamique te renvoie la taille du pointeur, 4 bytes .

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 460
    Points : 24 877
    Points
    24 877
    Par défaut
    CopyMemory fonctionne pour un tableau statique ou un comme dans ce sujet avec les tableaux dynamiques à une seule dimension comme on le faisait en Delphi 3 (avant que SetLength débarque pour les tableaux) mais ne fonctionne pas sur les tableaux dynamiques apparu avec Delphi 4 ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Move, CopyMemory, même combat !

    De plus, SizeOf sur un tableau dynamique te renvoie la taille du pointeur, 4 bytes .
    oui CopyMemory équivaut à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      Move(Src, Dest, SizeOf(Src));
    "SizeOf(Src)" du coup il copie exactement le nombre d'éléments de Src.

    Enfin il me semblait que ca fonctionnait.... à tester...
    Akim Merabet

  10. #10
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Un truc m'échappe peut être mais ceci fonctionne non?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    TArr = array of array of Integer;
     
    TfrmMain....
    Arr, Tmp: TArr;
    (...)
     
    procedure TfrmMain.Button3Click(Sender: TObject);
    var
      I, J: Integer;
    begin
      SetLength(Arr, 10, 10);
      for I := 0 to 9 do
      begin
        for J := 0 to 9 do
          Arr[I, J] := I * J;
      end;
    end;
     
    procedure TfrmMain.Button4Click(Sender: TObject);
    begin
      CopyMemory(@Tmp, @Arr, SizeOf(Arr));
      ShowMessage(IntToStr(Tmp[1, 3]));
    end;
    Akim Merabet

  11. #11
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 700
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 700
    Points : 13 138
    Points
    13 138
    Par défaut
    SizeOf n'est pas une fonction, mais plutôt un élément syntaxique qui permet de déterminer une constante à la compilation. La taille du tableau dynamique n'étant pas connue à ce moment-là, la taille du pointeur est renvoyée...

    Maintenant ajoutes ceci sur ton bouton 4:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    procedure TfrmMain.Button4Click(Sender: TObject);
    begin
      CopyMemory(@Tmp, @Arr, SizeOf(Arr));
      ShowMessage(IntToStr(Tmp[1, 3]));
     
      //Renvoi 4 et non la taille de Arr (10 *10 *SizeOf(integer))
      ShowMessage(IntToStr(SizeOf(Arr)));
     
      //On modifie Arr...
      Arr[1][3] = 33;
     
      //Tmp affiche maintenant 33. CopyMemory n'a copié que des pointeurs
      //sur des tableaux et non le contenu de ces tableaux.
      ShowMessage(IntToStr(Tmp[1, 3]));
    end;

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 460
    Points : 24 877
    Points
    24 877
    Par défaut
    Citation Envoyé par Kaféine Voir le message
    Un truc m'échappe peut être mais ceci fonctionne non?
    Tu n'as pas lu mon code "vacherie de la chose", qui montrait que Copy de A1 dans A2, ne recopiait pas les valeurs, modifier A1 modifiait A2 ...

    Pour les Dimensions d'un Tableau, il faut utiliser Length, Low et High ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  13. #13
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Ok les gars mea culpa...
    Akim Merabet

  14. #14
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    {$ALIGN ON}
    type
      PDblIntArray = ^TDblIntArray;
      TDblIntArray = packed array of array of integer;
     
    ... une fonction ...
    var A, B : TDblIntArray;
        X, Y : integer;
    begin
      // réglage de la taille
      SetLength(A, 5, 5);
     
      // remplissage quelconque
      for Y := 0 to 4 do
        for X := 0 to 4 do
          A[Y, X] := random(100);
     
      // assignation de A à B, nul besoin de move, copymemory ou autre.
      B := A;
    end;

    autre exemple :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    {$ALIGN ON}
    type
      PDblIntArray = ^TDblIntArray;
      TDblIntArray = packed array of array of integer;
     
      PMatrix = ^TMatrix;
      TMatrix = packed array of array of integer;
     
    // TMatrix et TDblIntArray sont incompatible de façon implicite, mais 
    // on peut les transtyper, l'un, dans l'autre, car compatible de façon explicite.
     
     
     
    function ArrayOfIntToStr(const A: TMatrix): string;
    var X, Y : integer;
    begin
      result := '(';
      for Y := 0 to High(A) do
      begin
        result := result + '[';
        for X := 0 to High(A[Y]) do
          result := result + IntToStr(A[Y,X]) + ', ';
        result := result + ']';
      end;
      result := result + ')';
    end;
     
    procedure TForm20.FormCreate(Sender: TObject);
    var A : TDblIntArray;
        B : TMatrix;
     
        X, Y : integer;
    begin
      SetLength(A, 5, 5);
      for Y := 0 to 4 do
        for X := 0 to 4 do
          A[Y, X] := random(100);
     
      // on transtype A en TMatrix
      // on peut egalement faire : 
      //    TDblIntArray(B) := A;
      B := TMatrix(A);
     
      richedit1.Text := ArrayOfIntToStr(TMatrix(A));
     
      richedit2.Text := ArrayOfIntToStr(B);
    end;
    [ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
    Ma messagerie n'est pas la succursale du forum... merci!

  15. #15
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 460
    Points : 24 877
    Points
    24 877
    Par défaut
    Dr. Who essaye ceci, je pense que tu vas dire "p****n de m***e"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    var A : TDblIntArray;
        B : TMatrix;
     
        X, Y : integer;
    begin
      SetLength(A, 5, 5);
      for Y := 0 to 4 do
        for X := 0 to 4 do
          A[Y, X] := random(100);
     
      // on transtype A en TMatrix
      // on peut egalement faire : 
      //    TDblIntArray(B) := A;
      B := TMatrix(A);
     
      richedit1.Text := ArrayOfIntToStr(TMatrix(A));
     
      richedit2.Text := ArrayOfIntToStr(B);
     
      for Y := 0 to 4 do
        for X := 0 to 4 do
          A[Y, X] := random(100);
     
      richedit3.Text := ArrayOfIntToStr(TMatrix(A));
     
      richedit4.Text := ArrayOfIntToStr(B);
    end;

    Depuis le début, on parle d'un problème d'un copie de référence et non de valeur, donc les deux tableaux A et B ne sont que des pointeurs vers les mêmes espaces mémoires ... hors le but est d'avoir une copie indépendante sans devoir écrire un boucle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      SetLength(B, 5);
      for Y := 0 to 4 do
        B[Y] := Copy(TMatrix(A)[Y]);
    J'ai vérifie, c'est façon là fonctionne, c'est peut-être plus efficace que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        SetLength(B, 5, 5);
      for Y := 0 to 4 do
        for X := 0 to 4 do
          B[Y, X] := A[Y, X];
    Cela permet une chose avec la boucle de Copy, c'est que la 2nde dimension peut varier !
    C'est déjà plus long à écrire en affection simple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        SetLength(B, 5);
      for Y := 0 to 4 do
      begin
        SetLength(B[Y], 5);
     
        for X := 0 to 4 do
          B[Y, X] := A[Y, X];
      end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  16. #16
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 700
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 700
    Points : 13 138
    Points
    13 138
    Par défaut
    Au minimum, Copy (comme pour une chaîne) prendra en compte les 2 dword précédents les données.

    Ce qui m'étonne Shai, c'est que dans ta déclaration SetLength(B, 5), les pointeurs sur les 2èmes dimensions sont à nil (aucune allocation) !
    Copy allouerait-il de la mémoire ?..

  17. #17
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 460
    Points : 24 877
    Points
    24 877
    Par défaut
    On dirait bien, il copie correctement le tableaux, je pense qu'il sait copier un tableau dynamique à une dimension sans soucis
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  18. #18
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    sinon on peut faire une copie par boucle, toujours efficace, même si la condition est de le faire sans, de toute façon avec des tableaux dynamique, pas trop le choix :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    procedure CopyMatrixVariableDim(const aSrc: TMatrix; var aDest: TMatrix);
    var Y,X, LY, LX : integer;
    begin
      LY := Length(aSrc);
      SetLength(aDest, LY);
      for Y := 0 to LY-1 do
      begin
        LX := Length(aSrc[Y]);
        SetLength(aDest[Y], LX);
        for X := 0 to LX-1 do
          aDest[Y,X] := aSrc[Y,X];
      end;
    end;
     
    procedure CopyMatrixFixedDim(const aSrc: TMatrix; var aDest: TMatrix);
    var Y,X, LY, LX : integer;
    begin
      LY := Length(aSrc);
      LX := Length(aSrc[LY-1]);
      SetLength(aDest, LY, LX);
      for Y := 0 to LY-1 do
        for X := 0 to LX-1 do
          aDest[Y,X] := aSrc[Y,X];
    end;


    sinon, on peut faire une classe qui englobe un pointeur de tableau à une dimension mais avec deux propriétés d'accés en simple dim et double dim :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
     
    uses RTLConsts;
     
    {$ALIGN ON}
     
    type
      _PMatrix = ^_Matrix;
      _Matrix = array[0..0] of integer;
     
      TMatrix = class
      private
        fYCount, fXCount, fCount : integer;
        fMatrix : _PMatrix;
        function GetSD(index: integer): integer;
        procedure SetSD(index: integer; const value: integer);
        function GetDD(X, Y: integer): integer;
        procedure SetDD(X, Y: integer; const value: integer);
        function GetMm: pointer;
      protected
        procedure IndexError(const aCurrentIndex, aMaxIndex: integer);
      public
        constructor Create;
     
        // simple dimension
        constructor CreateSD(const aCount: integer); reintroduce; overload;
        property Count  : integer read fCount;
        property ItemsSD[index: integer]: integer read GetSD write SetSD;
     
        // Double dimension
        constructor CreateDD(const aXCount, aYCount: integer); reintroduce; overload;
        property XCount : integer read fXCount;
        property YCount : integer read fYCount;
        property ItemsDD[X,Y: integer] : integer read GetDD write SetDD;
     
        procedure Assign(Src: TMatrix);
        procedure SDToString(Strings: TStrings);
        procedure DDToString(Strings: TStrings);
     
        property Memory : pointer read GetMm;
        destructor Destroy; override;
      end;
     
     
    { TMatrix }
     
    procedure TMatrix.IndexError(const aCurrentIndex, aMaxIndex: integer);
      function ReturnAddr: Pointer;
      asm
       mov eax,[ebp+4]
      end;
    begin
      raise ERangeError.CreateFmt(sArgumentOutOfRange_Index, [aCurrentIndex, aMaxIndex]) at ReturnAddr;
    end;
     
    function TMatrix.GetMm: pointer;
    begin
      result := pointer(fMatrix);
    end;
     
    procedure TMatrix.Assign(Src: TMatrix);
    begin
      FreeMem(fMatrix, fCount shl 2);
     
      fXCount := Src.fXCount;
      fYCount := Src.fYCount;
      fCount  := Src.fCount;
      fMatrix := AllocMem(fCount shl 2);
     
      CopyMemory(fMatrix, Src.fMatrix, fCount shl 2);
    end;
     
    constructor TMatrix.Create;
    begin
      inherited;
      fXCount := 0;
      fYCount := 0;
      fCount  := 0;
      fMatrix := nil;
    end;
     
    constructor TMatrix.CreateDD(const aXCount, aYCount: integer);
    begin
      fXCount := aXCount;
      fYCount := aYCount;
      fCount  := aXCount * aYCount;
      fMatrix := AllocMem(fCount shl 2);
      ZeroMemory(fMatrix, fCount shl 2);
    end;
     
    constructor TMatrix.CreateSD(const aCount: integer);
    begin
      fXCount := trunc(sqrt(aCount));
      fYCount := fXCount;
      fCount  := aCount;
      fMatrix := AllocMem(fCount shl 2);
      ZeroMemory(fMatrix, fCount shl 2);
    end;
     
    procedure TMatrix.DDToString(Strings: TStrings);
    var S : string;
        X,Y : integer;
    const
      coma : array[boolean] of char = (',',')');
    begin
      Strings.BeginUpdate;
      try
        Strings.Clear;
        for Y := 0 to fYCount-1 do
        begin
          S := '(';
          for X := 0 to fXCount-1 do
            S := S + IntToStr(fMatrix[Y*fYCount + X])+coma[X = fXCount-1];
          if Y < fYCount-1 then
            S := S + ',';
          Strings.Add(S);
        end;
      finally
        Strings.EndUpdate;
      end;
    end;
     
    destructor TMatrix.Destroy;
    begin
      FreeMem(fMatrix, fCount shl 2);
      inherited;
    end;
     
    function TMatrix.GetDD(X, Y: integer): integer;
    begin
      if (X < 0) or (X >= fXCount) then IndexError(X, fXCount);
      if (Y < 0) or (Y >= fYcount) then IndexError(Y, fYCount);
      result := fMatrix[(Y * fYCount) + X];
    end;
     
    function TMatrix.GetSD(index: integer): integer;
    begin
      if (index < 0) or (index >= fXCount) then IndexError(index, fCount);
      result := fMatrix[index];
    end;
     
    procedure TMatrix.SDToString(Strings: TStrings);
    var S : string;
        N : integer;
    const
      Coma : array[boolean] of Char = (')',',');
    begin
      Strings.BeginUpdate;
      try
        Strings.Clear;
        S := S + '(';
        for N := 0 to fCount-1 do
          S := S + IntToStr(fMatrix[N]) + Coma[N < fCount-1];
        Strings.Add(S);
      finally
        Strings.EndUpdate;
      end;
    end;
     
    procedure TMatrix.SetDD(X, Y: integer; const value: integer);
    begin
      if (X < 0) or (X >= fXCount) then IndexError(X, fXCount);
      if (Y < 0) or (Y >= fYcount) then IndexError(Y, fYCount);
      fMatrix[(Y*fYCount) + X] := value;
    end;
     
    procedure TMatrix.SetSD(index: integer; const value: integer);
    begin
      if (index < 0) or (index >= fXCount) then IndexError(index, fCount);
      fMatrix[index] := value;
    end;
    exemple d'utilisation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    var
      MXA, MXB : TMatrix;
     
    procedure TForm20.FormCreate(Sender: TObject);
    begin
      MXA := TMatrix.CreateDD(3,3);
      MXB := TMatrix.Create;
     
      MXA.ItemsDD[0,0] := 1;
      MXA.ItemsDD[1,0] := 2;
      MXA.ItemsDD[2,0] := 3;
      MXA.ItemsDD[0,1] := 4;
      MXA.ItemsDD[1,1] := 5;
      MXA.ItemsDD[2,1] := 6;
      MXA.ItemsDD[0,2] := 7;
      MXA.ItemsDD[1,2] := 8;
      MXA.ItemsDD[2,2] := 9;
     
      MXB.Assign(MXA);
     
      MXA.ItemsDD[0,0] := 10;
      MXA.ItemsDD[1,0] := 20;
      MXA.ItemsDD[2,0] := 30;
      MXA.ItemsDD[0,1] := 40;
      MXA.ItemsDD[1,1] := 50;
      MXA.ItemsDD[2,1] := 60;
      MXA.ItemsDD[0,2] := 70;
      MXA.ItemsDD[1,2] := 80;
      MXA.ItemsDD[2,2] := 90;
     
      MXA.DDToString(RichEdit1.Lines);
      MXB.SDToString(RichEdit2.Lines);
    end;
     
    procedure TForm20.FormDestroy(Sender: TObject);
    begin
      MXB.Free;
      MXA.Free;
    end;
    [ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
    Ma messagerie n'est pas la succursale du forum... merci!

  19. #19
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Salut,

    Avec les variants, on évite l'écriture des boucles.

    Apparement cette portion de code fonctionne [vous voyez je reste prudent ]

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    procedure TfrmMain.Button1Click(Sender: TObject);
    var
      Tab1, Tab2: Variant;
      Tmp1, Tmp2: Variant;
     
      function NouveauTab(ATab: array of Variant): Variant;
      begin
        Result := VarArrayOf(ATab);
      end;
     
    begin
      Tab1 := VarArrayOf([NouveauTab([11, 12, 13]), NouveauTab([21, 22, 23]), NouveauTab([31, 32, 33])]);
      Tab2 := Tab1;
      Tmp1 := VarArrayGet(Tab1, [1]);
      VarArrayPut(Tmp1, 1111, [1]);
      Tmp2 := VarArrayGet(Tab2, [1]);
      mmoOutput.Lines.Add(VarToStr(VarArrayGet(Tmp1, [1]))); // => 1111
      mmoOutput.Lines.Add(VarToStr(VarArrayGet(Tmp2, [1]))); // => 22
    end;
    Akim Merabet

  20. #20
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    procedure TForm1.Button1Click(Sender: TObject);
    var
        i,j,p:integer;
        d,n:array of array of integer;
        z:array of integer;
    begin
         ListBox1.Clear;
         ListBox2.Clear;
         setlength(d,3,4);
         setlength(n,3,4);
         p:=0;
         for i:=0 to high(d) do
           for j:=0 to high(d[i]) do
             begin
              inc(p);
              d[i,j]:=p;
              ListBox1.Items.Add(inttostr(p));
             end;
         for i:=0 to high(d) do
           begin
             Move(d[i,0],n[i,0],(high(d[i])+1)*sizeof(integer));
           end;
         for i:=0 to high(n) do
           for j:=0 to high(n[i]) do
             begin
              ListBox2.Items.Add(inttostr(n[i,j]));
             end;
    end;
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

Discussions similaires

  1. Tableau dynamique deux dimensions de class
    Par Hyssgrif dans le forum C++
    Réponses: 3
    Dernier message: 17/04/2015, 15h22
  2. Tableau dynamique à deux dimensions
    Par Neuromancien2 dans le forum ASP
    Réponses: 4
    Dernier message: 13/06/2007, 18h12
  3. Tableau dynamique à deux dimensions
    Par David Fouejio dans le forum MFC
    Réponses: 4
    Dernier message: 05/03/2007, 09h37
  4. Réponses: 1
    Dernier message: 09/03/2006, 17h25
  5. Réponses: 6
    Dernier message: 26/11/2005, 19h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo