Les tableaux dans C++

de | 26 octobre 2018


Un tableau est une série d’éléments du même type placés dans des emplacements de mémoire contigus pouvant être référencés individuellement en ajoutant un index à un identifiant unique.

Cela signifie que, par exemple, cinq valeurs de type int peuvent être déclarées en tant que tableau sans avoir à déclarer 5 variables différentes (chacune avec son propre identifiant). À la place, en utilisant un tableau, les cinq valeurs int sont stockées dans des emplacements de mémoire contigus et il est possible d’accéder aux cinq en utilisant le même identifiant, avec le bon index.

Par exemple, un tableau contenant 5 valeurs entières de type int appelé toto pourrait être représenté par:

toto :

0 1 2 3 4

où chaque panneau vierge représente un élément du tableau. Dans ce cas, ce sont des valeurs de type int. Ces éléments sont numérotés de 0 à 4, 0 étant le premier et 4 le dernier; En C ++, le premier élément d’un tableau est toujours numéroté avec un zéro (pas un), quelle que soit sa longueur.

Comme une variable normale, un tableau doit être déclaré avant son utilisation. Une déclaration typique pour un tableau en C ++ est:

type nom [éléments];

où type est un type valide (tel que int, float …), nom est un identificateur valide et le champ elements (qui est toujours placé entre crochets []), spécifie la longueur du tableau en termes de nombre de éléments.

Par conséquent, le tableau toto , avec cinq éléments de type int, peut être déclaré comme:

int toto [5];

REMARQUE: le champ d’éléments entre crochets [], représentant le nombre d’éléments dans le tableau, doit être une expression constante, car les tableaux sont des blocs de mémoire statique dont la taille doit être déterminée à la compilation, avant l’exécution du programme.

Initialisation des tableaux

Par défaut, les tableaux classiques de portée locale (par exemple, ceux déclarés dans une fonction) ne sont pas initialisés. Cela signifie qu’aucun de ses éléments n’est défini sur une valeur particulière; leur contenu est indéterminé au moment où le tableau est déclaré.

Mais les éléments d’un tableau peuvent être explicitement initialisés avec des valeurs spécifiques lors de sa déclaration, en les entourant entre accolades {}. Par exemple:

int toto [5] = {9, 3, 15, 20, 2007};

Cette déclaration déclare un tableau qui peut être représenté comme ceci:

toto :

0 1 2 3 4
9 3 15 20 2007

Le nombre de valeurs entre accolades {} ne doit pas être supérieur au nombre d’éléments du tableau. Par exemple, dans l’exemple ci-dessus, toto a été déclaré comportant 5 éléments (comme indiqué par le nombre entre crochets, []), et les accolades {} contenaient exactement 5 valeurs, une pour chaque élément. Si déclaré avec moins, les éléments restants sont définis sur leurs valeurs par défaut (ce qui, pour les types fondamentaux, signifie qu’ils sont remplis de zéros). Par exemple:

int titi [5] = {10, 20, 30};

Va créer un tableau comme ceci:

titi :

0 1 2 3 4
10 20 30 0 0

L’initialiseur peut même ne pas avoir de valeur, juste les accolades:

int car [5] = {};

Cela crée un tableau de cinq valeurs int, chacune initialisée avec une valeur de zéro:

car :

0 1 2 3 4
0 0 0 0 0

Lorsqu’une initialisation de valeurs est fournie pour un tableau, C ++ permet de laisser les crochets vides []. Dans ce cas, le compilateur assumera automatiquement une taille pour le tableau qui correspond au nombre de valeurs incluses entre les accolades {}:

int toto [] = {16, 2, 77, 40, 12071};

Après cette déclaration, le tableau toto aurait une longueur de 5 int, puisque nous avons fourni 5 valeurs d’initialisation.

Enfin, l’évolution du C ++ a conduit à l’adoption de l’initialisation universelle également pour les tableaux. Par conséquent, le signe égal entre la déclaration et l’initialiseur n’est plus nécessaire. Ces deux déclarations sont équivalentes:

int toto [] = {10, 20, 30};
int toto [] {10, 20, 30};

Les tableaux statiques et ceux déclarés directement dans un espace de noms (en dehors de toute fonction) sont toujours initialisés. Si aucun initialiseur explicite n’est spécifié, tous les éléments sont initialisés par défaut (avec des zéros, pour les types fondamentaux).

Accéder aux valeurs d’un tableau

Les valeurs de n’importe quel élément d’un tableau peuvent être consultées comme la valeur d’une variable régulière du même type. La syntaxe est la suivante:

nom [index]

Suivant les exemples précédents dans lesquels toto avait 5 éléments et chacun de ces éléments était de type int, le nom qui peut être utilisé pour faire référence à chaque élément est le suivant:

toto(0) toto(1) toto(2) toto(3) toto(4)

Par exemple, l’instruction suivante stocke la valeur 75 dans le troisième élément de toto:

toto [2] = 75;

et, par exemple, ce qui suit copie la valeur du troisième élément de toto dans une variable appelée x:

 x = toto [2];

Par conséquent, l’expression toto [2] est elle-même une variable de type int.

Notez que le troisième élément de toto est spécifié toto [2], puisque le premier est toto [0], le deuxième est toto [1] et que, par conséquent, le troisième est toto [2]. Pour cette même raison, son dernier élément est toto [4]. Par conséquent, si nous écrivons toto [5], nous accéderions au sixième élément de toto et dépasserions donc réellement la taille du tableau.

En C ++, il est correct sur le plan syntaxique de dépasser la plage d’index valide pour un tableau. Cela peut créer des problèmes, car l’accès à des éléments hors de portée ne provoque pas d’erreurs lors de la compilation, mais peut provoquer des erreurs lors de l’exécution. La raison de cette autorisation sera vue dans un chapitre ultérieur lorsque les pointeurs seront introduits.

À ce stade, il est important de pouvoir distinguer clairement les deux utilisations que les crochets [] ont associées aux tableaux. Ils effectuent deux tâches différentes: l’une consiste à spécifier la taille des tableaux lorsqu’ils sont déclarés; et le second consiste à spécifier des index pour les éléments de tableau concrets lors de leur accès. Ne confondez pas ces deux utilisations possibles des crochets [] avec des tableaux.

int toto [5]; // déclaration d'un nouveau tableau
toto [2] = 75; // accès à un élément du tableau.

La principale différence est que la déclaration est précédée du type des éléments, tandis que l’accès ne l’est pas.

Quelques autres opérations valides avec des tableaux:

toto [0] = a;
toto [a] = 75;
b = toto [a + 2];
toto [toto [a]] = toto [2] + 5;

Par exemple:

// exemple de tableaux
#include <iostream>
using namespace std;

int toto [] = {16, 2, 77, 40, 12071};
int n, résultat = 0;

int main ()
{
  pour (n = 0; n <5; ++ n)
  {
    résultat + = toto [n];
  }
  cout << résultat;
  return 0;
}

Résultat :

12206

Les tableaux multidimensionnels

Les tableaux multidimensionnels peuvent être décrits comme des « tableaux de tableaux ». Par exemple, un tableau bidimensionnel peut être imaginé comme une table bidimensionnelle constituée d’éléments, tous d’un même type de données uniforme.

0 1 2 3 4
0
1
2
3

immy représente un tableau bidimensionnel de 3 pour 5 éléments de type int. La syntaxe C ++ utilisée est la suivante:

int hed [3] [5];

et, par exemple, la manière de référencer le deuxième élément verticalement et le quatrième horizontalement dans une expression serait:

hed [1] [3]

(rappelez-vous que les indices de tableau commencent toujours par zéro).

Les tableaux multidimensionnels ne sont pas limités à deux indices (c.-à-d. Deux dimensions). Ils peuvent contenir autant d’indices que nécessaire. Attention, la quantité de mémoire nécessaire à un tableau augmente de manière exponentielle avec chaque dimension. Par exemple:

string siecle [100] [365] [24] [60] [60];

déclare un tableau avec un élément de type char pour chaque seconde du siecle. Cela représente plus de 3 milliards de caractères! Donc, cette déclaration consomme plus de 3 gigaoctets de mémoire!

À la fin, les tableaux multidimensionnels ne sont qu’une abstraction pour les programmeurs, car les mêmes résultats peuvent être obtenus avec un tableau simple, en multipliant ses indices:

int hed [3] [5]; // est équivalent à
int hed [15]; // (3 * 5 = 15)

À la seule différence qu’avec les tableaux multidimensionnels, le compilateur se souvient automatiquement de la profondeur de chaque dimension imaginaire. Les deux morceaux de code suivants produisent exactement le même résultat, mais l’un utilise un tableau bidimensionnel, tandis que l’autre utilise un tableau simple:

Tableau multi-dimensionel Tableau pseudo multi-dimensionel
#define WIDTH 5
#define HEIGHT 3int hed [HEIGHT][WIDTH];
int n,m;int main ()
{
for (n=0; n<HEIGHT; n++)
for (m=0; m<WIDTH; m++)
{
hed[n][m]=(n+1)*(m+1);
}
}
#define WIDTH 5
#define HEIGHT 3int hed [HEIGHT * WIDTH];
int n,m;int main ()
{
for (n=0; n<HEIGHT; n++)
for (m=0; m<WIDTH; m++)
{
hed[n*WIDTH+m]=(n+1)*(m+1);
}
}

Aucun des deux extraits de code ci-dessus ne produit de sortie à l’écran, mais les deux attribuent des valeurs au bloc de mémoire appelé hed de la manière suivante:

0 1 2 3 4
0 1 2 3 4 5
1 2 4 6 8 10
2 3 6 9 12 15

Notez que le code utilise des constantes définies pour la largeur et la hauteur, au lieu d’utiliser directement leurs valeurs numériques. Cela donne au code une meilleure lisibilité et permet de modifier facilement le code en un seul endroit.

Tableaux en paramètres

À un moment donné, il peut être nécessaire de passer un tableau à une fonction en tant que paramètre. En C ++, il n’est pas possible de transmettre le bloc entier de mémoire représenté par un tableau à une fonction directement sous forme d’argument. Mais ce qui peut être transmis à la place est son adresse. En pratique, cela a presque le même effet et il s’agit d’une opération beaucoup plus rapide et plus efficace.

Pour accepter un tableau en tant que paramètre pour une fonction, les paramètres peuvent être déclarés en tant que type de tableau, mais avec des crochets vides, en omettant la taille réelle du tableau. Par exemple:

void procedure (int arg [])

Cette fonction accepte un paramètre de type « tableau d’entiers » appelé arg. Afin de passer à cette fonction un tableau déclaré comme:

int myarray [40];

il suffirait d’écrire un appel comme celui-ci:

procedure (myarray);

Ici vous avez un exemple complet:

// tableaux comme paramètres
#include <iostream>
using namespace std;

void printarray (int arg [], int length) {
  pour (int n = 0; n <longueur; ++ n)
    cout << arg [n] << '';
  cout << '\ n';
}

int main ()
{
  int firstarray [] = {5, 10, 15};
  int secondarray [] = {2, 4, 6, 8, 10};
  printarray (firstarray, 3);
  printarray (secondarray, 5);
}

Résultat de l’exécution :

5 10 15
2 4 6 8 10
Modifier et exécuter

Dans le code ci-dessus, le premier paramètre (int arg []) accepte tout tableau dont les éléments sont de type int, quelle que soit sa longueur. Pour cette raison, nous avons inclus un deuxième paramètre indiquant à la fonction la longueur de chaque tableau que nous lui transmettons en tant que premier paramètre. Cela permet à la boucle for qui imprime le tableau de connaître la plage à itérer dans le tableau transmis, sans sortir de la plage.

Dans une déclaration de fonction, il est également possible d’inclure des tableaux multidimensionnels. Le format d’un paramètre de tableau tridimensionnel est le suivant:

type_base [] [profondeur] [profondeur]

Par exemple, une fonction avec un tableau multidimensionnel en argument pourrait être:

void procedure (int myarray [] [3] [4])

Notez que les premiers crochets [] sont laissés vides, tandis que les suivants spécifient des tailles pour leurs dimensions respectives. Cela est nécessaire pour que le compilateur puisse déterminer la profondeur de chaque dimension supplémentaire.

D’une certaine manière, passer un tableau en argument perd toujours une dimension. La raison derrière cela est que, pour des raisons historiques, les tableaux ne peuvent pas être copiés directement, et donc ce qui est réellement passé est un pointeur. Ceci est une source d’erreur commune pour les programmeurs débutants. Bien qu’une compréhension claire des pointeurs, expliquée dans un chapitre suivant,




Catégorie : C++

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *