Les tableaux dynamiques nécessite d'inclure <vector> dans l'en-tête :
#include <vector>
La syntaxe pour déclarer un tableau dynamique se décline en trois versions :
La saisie des données se fait comme pour un tableau statique :
vector
<int>
monTableau(3);
// Déclaration du tableau
monTableau[0] =
100;
monTableau[1] =
200;
monTableau[2] =
300;
Mais les points communs s'arrêtent là, car il n'est pas possible d'ajouter une valeur lorsque le tableau
statique est plein.
A l'inverse le tableau dynamique possède une instruction "push_back(valeur)" qui permet de poursuivre le remplissage.
Cette instruction augmente la taille du tableau d'une unité, et saisie automatiquement
en dernière position du tableau,
la valeur transmise entre parenthèse.
La ligne suivante ajoute la valeur 400 à notre tableau. Notez au passage la syntaxe particulière
avec le point de séparation entre le nom du tableau est l'instruction "push_back()".
monTableau.push_back(400);
C'est terminé ? On ne peut pas continuer le remplissage du tableau ? Et bien si, nous pouvons continuer autant de fois que nous le désirons. Pour chaque saisie, le tableau augmente sa taille d'une unité.
monTableau.push_back(500);
monTableau.push_back(600);
etc. ...
Vous allez me dire que nous allons vite perdre de vue la taille de notre tableau non ? Pas du tout car nous avons aussi à notre disposition un autre outil : l'instruction "size()". Notez à nouveau la syntaxe avec un point de séparation entre le nom du tableau et l'instruction.
int taille = monTableau.size();
La variable "taille" contient maintenant dans cet exemple la dimension de notre tableau.
D'accord pour le remplissage, mais peut-on aussi réduire la taille du tableau ?
La réponse est oui, avec l'instruction "pop_back()".
vector
<int>
monTableau(3,
0);
// Déclaration du tableau avec une taille de 3.
monTableau.pop_back();
// La dimension n'est plus que de 2.
monTableau.pop_back();
// La dimension n'est plus que de 1.
monTableau.pop_back();
// Le tableau ne contient plus aucune cellule.
Remarque : Soustraire une cellule à un tableau déjà vide conduirait à une erreur.
Découvrons maintenant un exemple complet utilisant un tableau dynamique :
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
double note,
moyenne;
string reponse;
vector
<double>
tableauDeNotes;
cout <<
"CALCUL DE MOYENNE" <<
endl
<<
endl;
do
{
cout
<<
"Saisir une note : ";
cin
>> note;
tableauDeNotes.push_back(note);
cout <<
"Dernière note ? oui...(o), non...(n) : ";
cin
>> reponse;
}while(reponse=="n");
cout <<
"Liste des notes"
<<
endl;
for(unsigned int
i = 0;
i < tableauDeNotes.size();
i++)
{
cout
<<
tableauDeNotes[i] <<
endl;
moyenne +=
tableauDeNotes[i];
}
cout
<< "Moyenne : "
<<
moyenne /
tableauDeNotes.size() <<
endl <<
endl;
system("PAUSE");
}
L'avantage de la transmission à une fonction, d'un tableau dynamique en place d'un tableau statique,
est d'éviter d'avoir à ajouter la taille de ce tableau.
En effet, cette information est maintenant disponible en interne grâce à la fonction size().
Par contre par défaut il faut savoir que la transmission se fait par valeur, et donc que la fonction
travaille uniquement sur une copie du tableau transmis.
Si le but est de modifier le tableau original, alors il vous faut adopter une transmission par référence.
Comment ?
En écrivant la fonction de cette façon (observez la présence de l'esperluette devant tab[]) :
void
maFonction(vector
<int>
&tab[])
{
// Corps de la fonction
}
L'appel de la fonction lui ne change pas :
maFonction (monTableau);
Il y a une autre raison qui doit vous faire éviter la transmission d'un tableau par valeur, c'est
la consommation de temps que génére cette transmission.
Imaginez un tableau de 1000 éléments à transférer dans une copie avant que la fonction
ne puisse agir dessus !
Une transmission par référence n'a juste besoin que de transmettre une seule variable :
l'adresse du tableau. Pour cet exemple c'est donc 1000 fois plus rapide.
D'accord je vais choisir la méthode par référence mais si je veux absolument éviter le risque qu'une
fonction puisse modifier par accident le contenu de mon tableau, je fais comment ?
Cette question me fait un peu sourire car je dirais qu'il suffit d'écrire le contenu de la fonction
pour ne pas que ça arrive. Toutefois si ça peut vous rassurer il existe une astuce qui permet
d'éviter ce désagrément tout en imposant la transmission par référence :
void
maFonction(vector
<int>
const& tab[])
{
// Corps de la fonction
}
Vous l'aviez deviné, c'est en utilisant le terme const.
Toute tentative de modifier le tableau conduirait à une erreur.
Une fonction peut-elle renvoyer un tableau ?
Oui bien sur comme ceci :
vector
<int>
maFonction()
{
// Corps de la fonction
return tableau;
}
Nous n'avons ici que le choix de la transmission par valeur, car le tableau est par principe détruit à la sortie de la fonction. La transmission de l'adresse d'un élément qui n'existe plus conduirait forcément à un plantage.