Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.
collection [2015/08/29 22:41] winjerome |
collection [2017/08/23 12:45] (Version actuelle) gbdivers |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | ^ Chapitre précédent ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ Chapitre suivant ^ | + | ^ [[nombres_aleatoires|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[map|Chapitre suivant]] ^ |
- | ====== Les collections de données ====== | ||
- | L'une des difficultés principales que vous aurez à résoudre en tant que développeur est de définir comment les données doivent être organisées en mémoire (structures de données) et comment ces données doivent être traitées (algorithmes). Il est intéressant, dès que cela est possible, de séparer ces deux aspects du problème dans des classes différentes, pour renforcer la réutilisabilité du code que vous écrivez. La bibliothèque standard du C++ est organisée de cette façon, avec d'un côté des classes de structures de données (''string'' pour les chaînes, ''vector'' pour les tableaux, etc.) et des fonctions libres pour le traitement des données (regroupées dans le fichier d'en-tête ''<algorithms>''). | + | ====== Le concept de collections de données ====== |
- | Pour qu'un code soit réutilisable au maximum, l'idéal serait que n'importe quelle structure de données soit compatible avec n'importe quel algorithme. Dit autrement, cela veut dire que si vous créez une structure de données, elle doit être utilisable avec n'importe quel algorithme de la bibliothèque standard et que si vous créez une algorithme, il doit être utilisable avec n'importe quelle structure de données de la bibliothèque standard. Pour cela, les structures de données sont conçues autour du concept de collection, que vous allez voir dans ce chapitre. | + | L'une des difficultés principales que vous aurez à résoudre en tant que développeur est de définir comment les données doivent être organisées en mémoire (structures de données) et comment ces données doivent être traitées (algorithmes). Il est intéressant, dès que cela est possible, de séparer ces deux aspects du problème dans des classes différentes, pour renforcer la réutilisabilité du code que vous écrivez. La bibliothèque standard du C++ est organisée de cette façon, avec d'un côté des classes de structures de données (''std::string'' pour les chaînes, ''std::vector'' pour les tableaux, etc.) et des fonctions libres pour le traitement des données (regroupées dans le fichier d'en-tête ''<algorithms>''). |
+ | |||
+ | Pour qu'un code soit réutilisable au maximum, l'idéal serait que n'importe quelle structure de données soit compatible avec n'importe quel algorithme. Dit autrement, cela veut dire que si vous créez une structure de données, elle doit être utilisable avec n'importe quel algorithme de la bibliothèque standard et que si vous créez un algorithme, il doit être utilisable avec n'importe quelle structure de données de la bibliothèque standard. Pour cela, les structures de données sont conçues autour du concept de collection, que vous allez voir dans ce chapitre. | ||
===== Les chaînes comme collection de caractères ===== | ===== Les chaînes comme collection de caractères ===== | ||
Ligne 24: | Ligne 25: | ||
// début de la collection | // début de la collection | ||
- | s.begin(); // fonction membre | + | s.begin(); // fonction membre |
std::begin(s); // fonction libre | std::begin(s); // fonction libre | ||
// fin de la collection | // fin de la collection | ||
- | s.end(); // fonction membre | + | s.end(); // fonction membre |
std::end(s); // fonction libre | std::end(s); // fonction libre | ||
</code> | </code> | ||
- | Les algorithmes de la bibliothèque standard s'appliquent sur une collection en donnant en argument le premier et le dernier élément de la collection sur laquelle on souhaite appliquer l'algorithme. Par exemple, pour appliquer l'algorithme ''sort'' (qui permet de trier les éléments d'une collection), on écrira : | + | Les algorithmes de la bibliothèque standard s'appliquent sur une collection en donnant en argument le premier et le dernier élément de la collection sur laquelle on souhaite appliquer l'algorithme. Par exemple, pour appliquer l'algorithme ''std::sort'' (qui permet de trier les éléments d'une collection), on écrira : |
<code cpp> | <code cpp> | ||
Ligne 62: | Ligne 63: | ||
</note> | </note> | ||
- | Il est également possible de parcourir une collection du dernier élément au premier élément en utilisant les fonctions ''rbegin'' (//reverse begin//) et ''rend'' (//reverse end//). Ces fonctions sont utilisables uniquement en fonctions membres. | + | Notez bien que même si ''std::string'' est une collection, c'est un cas particulier lorsque vous l'utilisez avec ''std::cout''. Dans ce cas, ''std::string'' n'est pas affichée comme un collection, mais bien comme une chaîne de caractères. Ce qui veut dire que dans le cas général de n'importe quelle collection, vous ne pouvez pas afficher directement son contenu avec ''std::cout''. Un code d'exemple est donné a la fin de ce chapitre pour afficher le contenu d'une collection. |
- | + | ||
- | Par exemple, il est possible de trier dans l'ordre inverse de cette manière : | + | |
<code cpp> | <code cpp> | ||
- | #include <iostream> | + | std::vector<int> v { 1, 2, 3 }; |
- | #include <string> | + | std::cout << v << std::endl; // erreur |
- | #include <algorithm> | + | |
- | + | ||
- | int main() { | + | |
- | std::string s { "azerty" }; | + | |
- | + | ||
- | std::sort(std::begin(s), std::end(s)); | + | |
- | std::cout << s << std::endl; | + | |
- | + | ||
- | std::sort(s.rbegin(), s.rend()); | + | |
- | std::cout << s << std::endl; | + | |
- | } | + | |
</code> | </code> | ||
- | affiche : | ||
- | <code> | + | ===== Templates et généricité ===== |
- | aertyz | + | |
- | zytrea | + | |
- | </code> | + | |
- | + | ||
- | ===== Généralisation des collections : les tableaux ===== | + | |
Les données que vous aurez à manipuler ne se limiteront pas aux chaînes de caractères. Heureusement, la bibliothèque standard fournit d'autres structures de données, qui permettent de manipuler n'importe quel type de données dans une collection. | Les données que vous aurez à manipuler ne se limiteront pas aux chaînes de caractères. Heureusement, la bibliothèque standard fournit d'autres structures de données, qui permettent de manipuler n'importe quel type de données dans une collection. | ||
- | La [[http://en.cppreference.com/w/cpp/container|page de documentation des conteneurs de la bibliothèque standard]] liste une quinzaine de types différents de structures de données. Nous n'allons voir dans ce chapitre que les tableaux de type ''vector'' et ''array'', les autres conteneurs seront vus dans des prochains chapitres. La différence entre ces deux types de tableau est que ''array'' représente un tableau dont le nombre d'éléments (on parle de la "taille du tableau") est fixé à la compilation, tandis que le nombre d'éléments de ''vector'' peut être modifié durant l'exécution. | + | La [[http://en.cppreference.com/w/cpp/container|page de documentation des conteneurs de la bibliothèque standard]] liste une quinzaine de types différents de structures de données. Nous n'allons voir dans ce chapitre que les tableaux de type ''std::vector'' et ''std::array'', les autres conteneurs seront vus dans des prochains chapitres. La différence entre ces deux types de tableau est que ''std::array'' représente un tableau dont le nombre d'éléments (on parle de la "taille du tableau") est fixé à la compilation, tandis que le nombre d'éléments de ''std::vector'' peut être modifié durant l'exécution. |
- | + | ||
- | ==== Templates et généricité ==== | + | |
Les conteneurs de données sont des classes, au même titre que ''std::string''. Pour déclarer un tableau, on utilisera donc la même syntaxe que pour déclarer une chaîne. Par exemple, pour créer un tableau vide d'entiers, on écrira : | Les conteneurs de données sont des classes, au même titre que ''std::string''. Pour déclarer un tableau, on utilisera donc la même syntaxe que pour déclarer une chaîne. Par exemple, pour créer un tableau vide d'entiers, on écrira : | ||
<code cpp> | <code cpp> | ||
- | std::vector<int> const integers {}; | + | std::vector<int> integers {}; |
</code> | </code> | ||
Dans ce code, ''integers'' est le nom de la variable qui contient le tableau d'entiers (//integers// signifie "des entiers" - prenez l'habitude d'écrire vos codes en anglais, en particulier pour nommer vos variables, fonctions et classes). Le type de tableau est ''vector<int>'', que l'on peut lire directement comme étant un tableau (''vector'') d'entiers (''int''). | Dans ce code, ''integers'' est le nom de la variable qui contient le tableau d'entiers (//integers// signifie "des entiers" - prenez l'habitude d'écrire vos codes en anglais, en particulier pour nommer vos variables, fonctions et classes). Le type de tableau est ''vector<int>'', que l'on peut lire directement comme étant un tableau (''vector'') d'entiers (''int''). | ||
- | La syntaxe de ''vector'' est un peu particulière. C'est ce que l'on appelle une classe template (ou classe générique). Vous avez déjà rencontré cette syntaxe dans le chapitre [[informations_sur_les_types|]], pour la classe ''std::numeric_limits''. | + | La syntaxe de ''std::vector'' est un peu particulière, c'est ce que l'on appelle une classe template (ou classe générique). Vous avez déjà rencontré cette syntaxe dans le chapitre [[informations_sur_les_types|]], pour la classe ''std::numeric_limits''. La syntaxe générale de ''std::vector'' est la suivante : |
+ | |||
+ | <code cpp> | ||
+ | std::vector<TYPE> | ||
+ | </code> | ||
Imaginons que l'on vous demande de créer un telle classe, qui permette de manipuler des tableaux de données. Une première approche serait d'écrire une classe représentant un tableau d'entier ''vector_int'', puis de la dupliquer et de modifier cette classe pour manipuler un tableau de doubles ''vector_double''. Et ainsi de suite pour chaque type que l'on souhaite manipuler. | Imaginons que l'on vous demande de créer un telle classe, qui permette de manipuler des tableaux de données. Une première approche serait d'écrire une classe représentant un tableau d'entier ''vector_int'', puis de la dupliquer et de modifier cette classe pour manipuler un tableau de doubles ''vector_double''. Et ainsi de suite pour chaque type que l'on souhaite manipuler. | ||
Ligne 113: | Ligne 97: | ||
Le second problème est qu'il ne sera pas possible de prendre en charge tous les types. Un utilisateur de votre code qui crée ses propres types devra copier votre code et le modifier pour prendre en charge ses propres types. C'est une autre source d'erreur importante, le code n'est pas évolutif. | Le second problème est qu'il ne sera pas possible de prendre en charge tous les types. Un utilisateur de votre code qui crée ses propres types devra copier votre code et le modifier pour prendre en charge ses propres types. C'est une autre source d'erreur importante, le code n'est pas évolutif. | ||
- | Les templates permettent d'écrire des classes et fonctions dont le comportement dépendra d'informations données à la compilation. Les informations données peuvent être un type ou une valeur entière. Les classes ''vector'' et ''array'' sont des exemples de template. Ces classes sont conçues pour accepter n'importe quel type de données, en particulier les types que vous créerez. Ce type d'approche présente de nombreux avantages : | + | Les templates permettent d'écrire des classes et fonctions dont le comportement dépendra d'informations données à la compilation. Les informations données peuvent être un type ou une valeur entière. Les classes ''vector'' et ''std::array'' sont des exemples de template. Ces classes sont conçues pour accepter n'importe quel type de données, en particulier les types que vous créerez. Ce type d'approche présente de nombreux avantages : |
* maintenabilité : le code n'est pas dupliqué. S'il doit être corrigé, il suffit de corriger une seule implémentation et tous les codes utilisant cette classe seront corrigés en même temps. | * maintenabilité : le code n'est pas dupliqué. S'il doit être corrigé, il suffit de corriger une seule implémentation et tous les codes utilisant cette classe seront corrigés en même temps. | ||
Ligne 140: | Ligne 124: | ||
Vous apprendrez par la suite différentes approches pour écrire du code générique performant, mais dans un premier temps, voyons comment utiliser de telles classes template. | Vous apprendrez par la suite différentes approches pour écrire du code générique performant, mais dans un premier temps, voyons comment utiliser de telles classes template. | ||
+ | |||
+ | |||
+ | ===== Les tableaux comme collections ===== | ||
+ | |||
+ | Les tableaux étant des collections, il est possible d'utiliser les fonctions ''begin'' et ''end'' pour obtenir respectivement le début et la fin d'un tableau. Ces fonctions sont également utilisables comme fonctions membres ou fonctions libres. Par exemple, avec la fonction de tri ''sort'' : | ||
+ | |||
+ | <code cpp> | ||
+ | std::sort(a.begin(), a.end()); // fonctions membres | ||
+ | std::sort(std::begin(a), std::end(a)); // fonctions libres | ||
+ | </code> | ||
+ | |||
+ | Au final, vous n'avez besoin que de connaître ces deux fonctions, ''begin'' et ''end'', pour utiliser une collection avec les algorithmes de la bibliothèque standard. Il existe d'autres types de collection que ''std::array'' et ''std::list'', n'hésitez pas à parcourir la page de documentation correspondante aux [[http://en.cppreference.com/w/cpp/container|conteneurs de données]] et à en tester quelques uns. | ||
==== Déclarer et initialiser des tableaux ==== | ==== Déclarer et initialiser des tableaux ==== | ||
- | La classe ''vector'' prend un seul argument template, qui est le type de données que le tableau doit contenir. La classe ''array'' prend deux arguments : le type de données et le nombre d'éléments que doit contenir le tableau. Par exemple, pour créer des tableaux vides : | + | La classe ''std::vector'' prend un seul argument template, qui est le type de données que le tableau doit contenir. La classe ''std::array'' prend deux arguments : le type de données et le nombre d'éléments que doit contenir le tableau. Leur syntaxe est donc la suivante : |
<code cpp> | <code cpp> | ||
+ | std::vector<TYPE> | ||
+ | std::array<TYPE, TAILLE> | ||
+ | </code> | ||
+ | |||
+ | Par exemple, pour créer des tableaux : | ||
+ | |||
+ | <code cpp> | ||
+ | // tableau d'entiers, la taille peut changer à l'exécution | ||
std::vector<int> const integers {}; | std::vector<int> const integers {}; | ||
+ | |||
+ | // tableau de 5 nombres réels, la taille est fixe | ||
std::array<float, 5> const floats {}; | std::array<float, 5> const floats {}; | ||
</code> | </code> | ||
- | Remarque : pour rappel, le but de ce cours n'est pas de vous présenter toutes les syntaxes possibles, mais celles qui sont utiles à connaître pour comprendre les bases du C++. Il est possible d'utiliser d'autres syntaxes pour les classes ''vector'' et ''array'', mais la compréhension de ces syntaxes nécessite des connaissances plus avancées en C++. | + | Par défaut, ''std::vector'' ne contient pas d'éléments lors de l'initialisation de la variable ''integers''. Comme ''std::vector'' est un tableau de taille redimensionnable, vous pourrez ajouter des éléments par la suite. |
+ | |||
+ | Au contraire, ''std::array'' est initialisé avec cinq éléments dans le code précédent. Il est possible de créer une ''std::array'' avec aucun élément, mais comme il n'est pas possible d'ajouter des éléments, l'intérêt est limité. | ||
+ | |||
+ | <note>Remarque : pour rappel, le but de ce cours n'est pas de vous présenter toutes les syntaxes possibles, mais celles qui sont utiles à connaître pour comprendre les bases du C++. Il est possible d'utiliser d'autres syntaxes pour les classes ''std::vector'' et ''std::array'', mais la compréhension de ces syntaxes nécessite des connaissances plus avancées en C++.</note> | ||
- | Il est possible d’initialiser ''vector'' avec un nombre déterminé d'éléments, comme pour ''array''. Pour cela, il faut donner ce nombre entre parenthèses : | + | Il est possible d’initialiser ''std::vector'' avec un nombre déterminé d'éléments, comme pour ''std::array''. Pour cela, il faut donner ce nombre entre parenthèses : |
<code cpp> | <code cpp> | ||
Ligne 158: | Ligne 168: | ||
</code> | </code> | ||
- | On retrouve ici la différence de syntaxe entre argument template et argument de fonction. Pour ''array'', la taille du tableau (nombre d'éléments) est fixée à la compilation, c'est donc un argument template (entre chevrons). Pour ''vector'', la taille est variable durant l'exécution, c'est donc un argument de fonction (entre parenthèses). | + | On retrouve ici la différence de syntaxe entre argument //template// et argument de fonction. Pour ''std::array'', la taille du tableau (nombre d'éléments) est fixée à la compilation, c'est donc un argument //template// (entre chevrons). Pour ''std::vector'', la taille est variable durant l'exécution, c'est donc un argument de fonction (entre parenthèses). |
- | Dans les deux cas, il est possible de connaître la taille d'un tableau en utilisant la fonction ''size''. | + | <note>**Accolades et parentheses** |
+ | |||
+ | Remarquez bien ici l'utilisation des parenthèses au lieu des accolades, ce n'est pas une erreur de frappe. | ||
+ | |||
+ | Les accolades permettent de définir une liste de valeurs, qui seront insérées directement dans une collection. Les parenthèses permettent d'appeler un constructeur (une fonction spéciale permettant d'initialiser une classe). | ||
+ | </note> | ||
+ | |||
+ | Dans les deux cas, il est possible de connaître la taille d'un tableau en utilisant la fonction membre ''size''. | ||
<code cpp main.cpp> | <code cpp main.cpp> | ||
Ligne 182: | Ligne 199: | ||
</code> | </code> | ||
- | Vous pouvez donner des valeurs entre les crochets pour initialiser le tableau. Une liste de valeurs (//initializer-list//) s'écrit entre crochets, avec des virgules comme séparateurs. | + | Vous pouvez donner des valeurs entre les accolades pour initialiser le tableau. Une liste de valeurs (//initializer-list//) s'écrit entre accolades, avec des virgules comme séparateurs. |
<code cpp> | <code cpp> | ||
Ligne 191: | Ligne 208: | ||
Remarque : pour rappel, l'utilisation des espaces est libre en C++. Le critère principal doit être la lisibilité du code. Il est tout à fait possible d'écrire les listes de valeurs sous forme compacte ''{0,1,2,3}''. Peu importe comment vous souhaitez présenter vos codes, mais essayez de respecter des conventions d'écriture (même informelles) dans vos codes, pour que les syntaxes soient homogènes. | Remarque : pour rappel, l'utilisation des espaces est libre en C++. Le critère principal doit être la lisibilité du code. Il est tout à fait possible d'écrire les listes de valeurs sous forme compacte ''{0,1,2,3}''. Peu importe comment vous souhaitez présenter vos codes, mais essayez de respecter des conventions d'écriture (même informelles) dans vos codes, pour que les syntaxes soient homogènes. | ||
- | Dans ce code, les deux tableaux sont initialisés avec les valeurs 0 à 3. ''vector'' étant un tableau dynamique, sa taille est initialisée en fonction du nombre d'éléments donné dans la liste. Ce qui signifie que ''integers'' contient 4 éléments dans ce code. Au contraire, la taille de ''array'' est fixée par le second argument template et non par le nombre d'éléments dans la liste. ''floats'' contient donc 5 éléments, les 4 premiers correspondant aux valeurs données dans la liste, le dernier est initialisé par défaut (avec la valeur 0 donc). | + | Dans ce code, les deux tableaux sont initialisés avec les valeurs 0 à 3. ''std::vector'' étant un tableau dynamique, sa taille est initialisée en fonction du nombre d'éléments donné dans la liste. Ce qui signifie que ''integers'' contient 4 éléments dans ce code. Au contraire, la taille de ''std::array'' est fixée par le second argument template et non par le nombre d'éléments dans la liste. ''floats'' contient donc 5 éléments, les 4 premiers correspondant aux valeurs données dans la liste, le dernier est initialisé par défaut (avec la valeur 0 donc). |
- | ==== Modifier un tableau ==== | + | ==== Modifier la taille d'un tableau ==== |
- | Comme ''array'' est un tableau de taille fixée à la compilation, il n'est pas possible d'ajouter ou de supprimer des éléments lors de l'exécution du programme. Cette partie ne s'applique donc qu'aux tableaux de type ''vector''. | + | Comme ''std::array'' est un tableau de taille fixée à la compilation, il n'est pas possible d'ajouter ou de supprimer des éléments lors de l'exécution du programme. Cette partie ne s'applique donc qu'aux tableaux de type ''vector''. |
- | Les tableaux de type ''vector'' peuvent être manipulés comme des piles. Une pile est une collection qui permet de lire, supprimer (//pop//) ou ajouter (//push//) des éléments à la fin de la collection (//back//). Les noms des fonctions membres sont assez simples à comprendre (même si vous ne comprenez pas très bien l'anglais) : | + | Les tableaux de type ''std::vector'' peuvent être manipulés comme des piles. Une pile est une collection qui permet de lire, supprimer (//pop//) ou ajouter (//push//) des éléments à la fin de la collection (//back//). Les noms des fonctions membres sont assez simples à comprendre (même si vous ne comprenez pas très bien l'anglais) : |
* ''back'' permet d'accéder au dernier élément, pour le lire ou le modifier ; | * ''back'' permet d'accéder au dernier élément, pour le lire ou le modifier ; | ||
Ligne 239: | Ligne 256: | ||
<note>Il existe également une collection qui permet d'être agrandie ou rétrécie depuis le premier et le dernier élément : [[http://en.cppreference.com/w/cpp/container/deque|std::deque]]. Son utilisation est assez similaire à ''std::vector'', vous verrez dans les exercices d'application comment l'utiliser.</note> | <note>Il existe également une collection qui permet d'être agrandie ou rétrécie depuis le premier et le dernier élément : [[http://en.cppreference.com/w/cpp/container/deque|std::deque]]. Son utilisation est assez similaire à ''std::vector'', vous verrez dans les exercices d'application comment l'utiliser.</note> | ||
+ | |||
===== Afficher le contenu d'une collection ===== | ===== Afficher le contenu d'une collection ===== | ||
- | Pour accéder à chaque élément individuellement, il est nécessaire de faire intervenir la notion d'itérateur et de boucles, ce qui sera vu dans la suite ce cours. Cependant, il est intéressant de voir rapidement la syntaxe permettant d'afficher le contenu d'une collection. Pour cela, vous pouvez utiliser la syntaxe suivante : | + | Pour afficher le contenu d'une collection, il n'est pas possible d'utiliser directement ''std::cout'' dessus. Il faut afficher individuellement chaque élément avec ''std::cout'', ce qui implique de voir comment parcourir une collection. Vous verrez cela dans la suite du cours, pour le moment, voici deux syntaxes pour faire cela. |
- | <code cpp> | + | ==== Avec un algorithme ==== |
- | for (auto const value: integers ) | + | |
- | std::cout << value << std::endl; | + | |
- | </code> | + | |
- | Ce code se lit de la façon suivante : "pour (//for//) chaque élément d'une collection (''integers'' dans ce code), afficher la valeur avec ''cout''". Ce code est relativement générique, vous pouvez l'utiliser avec n'importe quelle collection de données dont le type peut être affiché avec ''cout''. | + | Une première solution est en fait de copier (avec l'algorithme ''std::copy'') chaque élément dans le flux de sortie standard (''std::cout''). |
<code cpp main.cpp> | <code cpp main.cpp> | ||
Ligne 255: | Ligne 270: | ||
#include <vector> | #include <vector> | ||
#include <string> | #include <string> | ||
+ | #include <algorithm> | ||
+ | #include <iterator> | ||
int main() { | int main() { | ||
std::vector<int> const i { 1, 2, 3, 4 }; | std::vector<int> const i { 1, 2, 3, 4 }; | ||
- | for (auto const value: i) | + | copy(begin(i), end(i), std::ostream_iterator<int>(std::cout, "\t")); |
- | std::cout << value << std::endl; | + | |
std::cout << std::endl; | std::cout << std::endl; | ||
std::vector<double> const d { 1.2, 3.4, 5.6, 7.8 }; | std::vector<double> const d { 1.2, 3.4, 5.6, 7.8 }; | ||
- | for (auto const value: d) | + | copy(begin(d), end(d), std::ostream_iterator<double>(std::cout, "\t")); |
- | std::cout << value << std::endl; | + | |
std::cout << std::endl; | std::cout << std::endl; | ||
std::vector<std::string> const s { "un", "deux", "trois", "quatre" }; | std::vector<std::string> const s { "un", "deux", "trois", "quatre" }; | ||
- | for (auto const value: s) | + | copy(begin(s), end(s), std::ostream_iterator<std::string>(std::cout, "\t")); |
- | std::cout << value << std::endl; | + | |
std::cout << std::endl; | std::cout << std::endl; | ||
} | } | ||
Ligne 277: | Ligne 291: | ||
<code> | <code> | ||
- | 1 | + | 1 2 3 4 |
- | 2 | + | 1.2 3.4 5.6 7.8 |
- | 3 | + | un deux trois quatre |
- | 4 | + | </code> |
- | 1.2 | ||
- | 3.4 | ||
- | 5.6 | ||
- | 7.8 | ||
- | un | + | ==== Avec une boucle ==== |
- | deux | + | |
- | trois | + | Pour accéder à chaque élément individuellement, il est nécessaire de faire intervenir la notion d'itérateur et de boucles, ce qui sera vu dans la suite de ce cours. Cependant, il est intéressant de voir rapidement la syntaxe permettant d'afficher le contenu d'une collection. Pour cela, vous pouvez utiliser la syntaxe suivante : |
- | quatre | + | |
+ | <code cpp> | ||
+ | for (auto const value: integers ) | ||
+ | std::cout << value << std::endl; | ||
</code> | </code> | ||
- | Bien sûr, comme une chaîne de caractères ''string'' peut être vue comme une collection, il est également possible d'utiliser cette syntaxe pour afficher les caractères individuellement. | + | Ce code se lit de la façon suivante : "pour (//for//) chaque élément d'une collection (''integers'' dans ce code), afficher la valeur avec ''std::cout''". Ce code est relativement générique, vous pouvez l'utiliser avec n'importe quelle collection de données dont le type peut être affiché avec ''std::cout''. |
<code cpp main.cpp> | <code cpp main.cpp> | ||
#include <iostream> | #include <iostream> | ||
+ | #include <vector> | ||
#include <string> | #include <string> | ||
int main() { | int main() { | ||
- | std::string const s { "hello, wolrd!" }; | + | std::vector<int> const i { 1, 2, 3, 4 }; |
+ | for (auto const value: i) | ||
+ | std::cout << value << '\t'; | ||
+ | std::cout << std::endl; | ||
+ | |||
+ | std::vector<double> const d { 1.2, 3.4, 5.6, 7.8 }; | ||
+ | for (auto const value: d) | ||
+ | std::cout << value << '\t'; | ||
+ | std::cout << std::endl; | ||
+ | |||
+ | std::vector<std::string> const s { "un", "deux", "trois", "quatre" }; | ||
for (auto const value: s) | for (auto const value: s) | ||
- | std::cout << value << std::endl; | + | std::cout << value << '\t'; |
+ | std::cout << std::endl; | ||
} | } | ||
</code> | </code> | ||
Ligne 309: | Ligne 334: | ||
<code> | <code> | ||
- | h | + | 1 2 3 4 |
- | e | + | 1.2 3.4 5.6 7.8 |
- | l | + | un deux trois quatre |
- | l | + | |
- | o | + | |
- | , | + | |
- | + | ||
- | w | + | |
- | o | + | |
- | l | + | |
- | r | + | |
- | d | + | |
- | ! | + | |
</code> | </code> | ||
- | ===== Les tableaux comme collections ===== | + | Bien sûr, comme une chaîne de caractères ''std::string'' peut être vue comme une collection, il est également possible d'utiliser cette syntaxe pour afficher les caractères individuellement. |
- | Naturellement, les tableaux étant des collections, il est possible d'utiliser les fonctions ''begin'' et ''end'' pour obtenir respectivement le début et la fin d'un tableau. Ces fonctions sont également utilisables comme fonctions membres ou fonctions libres. Par exemple, avec la fonction de tri ''sort'' : | + | <code cpp main.cpp> |
+ | #include <iostream> | ||
+ | #include <string> | ||
- | <code cpp> | + | int main() { |
- | std::sort(a.begin(), a.end()); // fonctions membres | + | std::string const s { "hello, world!" }; |
- | std::sort(std::begin(a), std::end(a)); // fonctions libres | + | for (auto const value: s) |
+ | std::cout << value << ' '; | ||
+ | } | ||
</code> | </code> | ||
- | Au final, vous n'avez besoin que de connaître ces deux fonctions ''begin'' et ''end'' pour utiliser une collection avec les algorithmes de la bibliothèque standard. Il existe d'autres types de collection, n'hésitez pas à parcourir la page de documentation correspondante aux [[http://en.cppreference.com/w/cpp/container|conteneurs de données]] et à en tester quelques uns. | + | affiche : |
- | Les prochains chapitres seront consacrés à l'étude de quelques algorithmes importants, pour comparer des collections, trier les éléments, faire des recherches dans une collection, etc. | + | <code> |
- | + | h e l l o , w o r l d ! | |
- | __ resize, reserve, size, capacity, empty, max_size, shrink_to_fit __ | + | </code> |
- | ^ Chapitre précédent ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ Chapitre suivant ^ | ||
- | {{tag> Cours C++}} | + | ^ [[nombres_aleatoires|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[map|Chapitre suivant]] ^ |