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 09:08] – Ajout des conteneurs sans index 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=== | ||
<code cpp> | <code cpp> | ||
- | for (int i = 0; i < 100; i++) | + | std:: |
+ | for (size_t | ||
+ | std::cout << arr[i] << std:: | ||
+ | </ | ||
+ | |||
+ | ====Conteneur supportant les itérateurs==== | ||
+ | <code cpp> | ||
+ | std:: | ||
+ | |||
+ | // Lecture / écriture | ||
+ | std:: | ||
+ | for (it = vector.begin(); | ||
+ | (*it)++; | ||
+ | |||
+ | // Lecture seule | ||
+ | std:: | ||
+ | for (itc = vector.cbegin(); | ||
+ | std::cout << *itc << std:: | ||
+ | </ | ||
+ | |||
+ | =====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; | ||
</ | </ | ||
- | Chaque paramètre | + | ===Conteneur de type non primitif=== |
+ | |||
+ | <code cpp> | ||
+ | std:: | ||
+ | |||
+ | 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::cout << value << std:: | ||
+ | </ | ||
+ | |||
+ | L' | ||
<code cpp> | <code cpp> | ||
- | int i = 0; | + | std:: |
- | for (;;) | + | |
{ | { | ||
- | | + | |
- | break; | + | std:: |
- | std::cout << | + | std:: |
- | | + | for(; __begin1.operator!=(__end1); |
+ | | ||
+ | const std:: | ||
+ | std:: | ||
+ | std:: | ||
+ | | ||
+ | | ||
} | } | ||
</ | </ | ||
- | Et sa version | + | ===Implémentation sur une classe personnalisée=== |
+ | |||
+ | Il faut définir l'itérateur et la classe à parcourir. [[https:// | ||
+ | |||
+ | Dans l'idéal, | ||
+ | |||
+ | Il faut commencer par déclarer l' | ||
<code cpp> | <code cpp> | ||
- | int i = 0; | + | #include < |
- | while (i < 100) | + | |
+ | class DataSample; | ||
+ | |||
+ | // Données accessibles depuis la boucle. | ||
+ | class Data | ||
{ | { | ||
- | | + | |
- | i++; | + | int getA() const { return a; } |
+ | void setA(int aa) { a = aa; } | ||
+ | |||
+ | | ||
+ | int a; | ||
+ | }; | ||
+ | |||
+ | // 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; | ||
+ | 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) | ||
+ | { | ||
+ | | ||
+ | | ||
+ | // 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::endl; | ||
+ | } | ||
} | } | ||
</ | </ | ||
- | Avec un conteneur supportant les index : | + | ====Ranges==== |
+ | |||
+ | Les '' | ||
+ | |||
+ | * Boucle | ||
<code cpp> | <code cpp> | ||
- | std::array<int, 4> arr { 10, 20, 30, 40 }; | + | # |
- | for (size_t | + | |
- | std::cout << | + | for (int i : std:: |
+ | std::cout << i << std::endl; | ||
</ | </ | ||
- | Avec un conteneur ne supportant pas les index : | + | * Pour faire la boucle à l' |
<code cpp> | <code cpp> | ||
- | std::set< | + | #include < |
- | std::set<int>::const_iterator it; | + | |
+ | for (int i : std::views:: | ||
+ | std::cout << i << std::endl; | ||
- | for (it = set.begin(); | ||
- | std::cout << *it << std::endl; | ||
</ | </ | ||
- | ===for each=== | + | * S' |
<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; | ||
</ | </ | ||
- | Et avec un conteneur de type non primitif | + | * Filter les valeurs |
<code cpp> | <code cpp> | ||
- | std::set<std::string> set { " | + | # |
- | for (const std:: | + | for (int i : std:: |
- | std::cout << | + | std::cout << i << std:: |
+ | </ | ||
+ | |||
+ | * Modifier les valeurs dans la vue : | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | |||
+ | int main() { | ||
+ | | ||
+ | // Integer | ||
+ | std:: | ||
+ | // const char * | ||
+ | std:: | ||
+ | if (i % 15 == 0) | ||
+ | return " | ||
+ | else if (i % 3 == 0) | ||
+ | return " | ||
+ | else if (i % 5 == 0) | ||
+ | return " | ||
+ | else | ||
+ | return ""; | ||
+ | })) | ||
+ | std::cout << i << std:: | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | Les vues sont en lecture seule | ||
+ | </ | ||
+ | |||
+ | Le code | ||
+ | <code cpp> | ||
+ | int main() { | ||
+ | | ||
+ | for (int & i : | ||
+ | v | | ||
+ | | ||
+ | i = 3; | ||
+ | for (const int & i : v) | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | affichera | ||
+ | |||
+ | < | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | 4 | ||
+ | 5 | ||
+ | 6 | ||
+ | 7 | ||
+ | 8 | ||
+ | 9 | ||
+ | </ | ||
+ | |||
+ | * Ne prendre que les premiers résultats | ||
+ | |||
+ | <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:: | ||
+ | } | ||
+ | } | ||
</ | </ | ||
lang/cpp/boucles.1577347690.txt.gz · Dernière modification : 2019/12/26 09:08 de root