lang:cpp:boucles
Ceci est une ancienne révision du document !
Table des matières
La boucle traditionnelle
Intervalle
for (int i = 0; i < 100; i++) std::cout << i << std::endl;
Chaque paramètre est optionnel :
int i = 0; for (;;) { if (i >= 100) break; std::cout << i << std::endl; i++; }
Et sa version while
:
int i = 0; while (i < 100) { std::cout << i << std::endl; i++; }
Conteneur supportant les index
std::array<int, 4> arr { 10, 20, 30, 40 }; for (size_t i = 0; i < arr.size(); i++) std::cout << arr[i] << std::endl;
Conteneur supportant les itérateurs
std::vector<int> vector{ 10, 20, 30, 40 }; std::vector<int>::const_iterator it; std::vector<int>::iterator itc; // Lecture / écriture for (itc = vector.begin(); itc != vector.end(); itc++) (*itc)++; // Lecture seule for (it = vector.cbegin(); it != vector.cend(); it++) std::cout << *it << std::endl;
for each
Conteneur de type primitif
std::array<int, 4> arr = { 10, 20, 30, 40 }; for (int i : arr) std::cout << i << std::endl;
Conteneur de type non primitif
std::set<std::string> set { "10", "20", "30", "40" }; for (const std::string& val : set) std::cout << val << std::endl;
Conteneur multi-types (''std::map'', ''std::tuple'', ...)
std::map<int, std::string> map { {10, "10"}, {20, "20"}, {30, "30"}, {40, "40"} }; // L'utilisation de auto est obligatoire. for (const auto & [key, value] : map) std::cout << value << std::endl;
Sur une classe personnalisée
Il faut définir l'itérateur et la classe à parcourir. C++11 range-based for loops Archive le 26/12/2019
L'exemple ci-dessous se passe de template
.
Il faut commencer par déclarer l'itérateur.
#include <iostream> class DataSample; // Données accessibles depuis la boucle. class Data { public: int getA() const { return a; } void setA(int aa) { a = aa; } private: int a; }; // Itérateur accessible en écriture. class Iter { public: Iter(DataSample &p_vec, int pos) : _pos(pos), _p_vec(p_vec) {} bool operator!=(const Iter &other) const { return _pos != other._pos; } Data &operator*(); Iter &operator++() { ++_pos; return *this; } private: int _pos; DataSample &_p_vec; }; // Iterateur accessible uniquement en lecture. class ConstIter { public: ConstIter(const DataSample &p_vec, int pos) : _pos(pos), _p_vec(p_vec) {} bool operator!=(const ConstIter &other) const { return _pos != other._pos; } const Data &operator*() const; const ConstIter &operator++() { ++_pos; return *this; } private: int _pos; const DataSample &_p_vec; }; // Classe stockant les données et implémentant le pattern for each. class DataSample { public: // Méthodes accessibles en écriture. Data &get(int col) { return _data[col]; } Iter begin() { return Iter(*this, 0); } Iter end() { return Iter(*this, 100); } // Méthodes accessibles uniquement en lecture seule. const Data &get(int col) const { return _data[col]; } ConstIter begin() const { return ConstIter(*this, 0); } ConstIter end() const { return ConstIter(*this, 100); } void set(int index, int val) { _data[index].setA(val); } private: // Dans cette classe, les données sont sous forme d'un tableau. Data _data[100]; }; Data &Iter::operator*() { return _p_vec.get(_pos); } const Data &ConstIter::operator*() const { return _p_vec.get(_pos); } // Exemple d'usage. int main() { DataSample v; for (int i = 0; i < 100; i++) { v.set(i, i); } // Utilisation de begin et end en non const. // Le type de retour est Data& (qui peut être casté en const Data&). for (Data &i : v) { std::cout << i.getA() << std::endl; } // Utilisation de begin et end en const. // Le type de retour est obligatoirement const Data&. for (const Data &i : static_cast<const DataSample>(v)) { std::cout << i.getA() << std::endl; } }
Via une coroutine
#include <experimental/generator> #include <iostream> std::experimental::generator<int> loop(int iterations) { for (int i = 0; i < iterations; i++) { co_yield i; } } int main() { for (int i : loop(100)) { std::cout << i << std::endl; } }
Algorithmes
mismatch
Comparer deux classes itérables.
Ici, comparaison de deux string insensible à la casse.
#include <algorithm> #include <string> #include <utility> std::string un = "texte"; std::string deux = "Texte"; std::tuple<std::string::const_iterator, std::string::const_iterator> retval = std::mismatch( un.cbegin(), un.cend(), deux.cbegin(), deux.cend(), [](char un, char deux) { return std::tolower(un) == std::tolower(deux); }); if (retval == std::make_tuple(un.cend(), deux.cend())) std::cout << "Identique" << std::endl; else std::cout << "Différent" << std::endl;
lang/cpp/boucles.1577957301.txt.gz · Dernière modification : 2020/01/02 10:28 de root