web-dev-qa-db-fra.com

Comment déclarer un tableau lorsque je ne connais pas la longueur avant l'exécution?

J'avais à l'origine un tableau [1..1000] qui était défini comme une variable globale. Mais maintenant, j'ai besoin que ce soit n, pas 1000 et je ne le découvrirai que plus tard. Je sais ce que n est avant de remplir le tableau mais j'ai besoin qu'il soit global donc j'ai besoin d'un moyen de définir la taille d'un tableau global au moment de l'exécution.

Le contexte remplit un tableau avec une transformation linéaire des octets dans un fichier. Je ne sais pas quelle est la taille du fichier jusqu'à ce que quelqu'un veuille l'ouvrir et que les fichiers puissent être de n'importe quelle taille.

34
Arthur

Depuis Delphi 4, Delphi prend en charge tableaux dynamiques. Vous pouvez modifier leur taille au moment de l'exécution et ils conserveront les données que vous avez stockées dans d'autres éléments à l'ancienne taille. Ils peuvent contenir des éléments de tout type homogène, y compris des enregistrements et d'autres tableaux. Vous pouvez déclarer un tableau dynamique de la même manière que vous déclarez des tableaux normaux "statiques", mais simplement omettre les limites du tableau:

var
  ArthurArray: array of TForm;

Bien que les tableaux statiques vous permettent de spécifier à la fois la limite inférieure et la limite supérieure, l'index bas d'un tableau dynamique est toujours zéro. L'index élevé est donné par la fonction High, qui renvoie toujours un de moins que la longueur du tableau. Pour tout tableau dynamique x, High(x) = Length(x)-1.

Une variable globale est accessible par n'importe quel code, y compris les procédures locales.

Une variable globale de type tableau dynamique sera initialisée pour être un tableau vide . Sa longueur sera nulle et High appelée sur ce tableau sera -1. Low sur ce tableau retournera toujours zéro.

À tout moment, vous pouvez redimensionner un tableau dynamique. Utilisez la fonction SetLength, comme vous pouvez le faire avec des chaînes:

var
  NumElements: Integer;
begin
  NumElements := GetNumberOfArthurForms();
  SetLength(ArthurArray, NumElements);
end;

Si vous avez un tableau multidimensionnel, vous pouvez définir leurs longueurs dans une boucle:

var
  matrix: array of array of Double;
  i: Integer;
begin
  SetLength(matrix, height);
  for i := 0 to height - 1 do
    SetLength(matrix[i], width);
end;

Il existe un raccourci pour définir les longueurs de tous les tableaux internes à la fois:

begin
  SetLength(matrix, height, width);
end;

Comme je l'ai mentionné, les tableaux dynamiques conservent leurs anciennes valeurs lorsque vous les redimensionnez:

var
  data: array of string;
begin
  SetLength(data, 2);
  data[1] := 'foo';
  SetLength(data, 20);
  Assert(data[1] = 'foo');
end;

Mais si vous raccourcissez le tableau, tous les éléments qui résidaient au-delà du nouveau dernier élément sont définitivement perdus:

begin
  SetLength(data, 20);
  data[15] := 'foo';
  SetLength(data, 2);
  // data[15] does not exist anymore.
  SetLength(data, 16);
  writeln(data[15); // Should print an *empty* line.
end;

Mes démonstrations ci-dessus ont utilisé des chaînes. Les chaînes sont spéciales dans Delphi; ils sont gérés par le compilateur via des comptages de références. Pour cette raison, les nouveaux éléments du tableau dynamique de type chaîne sont initialisés pour être vides. Mais si j'avais utilisé des entiers à la place, il n'y aurait aucune garantie des valeurs des nouveaux éléments. Ils peuvent être nuls, mais ils peuvent aussi être autre chose, tout comme les valeurs initiales des variables locales autonomes.

Les fichiers d'aide de Delphi 7 sont très bons, me dit-on. Veuillez en savoir plus sur les tableaux dynamiques ici. Vous pouvez trouver des démonstrations de leur utilisation dans le code source VCL et RTL fourni dans votre installation Delphi, ainsi que dans presque tous les exemples de code Delphi produits au cours des 10 dernières années.

90
Rob Kennedy