Collections et boucle «pour tout … dans …»#

Collections : définition et exemples#

Définition : Collection

Une collection (collection datatype) est une valeur composite homogène
(elle regroupe plusieurs valeurs du même type).

Exemple

Un tableau (vector) est une collection

Dans un tableau, les valeurs sont dans un ordre donné, en tenant compte des répétitions :

#include<vector>
using namespace std;
vector<int> v = { 3, 2, 5, 2 };
v

Cela donne un sens au i-ième élément d’un tableau :

v[3]

Note

Il existe d’autres types de collections. Voyons quelques exemples.

Ensembles (set)#

Lorsque l’on souhaite ne tenir compte ni de l’ordre, ni des répétitions – comme dans un ensemble mathématique – on peut utiliser un set :

#include <set>
using namespace std;
set<int> s = { 3, 2, 5, 2};
s

Du coup, accéder au i-ième élément n’a pas de sens :

s[0]

Multi-ensembles (multiset)#

Si l’on ne souhaite pas tenir compte de l’ordre mais tout de même des répétitions, on peut utiliser un multi-ensemble (multiset) :

multiset<int> m = { 3, 2, 5, 2 };
m
m[0]

La boucle for each#

Une opération omniprésente sur une collection est de parcourir ses valeurs : jusqu’ici on l’a fait à l’aide d’un indice :

#include<vector>
#include<iostream>
using namespace std;
vector<int> v = { 3, 2, 5, 2 };
for ( int i=0; i < v.size(); i++ ) {
    cout << v[i] << endl;
}

Cet idiome est un peu lourd et sujet à erreurs. Surtout, il ne se généralise pas à d’autres collections comme les ensembles! (pourquoi?).

À la place nous allons littéralement écrire «pour toute valeur dans v faire …» :

for ( auto valeur: v ) {
    cout << valeur << endl;
} 

C’est l’équivalent du for valeur in v: de Python. Et cela fonctionne tout aussi bien pour toute autre collection :

#include<set>
set<int> s = { 3, 2, 5, 2 };
for ( auto valeur: s ) {
    cout << valeur << endl;
}
multiset<int> m = { 3, 2, 5, 2 };
for ( auto valeur: m ) {
    cout << valeur << endl;
}

La boucle for each (for each loop) : syntaxe et sémantique#

Syntaxe

    for ( auto identificateur: collection ) {
        bloc d instructions;
    }

Sémantique

Pour chaque élément de la collection tour à tour, affecter la valeur de l’élément à l’identificateur et exécuter le bloc d’instructions.

Attention

Du fait de l’affectation, la boucle for each parcourt des copies des valeurs de la collection. En particulier, une affectation identificateur = ... ne change pas le tableau d’origine.

Vous verrez au second semestre comment changer cela lorsque souhaitable, en utilisant une référence.

Exemple

Quelle est la valeur de m après l’instruction suivante?

#include<vector>
using namespace std;
vector<int> m = { 3, 2, 5, 2 };
for ( auto valeur: m ) {
    valeur = 1;
}
m

Digression : à propos de auto#

Vous vous demandez peut-être quelle est la signification de auto?

On est en train de déclarer une nouvelle variable. Il faut donc préciser son type. On pourrait très bien mettre int comme type puisque l’on manipule des collections d’entiers :

for ( int valeur: v ) {
    cout << valeur << endl;
}

Mais c’est redondant.

Définition : auto

auto (auto (c++ keyword)) est un type spécial qui indique à C++ de sélectionner automatiquement le type adéquat en fonction du contexte. On appelle cela de l”inférence de type.

auto i = 1;
i
auto pi = 3.14;
pi