Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.
predicats [2014/09/01 12:32] gbdivers |
predicats [2019/02/21 23:04] (Version actuelle) alavida Corps de la fonction lambda est entre les accolades et non entre les crochets |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | ^ Chapitre précédent ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ Chapitre suivant ^ | + | ^ [[autres_collections|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[bitset|Chapitre suivant]] ^ |
- | ====== Les foncteurs ====== | + | |
+ | ====== Les foncteurs et fonctions lambdas ====== | ||
__foncteur ? fonction objet ? opérateur ? autre ? __ | __foncteur ? fonction objet ? opérateur ? autre ? __ | ||
Ligne 20: | Ligne 21: | ||
Cet algorithme est dit "modifiant" puisqu'il modifie directement le conteneur sur lequel on applique la fonction. | Cet algorithme est dit "modifiant" puisqu'il modifie directement le conteneur sur lequel on applique la fonction. | ||
- | Fondamentalement, cet algorithme fonctionne de la façon suivante : il parcourir les éléments de la collection et réalise des tests de comparaison par paire d'éléments. Pour faire cette comparaison, l'algorithme utilise l'opérateur de comparaison ''<'' sur les éléments. Par exemple, pour faire le trie d'un tableau d'entiers (''vector<int>''), l'algorithme réaliser des comparaisons d'entiers (''valeur 1 < valeur 2''). | + | Fondamentalement, cet algorithme fonctionne de la façon suivante : il parcourt les éléments de la collection et réalise des tests de comparaison par paire d'éléments. Pour faire cette comparaison, l'algorithme utilise l'opérateur de comparaison ''<'' sur les éléments. Par exemple, pour faire le tri d'un tableau d'entiers (''vector<int>''), l'algorithme réalise des comparaisons d'entiers (''valeur 1 < valeur 2''). |
- | Dit autrement, cela veut dire que si on utilise un ''vector<un_type>'', il faut que la comparaison ''<'' est un sens pour ce type ''un-type'' (ce qui sera le cas avec la majorité des types de base du C++). | + | Dit autrement, cela veut dire que si on utilise un ''vector<un_type>'', il faut que la comparaison ''<'' ait un sens pour ce type ''un_type'' (ce qui sera le cas avec la majorité des types de base du C++). |
On dit que l'opérateur ''<'' est le prédicat utilisé par l'algorithme de trie ''std::sort''. Plus généralement, un prédicat est une expression qui retourne un booléen (''true'' ou ''false''). Les différents algorithmes de la bibliothèque standard n'utilisent pas tous l'opérateur ''<'', certains utilisent l'opérateur d'égalité ''=='', d'autres n'utilisent pas de prédicat. | On dit que l'opérateur ''<'' est le prédicat utilisé par l'algorithme de trie ''std::sort''. Plus généralement, un prédicat est une expression qui retourne un booléen (''true'' ou ''false''). Les différents algorithmes de la bibliothèque standard n'utilisent pas tous l'opérateur ''<'', certains utilisent l'opérateur d'égalité ''=='', d'autres n'utilisent pas de prédicat. | ||
- | Imaginons maintenant que l'on souhaite trier une collection dans l'ordre inverse, c'est-à-dire du plus grand au plus petit. Une première solution serait de trier dans l'ordre par défaut (plus petit au plus grand), puis d'inverser l'ordre des éléments. Une autre solution serait de réécrire un algorithme de trie (appelé ''reverse_sort'' par exemple) et qui trie dans l'ordre inverse (du plus grand au plus petit). | + | Imaginons maintenant que l'on souhaite trier une collection dans l'ordre inverse, c'est-à-dire du plus grand au plus petit. Une première solution serait de trier dans l'ordre par défaut (plus petit au plus grand), puis d'inverser l'ordre des éléments. Une autre solution serait de réécrire un algorithme de tri (appelé ''reverse_sort'' par exemple) et qui trie dans l'ordre inverse (du plus grand au plus petit). |
- | Ces deux solutions ne sont pas correctes en termes de C++ moderne. La première est inutilement plus compliqué (il faut écrire deux lignes au lieu d'une seule), la seconde demande de réécrire l'algorithme de trie. | + | Ces deux solutions ne sont pas correctes en termes de C++ moderne. La première est inutilement plus compliqué (il faut écrire deux lignes au lieu d'une seule), la seconde demande de réécrire l'algorithme de tri. |
===== Les foncteurs de la bibliothèque standard ===== | ===== Les foncteurs de la bibliothèque standard ===== | ||
Ligne 92: | Ligne 93: | ||
</code> | </code> | ||
- | Pour bien comprendre la différence entre les différents types de fonction, revoyons les différentes syntaxes pour créer une variable (nommée ''object'') d'un type donné (''MyObject'') et sur laquelle nous appliquons une fonction : | + | Pour bien comprendre la différence entre les divers types de fonction, revoyons les multiples syntaxes pour créer une variable (nommée ''object'') d'un type donné (''MyObject'') et sur laquelle nous appliquons une fonction : |
<code cpp> | <code cpp> | ||
Ligne 112: | Ligne 113: | ||
__ composition de fonction, not1, not2, bind ? __ | __ composition de fonction, not1, not2, bind ? __ | ||
+ | |||
+ | Plus généralement, il est possible d'utiliser n'importe quelle fonction de la bibliothèque standard, à partir du moment où celle-ci respecte la signature attendue par un algorithme donné. En particulier, il est possible d'utiliser les fonctions de manipulations de caractères, définies dans le fichier d'en-tête ''<cctype>'' : [[http://en.cppreference.com/w/cpp/string/byte|Null-terminated byte strings]] (ou leur équivalent pour ''wstring'' : [[http://en.cppreference.com/w/cpp/string/wide|Null-terminated wide strings]]). Ces fonctions se divisent en deux catégories : | ||
+ | |||
+ | * les fonctions de test (//Character classification//) : | ||
+ | * ''isalnum'' (alphanumérique) ; | ||
+ | * ''isalpha'' (alphabétique) ; | ||
+ | * ''islower'' (minuscule) ; | ||
+ | * ''isupper'' (majuscule) ; | ||
+ | * ''isdigit'' (chiffre décimal) ; | ||
+ | * ''isxdigit'' (chiffre hexadécimal) ; | ||
+ | * ''iscntrl'' (caractère de contrôle) ; | ||
+ | * ''isgraph'' (caractère graphique) ; | ||
+ | * ''isspace'' (espace) ; | ||
+ | * ''isblank'' (caractère blanc) ; | ||
+ | * ''isprint'' (caractère affichable) ; | ||
+ | * ''ispunct'' (ponctuation). | ||
+ | * les fonctions de modification (//Character manipulation//) : | ||
+ | * ''tolower'' (convertie en minuscule) ; | ||
+ | * ''toupper'' (converti en majuscule). | ||
+ | |||
+ | La syntaxe pour utiliser les fonctions dans un algorithme est différente de celle pour les objets-fonctions. Il faut simplement mettre la nom de la fonction. Par exemple, pour convertir une chaîne de caractères en majuscule, il est possible d'utiliser l'algorithme ''transform'' (que vous verrez par la suite) et la fonction ''toupper'' : | ||
+ | |||
+ | <code cpp main.cpp> | ||
+ | #include <iostream> | ||
+ | #include <string> | ||
+ | #include <algorithm> | ||
+ | |||
+ | int main() { | ||
+ | std::string s { "abcdef" }; | ||
+ | std::transform(begin(s), end(s), begin(s), toupper); | ||
+ | std::cout << s << std::endl; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | affiche : | ||
+ | |||
+ | <code> | ||
+ | ABCDEF | ||
+ | </code> | ||
==== Exercices ==== | ==== Exercices ==== | ||
- | * tirer avec d'autres prédicats | + | * trier avec d'autres prédicats |
* combiner des prédicats | * combiner des prédicats | ||
Ligne 124: | Ligne 164: | ||
Il est important que vous sachiez créer des fonctions, c'est un point fondamental en C++, vous les utiliserez dans tous vos codes. Et plus important, ce qui sera fondamental est de savoir découper correctement les problèmes complexes en fonctions plus simples. Ce chapitre ne sera pas suffisant pour étudier toutes les possibilités offertes par les fonctions, nous reviendrons dessus en détail par la suite. Cette partie se focalise sur l'utilisation simple des fonctions lambdas avec les algorithmes de la bibliothèque standard. | Il est important que vous sachiez créer des fonctions, c'est un point fondamental en C++, vous les utiliserez dans tous vos codes. Et plus important, ce qui sera fondamental est de savoir découper correctement les problèmes complexes en fonctions plus simples. Ce chapitre ne sera pas suffisant pour étudier toutes les possibilités offertes par les fonctions, nous reviendrons dessus en détail par la suite. Cette partie se focalise sur l'utilisation simple des fonctions lambdas avec les algorithmes de la bibliothèque standard. | ||
- | Les fonctions lambdas sont une technique issue de la programmation fonctionnelle. Vous avez déjà utiliser des fonctions (membres ou libres) et vous avez déjà définit une fonction : la fonction ''main''. Pour rappel, une fonction permet de réaliser une tâche particulière et est constituée de : | + | Les fonctions lambdas sont une technique issue de la programmation fonctionnelle. Vous avez déjà utilisé des fonctions (membres ou libres) et vous avez déjà défini une fonction : la fonction ''main''. Pour rappel, une fonction permet de réaliser une tâche particulière et est constituée de : |
* un nom de fonction (''main'') ; | * un nom de fonction (''main'') ; | ||
Ligne 146: | Ligne 186: | ||
<note info>''Programmation fonctionnelle''</note> | <note info>''Programmation fonctionnelle''</note> | ||
- | Une fonction lambda est une fonction particulière. Elle n'a pas de nom et peut être déclarée dans le corps d'une autre fonction. A part cela, elle se comporte comme une fonction classique et peut recevoir des arguments, retourner une valeur. Il existe plusieurs façon d'écrire des fonctions lambdas, mais comme nous les utilisons ici dans les algorithmes de la bibliothèques standard, il est nécessaire de respecter la signature imposée par les algorithmes. | + | Une fonction lambda est une fonction particulière. Elle n'a pas de nom (elle est dite anonyme) et peut être déclarée dans le corps d'une autre fonction. A part cela, elle se comporte comme une fonction classique et peut recevoir des arguments, retourner une valeur. Il existe plusieurs façon d'écrire des fonctions lambdas, mais comme nous les utilisons ici dans les algorithmes de la bibliothèques standard, il est nécessaire de respecter la signature imposée par les algorithmes. |
La définition d'une fonction lambda se décompose en trois parties : | La définition d'une fonction lambda se décompose en trois parties : | ||
Ligne 178: | Ligne 218: | ||
</code> | </code> | ||
- | Le corps de la fonction lambda (entre les crochets) peut contenir plusieurs lignes (séparées par un point-virgule), déclarer des variables, appeler d'autres fonctions, etc. Bref, vous pouvez mettre dans le corps d'une fonction lambda toutes les instructions que vous souhaitez. | + | Le corps de la fonction lambda (entre les accolades) peut contenir plusieurs lignes (séparées par un point-virgule), déclarer des variables, appeler d'autres fonctions, etc. Bref, vous pouvez mettre dans le corps d'une fonction lambda toutes les instructions que vous souhaitez. |
Pour écrire une fonction lambda qui prend deux paramètres, compare les valeurs et retourne un booléen, on peut donc écrire : | Pour écrire une fonction lambda qui prend deux paramètres, compare les valeurs et retourne un booléen, on peut donc écrire : | ||
Ligne 237: | Ligne 277: | ||
* trier selon la valeur absolue | * trier selon la valeur absolue | ||
- | ^ Chapitre précédent ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ Chapitre suivant ^ | ||
- | {{tag> Cours C++}} | + | ^ [[autres_collections|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[bitset|Chapitre suivant]] ^ |