Outils d'utilisateurs

Outils du Site


fonctions

Différences

Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.

Lien vers cette vue

fonctions [2016/06/02 19:44]
gbdivers
fonctions [2016/06/28 16:27] (Version actuelle)
gbdivers
Ligne 1: Ligne 1:
  
-^ Chapitre précédent ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ Chapitre suivant ^+[[validation_motifs|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[parametres_arguments|Chapitre suivant]] ^
  
 ====== Créer des fonctions ====== ====== Créer des fonctions ======
Ligne 78: Ligne 78:
 En pratique, cela ne sera pas nécessaire si vous écrivez correctement vos fonctions, en leur donnant un nom explicite. Avec le nom de la fonction, vous pourrez comprendre ce qu'elle fait et continuer la lecture du code, sans devoir aller lire les instructions dans la fonction appelée. En pratique, cela ne sera pas nécessaire si vous écrivez correctement vos fonctions, en leur donnant un nom explicite. Avec le nom de la fonction, vous pourrez comprendre ce qu'elle fait et continuer la lecture du code, sans devoir aller lire les instructions dans la fonction appelée.
  
-Et en fait, c'est ce que vous faite depuis le début de ce cours. Vous avez déjà utiliser des fonctions, comme par exemple les algorithmes de la bibliothèque standard. Dans le code suivant :+Et en fait, c'est ce que vous faite depuis le début de ce cours. Vous avez déjà utilisé des fonctions, comme par exemple les algorithmes de la bibliothèque standard. Dans le code suivant :
  
 <code cpp> <code cpp>
-vector<int> v { 1, 8, 3, 5, 2, 9 };+std::vector<int> v { 1, 8, 3, 5, 2, 9 };
 std::sort(begin(v), end(v)); std::sort(begin(v), end(v));
 std::cout << v.front() << std::endl; std::cout << v.front() << std::endl;
 </code> </code>
  
-Lorsque vous lisez la ligne avec ''std::sort'', vous comprenez que le tableau est trié et que vous afficher ensuite le premier élément. Vous n'avez pas besoin d'aller lire le code de cette fonction pour comprendre que ce code va afficher la valeur "1" (première valeur du tableau après le tri).+Lorsque vous lisez la ligne avec ''std::sort'', vous comprenez que le tableau est trié et que vous affichez ensuite le premier élément. Vous n'avez pas besoin d'aller lire le code de cette fonction pour comprendre que ce code va afficher la valeur "1" (première valeur du tableau après le tri).
  
-C'est une règle générale qu'il faut retenir quand vous créez une fonction : il faut pouvoir (idéalement) la comprendre et l'utiliser sans devoir aller lire le code de la fonction ou la documentation. (Le nom de la fonction et des parametres doit etre la premiere documentation).+C'est une règle générale qu'il faut retenir quand vous créez une fonction : il faut pouvoir (idéalement) la comprendre et l'utiliser sans devoir aller lire le code de la fonction ou la documentation. (Le nom de la fonction et des paramètres doit être la première documentation).
  
 Un autre exemple de fonction que vous connaissez bien maintenant : la fonction ''main'' : Un autre exemple de fonction que vous connaissez bien maintenant : la fonction ''main'' :
Ligne 99: Ligne 99:
 ===== Pourquoi créer des fonctions ? ===== ===== Pourquoi créer des fonctions ? =====
  
-<note>**A rediger...**+<note>**À rédiger...**
  
-Savoir utiliser des fonctions ne consiste pas seulement connaitre les syntaxes pour écrire et utiliser des fonctions. L'objectif est avant tout de savoir décomposer une problématique complexe en sous-problématiques de plus en plus simples, de façon arriver des solutions connues ou facilement implémentables.+Savoir utiliser des fonctions ne consiste pas seulement à connaitre les syntaxes pour écrire et utiliser des fonctions. L'objectif est avant tout de savoir décomposer une problématique complexe en sous-problématiques de plus en plus simples, de façon à arriver à des solutions connues ou facilement implémentables.
  
 {{ :function.png |}} {{ :function.png |}}
Ligne 109: Ligne 109:
   * courte : en quelques lignes (quelques lignes a quelques dizaines de lignes) ;   * courte : en quelques lignes (quelques lignes a quelques dizaines de lignes) ;
   * simple a implémenter : qui utilise au maximum d'autres fonctions, en particulier des classes et algorithmes de la bibliothèques standard ;   * simple a implémenter : qui utilise au maximum d'autres fonctions, en particulier des classes et algorithmes de la bibliothèques standard ;
-  * comprehensible partir du nom de la fonction et des parametres (et de la documentation), n'importe qui peut comprendre ce que fait la fonction ; +  * compréhensible à partir du nom de la fonction et des paramètres (et de la documentation), n'importe qui peut comprendre ce que fait la fonction ; 
-  * generique : la fonction peut etre utilisee avec de nombreux types de donnees +  * générique : la fonction peut être utilisée avec de nombreux types de données 
-  * testable : il est facile d'ecrire des tests permettant de verifier le comportement d'une fonction.+  * testable : il est facile d’écrire des tests permettant de vérifier le comportement d'une fonction.
  
-exemple de demarche partant d'une problematique en solutions simple+exemple de démarche partant d'une problématique en solutions simples
 </note> </note>
  
Ligne 137: Ligne 137:
 <code> <code>
 void f(int);      // déclaration void f(int);      // déclaration
-void f() { ... }  // définition+void f(int) { ... }  // définition
 </code> </code>
  
-Une declaration ne sert qu'a "dire" (declarer) au compilateur qu'un identifiant existe, alors qu'une definition explique quoi correspond un identifiant (ce qu'il est, comment il est definit).+Une déclaration ne sert qu'a "dire" (déclarer) au compilateur qu'un identifiant existe, alors qu'une définition explique à quoi correspond un identifiant (ce qu'il est, comment il est définit).
  
-Une meme fonction peut avoir plusieurs declaration, mais ne peut avoir qu'une seule definition (ODR, //One Definition Rule//).+Une même fonction peut avoir plusieurs déclarations, mais ne peut avoir qu'une seule définition (ODR, //One Definition Rule//)
 + 
 +A noter la similarite entre la syntaxe pour declarer une fonction et l'initialisation d'une variable avec des parentheses : 
 + 
 +<code cpp> 
 +int x(int);  // un type = declaration d'une fonction 
 +int y(123);  // une valeur = definition d'une variable 
 +int z();     // rien = fonction ou variable ? 
 +</code> 
 + 
 +La derniere syntaxe correspond en fait a la declaration d'une fonction, qui ne prend aucun parametre et retourne un entier. Le probleme est que cette syntaxe est regulierement confondue avec une initialisation par defaut d'une variable. Ce qui produira bien sur une erreur de compilation lorsque vous esserez d'utiliser une fonction comme si c'etait une variable.
 </note> </note>
  
Ligne 178: Ligne 188:
 </code> </code>
  
-Note : dans ces codes, ''{}'' indique un bloc d'instructions... sans instructions. Donc ces fonctions ne font rien, ce sont juste des exemples pour presenter la syntaxe.+Note : dans ces codes, ''{}'' indique un bloc d'instructions... sans instructions. Donc ces fonctions ne font rien, ce sont juste des exemples pour présenter la syntaxe.
  
  
-Tous ces noms de fonction sont valides. La premiere liste de noms ("f", "g", etc. jusqu'a "bar") ne sont pas explicite, donc impossible de savoir ce qu'elles font sans lire leur code. Ce sont donc de mauvais noms en général (mais utilisé souvent comme des codes d'explication, pour nommer des fonctions qui n'ont pas d'autre utilité que d'expliquer quelque chose ou pour lequel le nom importe peu. Ne pas utiliser dans des codes réels).+Tous ces noms de fonction sont valides. La première liste de noms ("f", "g", etc. jusqu’à "bar") ne sont pas explicite, donc impossible de savoir ce qu'elles font sans lire leur code. Ce sont donc de mauvais noms en général (mais utilisé souvent comme des codes d'explication, pour nommer des fonctions qui n'ont pas d'autre utilité que d'expliquer quelque chose ou pour lequel le nom importe peu. Ne pas utiliser dans des codes réels).
  
-Les 2 fonctions suivantes "une_fonction_quelconque" et "UneAutreFonction" ont des noms plus explicite. Notez l'utilisation des ''_'' et majuscule pour faciliter la lecture. Forme préférer dans vos codes, avec des noms explicites.+Les 2 fonctions suivantes "une_fonction_quelconque" et "UneAutreFonction" ont des noms plus explicite. Notez l'utilisation des ''_'' et majuscule pour faciliter la lecture. Forme à préférer dans vos codes, avec des noms explicites.
  
 La suivante est un exemple de fonction valide, mais peu lisible à cause de la mauvaise utilisation des majuscules. La suivante est un exemple de fonction valide, mais peu lisible à cause de la mauvaise utilisation des majuscules.
  
-Les 2 dernières utilise un nom avec un numéro. C'est également un exemple de nom peu explicite, à éviter dans un code réel.+Les 2 dernières utilisent un nom avec un numéro. C'est également un exemple de nom peu explicite, à éviter dans un code réel.
  
-Exemple de noms pas valides :+Exemple de noms invalides :
  
 <code> <code>
Ligne 195: Ligne 205:
 void une&fonction() {}  // caractère illégal void une&fonction() {}  // caractère illégal
 </code> </code>
 +
 +===== Appel de fonction =====
  
 Pour appeler une fonction qui ne prend pas d'arguments et qui ne retourne pas d'information, vous pouvez l'appeler directement en utilisant son nom et des parentheses vides. Vous avez utilise cette syntaxe de nombreuses fois, par exemple pour la fonction ''size'' de ''std::string'' ou la fonction ''clear'' de ''std::vector''. Pour appeler une fonction qui ne prend pas d'arguments et qui ne retourne pas d'information, vous pouvez l'appeler directement en utilisant son nom et des parentheses vides. Vous avez utilise cette syntaxe de nombreuses fois, par exemple pour la fonction ''size'' de ''std::string'' ou la fonction ''clear'' de ''std::vector''.
Ligne 202: Ligne 214:
 </code> </code>
  
-Bien sur, vous pouvez appeler plusieurs fois une meme fonction (comme vu dans le second code) ou appeler une fonction depuis une autre fonction. (C'est d'ailleurs ce que vous faites quand vous appeler une fonction quelconque depuis la fonction ''main'').+Par exemple : 
 + 
 +<code cpp> 
 +#include <iostream> 
 + 
 +void f() { 
 +    std::cout << "hello, world" << std::endl; 
 +
 + 
 +int main() { 
 +    f(); 
 +
 +</code> 
 + 
 +affiche : 
 + 
 +<code> 
 +hello, world 
 +</code> 
 + 
 +Le compilateur lit le code dans l'ordre où il est écrit, donc, comme pour les variables, vous ne pouvez pas utiliser une fonction avant qu'elle ne soit définie. Le code suivant est donc invalide, même si la fonction existe : 
 + 
 +<code cpp> 
 +int main() { 
 +    f(); 
 +
 + 
 +void f() {} 
 +</code> 
 + 
 +affiche le message d'erreur suivant : 
 + 
 +<code> 
 +main.cpp:2:5: error: use of undeclared identifier 'f' 
 +    f(); 
 +    ^ 
 +</code> 
 + 
 +Ce qui signifie "utilisation d'un identifiant non déclaré" (sous entendant "non déclaré dans le code qui précède la ligne de code qui utilise cet identifiant). 
 + 
 +Il est possible de déclarer une fonction et de la définir plus tard, en utilisant une déclaration anticipée (//forward declaration//), vous verrez cela dans la suite de ce cours. 
 + 
 +Vous pouvez appeler plusieurs fois une même fonction (comme vu dans le second code) ou appeler une fonction depuis une autre fonction. (C'est d'ailleurs ce que vous faites quand vous appeler une fonction quelconque depuis la fonction ''main'').
  
 <code cpp> <code cpp>
Ligne 215: Ligne 269:
 </code> </code>
  
-Une fonction qui est definie dans une autre fonction est appellee une fonction imbriquee (//nested function//). En C++, part le cas particulier des fonctions lambdas que vous verrez ensuite, une fonction ne peut pas etre imbriquee dans une autre fonction.+Une fonction qui est définie dans une autre fonction est appelée une fonction imbriquée (//nested function//). En C++, à part le cas particulier des fonctions lambdas que vous verrez ensuite, une fonction ne peut pas être imbriquée dans une autre fonction.
  
 <code cpp> <code cpp>
 void f() {  void f() { 
-    void g(); // declaration d'une fonction imbriquee : erreur+    void g(); // déclaration d'une fonction imbriquée : erreur
 } }
 </code> </code>
  
-Les fonctions doivent etre declarees dans un espace de noms - qui sera vu dans le chapitre sur la creation de bibliotheques - ou dans une classe - qui sera vu dans la partie programmation orientee objet. Quand vous declarer une fonction directement en dehors de la fonction ''main'', comme vous le faites depuis le debut de ce chapitre, vous les declarez en fait dans un espace de noms global et anonyme. Cela sera egalement vu bientot.+Les fonctions doivent être déclarées dans un espace de noms - qui sera vu dans le chapitre sur la création de bibliothèques - ou dans une classe - qui sera vu dans la partie programmation orientée objet. Quand vous déclarer une fonction directement en dehors de la fonction ''main'', comme vous le faites depuis le début de ce chapitre, vous les déclarez en fait dans un espace de noms global et anonyme. Cela sera également vu bientôt.
  
-Un cas particulier de fonction qui appelle une fonction : il est possible d'ecrire une fonction qui s'appelle elle meme. Le code suivant est valide (tout au moins en termes de syntaxe) :+Un cas particulier de fonction qui appelle une fonction : il est possible d’écrire une fonction qui s'appelle elle même. Le code suivant est valide (tout au moins en termes de syntaxe) :
  
 <code cpp> <code cpp>
Ligne 233: Ligne 287:
 </code> </code>
  
-Un code qui s'appelle lui-meme est appele un code recursif. C'est une approche interessante pour resoudre de tres nombreuses problematiques. Vous verrez dans les exercices et complements quelques exemples d'algorithmes recursifs.+Un code qui s'appelle lui-même est appelle un code récursif. C'est une approche intéressante pour résoudre de très nombreuses problématiques. Vous verrez dans les exercices et compléments quelques exemples d'algorithmes récursifs.
  
-Cependant, le code precedent est trop simpliste et produira un crash a l'execution du programme. La raison est tres simple : la fonction f va appeler la fonction f qui va appeler la fonction f qui va appeler la fonction f... et ainsi de suite, a l'infini. Ou plus precisement, puisqu'un ordinateur n'a pas des capacites infinies, jusqu'a ce que les ressources allouees au programme soient toutes utilisees et que le programme crash.+Cependant, le code précédent est trop simpliste et produira un crash a l’exécution du programme. La raison est très simple : la fonction f va appeler la fonction f qui va appeler la fonction f qui va appeler la fonction f... et ainsi de suite, a l'infini. Ou plus précisément, puisqu'un ordinateur n'a pas des capacités infinies, jusqu’à ce que les ressources allouées au programme soient toutes utilisées et que le programme crash.
  
  
-===== Variable locale une fonction =====+===== Variable locale à une fonction =====
  
-Un petit rappel sur les notions de portee et de duree de vie. Pour le moment, vous n'avez utilise que des variables locales une fonction. Une telle fonction est declaree dans un bloc dans une fonction (dans la fonction ''main'' jusque maintenant, mais c'est valide pour n'importe quelle fonction que vous pouvez creer). Cette variable est utilisable a partir du moment ou elle est definie et jusqu'a la fin du bloc.+Un petit rappel sur les notions de portée et de durée de vie. Pour le moment, vous n'avez utilise que des variables locales à une fonction. Une telle fonction est déclarée dans un bloc dans une fonction (dans la fonction ''main'' jusque maintenant, mais c'est valide pour n'importe quelle fonction que vous pouvez créer). Cette variable est utilisable a partir du moment ou elle est définie et jusqu’à la fin du bloc.
  
 <code cpp> <code cpp>
 { {
-    int i {};  // definition d'une variable i+    int i {};  // définition d'une variable i
     ...     ...
-}              // fin de portee de la variable i+}              // fin de portée de la variable i
 </code> </code>
  
-Les notions de portee (//scope//) et duree de vie (//lifetime//) sont tres proches (pour le moment) :+Les notions de portée (//scope//) et durée de vie (//lifetime//) sont très proches (pour le moment) :
  
-  * la portee est quand la variable est utilisable dans le code ; +  * la portée est quand la variable est utilisable dans le code ; 
-  * la duree de vie est quand la variable existe en memoire de l'ordinateur.+  * la durée de vie est quand la variable existe en mémoire de l'ordinateur.
  
-Pour des variables locales, la portee et la duree de vie d'une variable sont les memes, mais vous verrez qu'il existe une autre categorie de variables (les variables dynamiques), dont la portee et la duree de vie peuvent etre differentes.+Pour des variables locales, la portée et la durée de vie d'une variable sont les mêmes, mais vous verrez qu'il existe une autre catégorie de variables (les variables dynamiques), dont la portée et la durée de vie peuvent être différentes.
  
 <note>**Variables globales** <note>**Variables globales**
  
-Il existe en fait une troisieme categorie : les variables globales, qui ont generalement une portee globale (accessible n'importe ou dans le programme - c'est par exemple le cas de ''std::cout'') et une duree de vie permanente (creation au lancement du programme et destruction lorsque le programme se termine).+Il existe en fait une troisième catégorie : les variables globales, qui ont généralement une portée globale (accessible n'importe ou dans le programme - c'est par exemple le cas de ''std::cout'') et une durée de vie permanente (création au lancement du programme et destruction lorsque le programme se termine).
  
-L'utilisation des variables globales est problematique en termes de conception et d'utilisation, elles doivent etre evitee au maximum. C'est a dire toujours, sauf quand vous avez de tres bonnes justifications pour ne pas respecter cette regle.+L'utilisation des variables globales est problématique en termes de conception et d'utilisation, elles doivent être évitée au maximum. C'est a dire toujours, sauf quand vous avez de très bonnes justifications pour ne pas respecter cette régle.
 </note> </note>
  
-Pour terminer ce rappel, les variables sont accessible dans le meme bloc ou elles sont definies et dans les blocs enfants, mais pas dans les blocs parents ou les blocs qui n'ont pas de relation hierarchique.+Pour terminer ce rappel, les variables sont accessible dans le même bloc où elles sont définies et dans les blocs enfants, mais pas dans les blocs parents ou les blocs qui n'ont pas de relation hiérarchique.
  
 <code> <code>
Ligne 272: Ligne 326:
             std::cout << i << std::endl; // ok, bloc enfant             std::cout << i << std::endl; // ok, bloc enfant
         }         }
-        std::cout << i << std::endl;     // ok, meme bloc+        std::cout << i << std::endl;     // ok, même bloc
     }     }
     std::cout << i << std::endl;         // erreur, bloc parent     std::cout << i << std::endl;         // erreur, bloc parent
     {     {
-        std::cout << i << std::endl;     // erreur, bloc independent+        std::cout << i << std::endl;     // erreur, bloc indépendant
     }     }
 } }
 </code> </code>
  
-Cette notion est tres importante comprendre lorsque vous appelez des fonctions : les variables locales dans ces fonctions sont detruites a la fin de la fonction. Si vous appelez plusieurs fois une fonction, les variables locales sont creees puis detruites a chaque appel. Il n'est pas possible de transmettre des informations entre les differents appels via des variables locales.+Cette notion est très importante à comprendre lorsque vous appelez des fonctions : les variables locales dans ces fonctions sont détruites à la fin de la fonction. Si vous appelez plusieurs fois une fonction, les variables locales sont créées puis détruites à chaque appel. Il n'est pas possible de transmettre des informations entre les différents appels via des variables locales.
  
-Considerez par exemple le code suivant.+Considérez par exemple le code suivant.
  
 <code> <code>
Ligne 289: Ligne 343:
  
 void f() { void f() {
-   int i;   // volontairement non initialisee+   int i;   // volontairement non initialisée
    std::cout << i << std::endl;    std::cout << i << std::endl;
    i = 123;    i = 123;
Ligne 306: Ligne 360:
 #include <iostream> #include <iostream>
 int main() { int main() {
-   int i;   // volontairement non initialisee+   int i;   // volontairement non initialisée
    std::cout << i << std::endl;    std::cout << i << std::endl;
    i = 123;    i = 123;
Ligne 321: Ligne 375:
  
 <code> <code>
-xxx // une valeur aleatoire quelconque, puisque i n'est pas initialise+xxx // une valeur aléatoire quelconque, puisque i n'est pas initialise
 123 123
 123 123
Ligne 327: Ligne 381:
 </code> </code>
  
-Mais il faut bien comprendre que ce qui se passe en realite est que chaque appel de fonction va creer une nouvelle variable locale puis la detruire. Donc meme si le nom est le meme, c'est comme si la variable etait differente. Un code plus correct serait celui ci :+Mais il faut bien comprendre que ce qui se passe en réalité est que chaque appel de fonction va créer une nouvelle variable locale puis la détruire. Donc même si le nom est le même, c'est comme si la variable était différente. Un code plus correct serait celui ci :
  
 <code> <code>
 #include <iostream> #include <iostream>
 int main() { int main() {
-   int i_1;   // volontairement non initialisee+   int i_1;   // volontairement non initialisée
    std::cout << i_1 << std::endl;    std::cout << i_1 << std::endl;
    i_1 = 123;    i_1 = 123;
    std::cout << i_1 << std::endl;    std::cout << i_1 << std::endl;
        
-   int i_2;   // volontairement non initialisee+   int i_2;   // volontairement non initialisée
    std::cout << i_2 << std::endl;    std::cout << i_2 << std::endl;
    i_2 = 123;    i_2 = 123;
Ligne 344: Ligne 398:
 </code> </code>
  
-Avec ce code, vous comprenez bien qu'il n'y a pas de raison que les deux appels a la fonction f possedent la meme valeur dans ''i''. Faites bien attention a cela.+Avec ce code, vous comprenez bien qu'il n'y a pas de raison que les deux appels a la fonction f possèdent la même valeur dans ''i''. Faites bien attention a cela.
  
 <note>**Garantie des comportements** <note>**Garantie des comportements**
  
-En fait, si vous executez le code propose, vous obtiendrez en fait probablement :+En fait, si vous exécutez le code proposé, vous obtiendrez probablement :
  
 <code> <code>
Ligne 357: Ligne 411:
 </code> </code>
  
-La raison est que le compilateur peut optimiser au mieux le programme génère a partir de votre code et peut donc utiliser le meme emplacement en memoire entre les deux appels de fonction, ce qui donnera l'impression que la valeur de ''i'' est transmise.+La raison est que le compilateur peut optimiser au mieux le programme génère a partir de votre code et peut donc utiliser le même emplacement en mémoire entre les deux appels de fonction, ce qui donnera l'impression que la valeur de ''i'' est transmise.
  
-Mais bien sur, sur un code plus complexe, le comportement pourra etre différent. La norme C++ ne garantie pas que le comportement du programme sera de toujours afficher une valeur aléatoire si la variable n'est pas initialisée ou d'afficher une valeur différente entre deux appels de fonction.+Mais bien sur, sur un code plus complexe, le comportement pourra être différent. La norme C++ ne garantie pas que le comportement du programme sera de toujours afficher une valeur aléatoire si la variable n'est pas initialisée ou d'afficher une valeur différente entre deux appels de fonction.
  
-Il est parfois possible d'ecrire des codes de tests, pour comprendre le comportement d'un code. Mais cela ne permet pas de savoir si c'est un comportement specifique a votre compilateur ou si c'est un comportement garantie par la norme C++.+Il est parfois possible d’écrire des codes de tests, pour comprendre le comportement d'un code. Mais cela ne permet pas de savoir si c'est un comportement spécifique a votre compilateur ou si c'est un comportement garantie par la norme C++.
  
-Il est preferable d'ecrire du code dont le comportement est garantie par la norme (et donc eviter par exemple les "undefined behavior", meme s'ils peuvent parfois avoir le comportement attendu), pour avoir un code le plus portable possible. (Meme si vous n'etes pas a l'abris qu'un compilateur particulier ne respecte pas la norme C++ sur certains points, cela peut arriver. Mais c'est suffisamment rare, surtout pour les syntaxes de bases vues dans ce cours).+Il est préférable d’écrire du code dont le comportement est garantie par la norme (et donc éviter par exemple les "undefined behavior", même s'ils peuvent parfois avoir le comportement attendu), pour avoir un code le plus portable possible. (Même si vous n’êtes pas a l’abri qu'un compilateur particulier ne respecte pas la norme C++ sur certains points, cela peut arriver. Mais c'est suffisamment rare, surtout pour les syntaxes de bases vues dans ce cours).
 </note> </note>
  
-^ Chapitre précédent ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ Chapitre suivant ^+[[validation_motifs|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[parametres_arguments|Chapitre suivant]] ^
  
fonctions.1464889450.txt.gz · Dernière modification: 2016/06/02 19:44 par gbdivers