lang:cpp:boucles
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
| lang:cpp:boucles [2019/12/26 13:56] – Ajout de la boucle for c++17 root | lang:cpp:boucles [2020/06/16 15:00] (Version actuelle) – Précision sur le style fonctionnel root | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| - | ====Toutes | + | =====Boucle sur des données (old style)===== |
| + | ====Conteneur supportant | ||
| - | ===La boucle traditionnelle=== | ||
| - | * Intervalle | ||
| <code cpp> | <code cpp> | ||
| - | for (int i = 0; i < 100; i++) | + | std:: |
| - | std::cout << i << std::endl; | + | for (size_t |
| + | std::cout << | ||
| </ | </ | ||
| - | Chaque paramètre est optionnel : | + | ====Conteneur supportant les itérateurs==== |
| <code cpp> | <code cpp> | ||
| - | int i = 0; | + | std:: |
| - | for (;;) | + | |
| - | { | + | // Lecture / écriture |
| - | | + | std:: |
| - | break; | + | for (it = vector.begin(); it != vector.end(); it++) |
| + | (*it)++; | ||
| + | |||
| + | // Lecture seule | ||
| + | std:: | ||
| + | for (itc = vector.cbegin(); | ||
| + | | ||
| + | </ | ||
| + | |||
| + | =====Programmation fonctionnelle===== | ||
| + | |||
| + | ====for each==== | ||
| + | |||
| + | ===Conteneur de type primitif=== | ||
| + | |||
| + | <code cpp> | ||
| + | std:: | ||
| + | // Ici, on utilise const & pour conserver le style fonctionnel. | ||
| + | // Mais passer en copie un type primitif n'est pas plus penalisant que d' | ||
| + | for (const int& i : arr) | ||
| std::cout << i << std::endl; | std::cout << i << std::endl; | ||
| - | i++; | ||
| - | } | ||
| </ | </ | ||
| - | Et sa version '' | + | ===Conteneur de type non primitif=== |
| <code cpp> | <code cpp> | ||
| - | int i = 0; | + | std:: |
| - | while (i < 100) | + | |
| + | for (const std:: | ||
| + | std::cout << val << std:: | ||
| + | </ | ||
| + | |||
| + | ===Conteneur multi-types (map, tuple, ...)=== | ||
| + | |||
| + | <code cpp> | ||
| + | std:: | ||
| + | |||
| + | // L' | ||
| + | // const s' | ||
| + | for (const auto & [key, value] : map) | ||
| + | std:: | ||
| + | </ | ||
| + | |||
| + | L' | ||
| + | |||
| + | <code cpp> | ||
| + | std:: | ||
| { | { | ||
| - | std::cout << | + | std::map<int, long, std::less<int>, std:: |
| - | | + | |
| + | | ||
| + | for(; __begin1.operator!=(__end1); | ||
| + | { | ||
| + | const std:: | ||
| + | std:: | ||
| + | std:: | ||
| + | std:: | ||
| + | } | ||
| } | } | ||
| </ | </ | ||
| - | * Conteneur supportant les index : | + | ===Implémentation sur une classe personnalisée=== |
| + | |||
| + | Il faut définir l' | ||
| + | |||
| + | Dans l' | ||
| + | |||
| + | Il faut commencer par déclarer l' | ||
| <code cpp> | <code cpp> | ||
| - | std::array<int, 4> arr { 10, 20, 30, 40 }; | + | #include < |
| - | for (size_t | + | |
| - | std::cout << | + | class DataSample; |
| + | |||
| + | // Données accessibles depuis la boucle. | ||
| + | class Data | ||
| + | { | ||
| + | | ||
| + | int getA() const { return a; } | ||
| + | void setA(int aa) { a = aa; } | ||
| + | |||
| + | | ||
| + | | ||
| + | }; | ||
| + | |||
| + | // Itérateur accessible en écriture. | ||
| + | class Iter | ||
| + | { | ||
| + | | ||
| + | Iter(DataSample &p_vec, int pos) : _pos(pos), _p_vec(p_vec) | ||
| + | |||
| + | bool operator!=(const Iter &other) const { return _pos != other._pos; } | ||
| + | Data & | ||
| + | Iter & | ||
| + | { | ||
| + | ++_pos; | ||
| + | return *this; | ||
| + | } | ||
| + | |||
| + | | ||
| + | int _pos; | ||
| + | DataSample & | ||
| + | }; | ||
| + | |||
| + | // Iterateur accessible uniquement en lecture. | ||
| + | class ConstIter | ||
| + | { | ||
| + | | ||
| + | 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 & | ||
| + | const ConstIter & | ||
| + | { | ||
| + | ++_pos; | ||
| + | return *this; | ||
| + | } | ||
| + | |||
| + | | ||
| + | int _pos; | ||
| + | const DataSample & | ||
| + | }; | ||
| + | |||
| + | // Classe stockant les données et implémentant le pattern for each. | ||
| + | class DataSample | ||
| + | { | ||
| + | | ||
| + | // Méthodes accessibles en écriture. | ||
| + | Data & | ||
| + | Iter begin() { return Iter(*this, 0); } | ||
| + | Iter end() { return Iter(*this, 100); } | ||
| + | // Méthodes accessibles uniquement en lecture seule. | ||
| + | const Data & | ||
| + | ConstIter begin() const { return ConstIter(*this, | ||
| + | ConstIter end() const { return ConstIter(*this, | ||
| + | |||
| + | void set(int index, int val) { _data[index].setA(val); | ||
| + | |||
| + | | ||
| + | // Dans cette classe, les données sont sous forme d'un tableau. | ||
| + | Data _data[100]; | ||
| + | }; | ||
| + | |||
| + | Data & | ||
| + | const Data & | ||
| + | |||
| + | // Exemple d' | ||
| + | int main() | ||
| + | { | ||
| + | DataSample v; | ||
| + | | ||
| + | { | ||
| + | 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) | ||
| + | | ||
| + | | ||
| + | } | ||
| + | // Utilisation de begin et end en const. | ||
| + | // Le type de retour est obligatoirement const Data& | ||
| + | for (const Data &i : static_cast< | ||
| + | { | ||
| + | std::cout << i.getA() << std:: | ||
| + | } | ||
| + | } | ||
| </ | </ | ||
| - | Utiliser de préférence la version '' | + | ====Ranges==== |
| - | * Conteneur ne supportant | + | Les '' |
| + | |||
| + | * Boucle | ||
| <code cpp> | <code cpp> | ||
| - | std::set<int> set { 10, 20, 30, 40 }; | + | # |
| - | std:: | + | |
| - | for (it = set.begin(); | + | for (int i : std:: |
| - | std::cout << | + | std::cout << |
| </ | </ | ||
| - | Utiliser de préférence | + | * Pour faire la boucle à l'envers : |
| - | ===for each=== | + | <code cpp> |
| + | #include < | ||
| - | | + | for (int i : std:: |
| + | std::cout << i << std:: | ||
| + | |||
| + | </ | ||
| + | |||
| + | | ||
| <code cpp> | <code cpp> | ||
| - | std::array<int, 4> arr = { 10, 20, 30, 40 }; | + | # |
| - | for (int i : arr) | + | |
| + | for (int i : std:: | ||
| std::cout << i << std::endl; | std::cout << i << std::endl; | ||
| </ | </ | ||
| - | * Conteneur de type non primitif | + | * Filter les valeurs |
| <code cpp> | <code cpp> | ||
| - | std::set<std::string> set { " | + | # |
| - | for (const std::string& val : set) | + | for (int i : std::views::iota(0, 100) | std:: |
| - | std::cout << | + | std::cout << |
| </ | </ | ||
| - | * Conteneur multi-types ('' | + | * Modifier les valeurs dans la vue : |
| <code cpp> | <code cpp> | ||
| - | std::map<int, std::string> map { {10, " | + | # |
| - | // L' | + | int main() { |
| - | for (const | + | for (const |
| - | std::cout << | + | // Integer |
| + | std:: | ||
| + | // const char * | ||
| + | std:: | ||
| + | if (i % 15 == 0) | ||
| + | return " | ||
| + | else if (i % 3 == 0) | ||
| + | return " | ||
| + | else if (i % 5 == 0) | ||
| + | return " | ||
| + | else | ||
| + | return ""; | ||
| + | })) | ||
| + | | ||
| + | } | ||
| </ | </ | ||
| - | * Sur une classe personnalisée : | + | <WRAP center round important 60%> |
| + | Les vues sont en lecture seule | ||
| + | </ | ||
| - | Il faut définir l' | + | Le code |
| + | <code cpp> | ||
| + | int main() { | ||
| + | std:: | ||
| + | | ||
| + | | ||
| + | | ||
| + | i = 3; | ||
| + | | ||
| + | std::cout << i << " | ||
| + | } | ||
| + | </code> | ||
| - | L' | + | affichera |
| - | Il faut commencer par déclarer l' | + | < |
| + | 1 | ||
| + | 2 | ||
| + | 3 | ||
| + | 4 | ||
| + | 5 | ||
| + | 6 | ||
| + | 7 | ||
| + | 8 | ||
| + | 9 | ||
| + | </ | ||
| + | |||
| + | * Ne prendre que les premiers résultats | ||
| <code cpp> | <code cpp> | ||
| + | #include < | ||
| + | int main() { | ||
| + | for (int i : | ||
| + | | ||
| + | | ||
| + | std::cout << i << std::endl; | ||
| + | } | ||
| </ | </ | ||
| + | |||
| + | =====Via une coroutine===== | ||
| + | |||
| + | <code cpp> | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | std:: | ||
| + | { | ||
| + | for (int i = 0; i < iterations; i++) | ||
| + | { | ||
| + | co_yield i; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | int main() | ||
| + | { | ||
| + | for (int i : loop(100)) | ||
| + | { | ||
| + | std::cout << i << std::endl; | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
lang/cpp/boucles.1577364989.txt.gz · Dernière modification : de root
