Les séquences sont très utiles pour stocker des éléments, mais parfois nous avons besoin d'un moyen de vérifier si tous ou certains éléments vérifient un prédicat, ou d'appliquer une fonction sur chaque élément. Dans ce cours, nous découvrirons des fonctions déjà définies dans la bibliothèque STL pour résoudre ces problèmes.
<algorithm>.#include <algorithm> // all_of, any_of, none_of, for_each, for_each_n
#include <execution> // politiques d'exécution (C++17)
using namespace std;| Fonction | Retourne vrai si… | Séquence vide → |
|---|---|---|
all_of | tous les éléments vérifient pred | true |
any_of | au moins un élément vérifie pred | false |
none_of | aucun élément ne vérifie pred | true |
for_each | Applique fct à chaque élément → retourne fct | |
for_each_n | Applique fct aux n premiers éléments → retourne it_begin+n | |
Fonction all_of
L'algorithme all_of détermine si chaque élément d'une séquence répond à certains critères spécifiés par l'utilisateur.
Il renvoie true si la séquence cible est vide ou si pred est true pour tous les éléments ; sinon il renvoie false.
bool all_of([ep], it_debut, it_fin, pred);Arguments :
- Une politique d'exécution
std::executionfacultative, ep (défaut :std::execution::seq) - Une paire d'objets InputIterator, it_debut et it_fin, représentant la séquence cible
- Un prédicat unaire, pred, qui accepte un élément de la séquence cible
bool. Exemple : bool positif(int a) { return a > 0; }Exemple 1 — Vérifier si tous les éléments sont positifs
#include <iostream>
#include <algorithm>
#include <deque>
using namespace std;
bool positif(int a) { return a > 0; }
int main() {
int vals1[] = {1, 2, 3, 2, 3, 4, -5, 13, 8, 9, 6}; // contient -5
int vals2[] = {1, 2, 3, 2, 3, 4, 5, 13, 8, 9, 6}; // tous positifs
deque<int> d1(vals1, vals1 + 11);
deque<int> d2(vals2, vals2 + 11);
// Vérifier si tous les éléments de d1 sont positifs
if (all_of(d1.begin(), d1.end(), positif))
cout << "tous les éléments de d1 sont positifs\n";
else
cout << "Il y a au moins un élément négatif ou nul dans d1\n";
if (all_of(d2.begin(), d2.end(), positif))
cout << "tous les éléments de d2 sont positifs\n";
else
cout << "Il y a au moins un élément négatif ou nul dans d2\n";
return 0;
}Il y a au moins un élément négatif ou nul dans d1 tous les éléments de d2 sont positifs
positif par une expression lambda:all_of(d1.begin(), d1.end(), [](int a){ return a > 0; });Les lambdas évitent de déclarer une fonction séparée pour des prédicats simples.Fonction any_of
L'algorithme any_of détermine si au moins un élément d'une séquence répond à certains critères spécifiés par l'utilisateur.
Il renvoie false si la séquence cible est vide ou si pred n'est true pour aucun élément ; sinon il renvoie true.
bool any_of([ep], it_debut, it_fin, pred);Arguments :
- Une politique d'exécution
std::executionfacultative, ep - Une paire d'objets InputIterator, it_debut et it_fin
- Un prédicat unaire, pred
Exemple 2 — Vérifier si la séquence contient au moins un nombre pair
#include <iostream>
#include <algorithm>
#include <deque>
using namespace std;
bool estpair(int a) { return a % 2 == 0; }
int main() {
int vals1[] = {1, 2, 3, 2, 3, 4, 5, 13, 8, 9, 6}; // contient des pairs
int vals2[] = {1, 5, 3, 9, 3, 13, 5, 13, 21, 9, 35}; // tous impairs
deque<int> d1(vals1, vals1 + 11);
deque<int> d2(vals2, vals2 + 11);
if (any_of(d1.begin(), d1.end(), estpair))
cout << "La séquence d1 contient un nombre pair\n";
else
cout << "La séquence d1 ne contient pas un nombre pair\n";
if (any_of(d2.begin(), d2.end(), estpair))
cout << "La séquence d2 contient un nombre pair\n";
else
cout << "La séquence d2 ne contient pas un nombre pair\n";
return 0;
}La séquence d1 contient un nombre pair La séquence d2 ne contient pas un nombre pair
Fonction none_of
L'algorithme none_of détermine si aucun élément d'une séquence ne répond à certains critères spécifiés par l'utilisateur.
Il renvoie true si la séquence cible est vide ou si pred est true pour aucun élément ; sinon il renvoie false.
bool none_of([ep], it_debut, it_fin, pred);Arguments :
- Une politique d'exécution
std::executionfacultative, ep - Une paire d'objets InputIterator, it_debut et it_fin
- Un prédicat unaire, pred
pred:none_of(pred)est équivalent à!any_of(pred)all_of(pred)impliqueany_of(pred)(si la séquence est non vide)- Si
all_of(pred)est vrai, alorsnone_of(!pred)est aussi vrai
Exemple 3 — Vérifier qu'aucun élément n'est pair
#include <iostream>
#include <algorithm>
#include <deque>
using namespace std;
bool estpair(int a) { return a % 2 == 0; }
int main() {
int vals1[] = {1, 2, 3, 2, 3, 4, 5, 13, 8, 9, 6}; // contient des pairs
int vals2[] = {1, 5, 3, 9, 3, 13, 5, 13, 21, 9, 35}; // tous impairs
deque<int> d1(vals1, vals1 + 11);
deque<int> d2(vals2, vals2 + 11);
// none_of retourne true si AUCUN élément ne vérifie pred
if (none_of(d1.begin(), d1.end(), estpair))
cout << "La séquence d1 ne contient pas un nombre pair\n";
else
cout << "La séquence d1 contient un nombre pair\n";
if (none_of(d2.begin(), d2.end(), estpair))
cout << "La séquence d2 ne contient pas un nombre pair\n";
else
cout << "La séquence d2 contient un nombre pair\n";
return 0;
}La séquence d1 contient un nombre pair La séquence d2 ne contient pas un nombre pair
none_of(pred) = !any_of(pred). La différence réside dans l'intention sémantique exprimée dans le code.Fonction for_each
L'algorithme for_each applique une fonction définie par l'utilisateur à chaque élément d'une séquence.
Bien que for_each soit considéré comme une opération non-modificatrice, si it_debut est un itérateur mutable, fct peut modifier les éléments. Toutes les valeurs que fct renvoie sont ignorées.
Si on omet ep, for_each retourne fct ; sinon, il renvoie void.
for_each([ep], it_debut, it_fin, fct);Arguments :
- Une politique d'exécution
std::executionfacultative, ep - Une paire d'objets InputIterator, it_debut et it_fin
- Une fonction unaire, fct, qui accepte un élément de la séquence
Exemple 4 — Afficher et calculer les carrés de chaque élément
#include <iostream>
#include <algorithm>
#include <deque>
using namespace std;
void afficher(int a) { cout << a << " "; }
void puissance(int p) { cout << p * p << " "; }
int main() {
int vals[] = {1, 2, 3, 2, 3, 4, 5, 13, 8, 9, 6};
deque<int> v(vals, vals + 11);
// Afficher tous les éléments
for_each(v.begin(), v.end(), afficher);
cout << '\n';
// Afficher le carré de chaque élément
for_each(v.begin(), v.end(), puissance);
cout << '\n';
return 0;
}1 2 3 2 3 4 5 13 8 9 6 1 4 9 4 9 16 25 169 64 81 36
for_each est souvent remplaçable par une boucle for classique ou un range-based for (C++11) :for (int x : v) cout << x << " "; // range-based for
for_each(v.begin(), v.end(), afficher); // for_each — équivalentL'avantage de for_each est sa compatibilité avec les politiques d'exécution parallèle (std::execution::par).Fonction for_each_n
L'algorithme for_each_n applique une fonction définie par l'utilisateur aux n premiers éléments d'une séquence.
Il applique fct à chaque élément dans l'intervalle [it_begin, it_begin + n). Les valeurs retournées par fct sont ignorées. La fonction retourne it_begin + n.
InputIterator for_each_n([ep], it_begin, n, fct);Arguments :
- Une politique d'exécution
std::executionfacultative, ep - Un InputIterator it_begin — premier élément de la séquence cible
- Un entier n — nombre d'éléments à traiter ; l'intervalle est
[it_begin, it_begin + n) - Une fonction unaire, fct
| Aspect | for_each | for_each_n |
|---|---|---|
| Portée | Toute la séquence [début, fin) | Les n premiers éléments [début, début+n) |
| Borne finale | it_fin requis | n requis, it_fin non nécessaire |
| Valeur retournée | fct (sans ep) | it_begin + n |
| Disponible depuis | C++98 | C++17 |
Exemple 5 — Appliquer une fonction aux 4 premiers éléments seulement
#include <iostream>
#include <algorithm>
#include <deque>
using namespace std;
void afficher(int a) { cout << a << " "; }
void puissance(int p) { cout << p * p << " "; }
int main() {
int vals[] = {1, 2, 3, 2, 3, 4, 5, 13, 8, 9, 6};
deque<int> v(vals, vals + 11);
// Afficher les 4 premiers éléments
for_each_n(v.begin(), 4, afficher);
cout << '\n';
// Carré des 4 premiers éléments
for_each_n(v.begin(), 4, puissance);
cout << '\n';
return 0;
}1 2 3 2 1 4 9 4
for_each_n retourne un itérateur pointant sur l'élément juste après le dernier traité. Cela permet de chaîner les opérationsou de reprendre le traitement là où on s'est arrêté :auto it = for_each_n(v.begin(), 4, afficher); // traite v[0]..v[3]
for_each_n(it, 3, afficher); // traite v[4]..v[6]Récapitulatif — Algorithmes de séquence non-modificateurs
| Fonction | Signature simplifiée | Rôle | Retourne |
|---|---|---|---|
all_of | all_of(deb, fin, pred) | Tous les éléments vérifient pred ? | bool |
any_of | any_of(deb, fin, pred) | Au moins un élément vérifie pred ? | bool |
none_of | none_of(deb, fin, pred) | Aucun élément ne vérifie pred ? | bool |
for_each | for_each(deb, fin, fct) | Applique fct à chaque élément | fct |
for_each_n | for_each_n(deb, n, fct) | Applique fct aux n premiers éléments | deb + n |
Discussion (0)
Soyez le premier à laisser un commentaire !
Laisser un commentaire
Votre commentaire sera visible après modération.