Big Tuto : Apprenez le C++

Chapitre 7 : Les fonctions - 2ème partie

Tutoriel présenté par : Robert Gillard (Gondulzac)
Date d'écriture : 28 novembre 2015
Date de révision : -

      Préliminaires 

   Dans le chapitre 6, nous avons vu des fonctions dont les paramètres étaient passés par valeur et dont l'instruction return ne permettait que de renvoyer une seule valeur, or le C++ permet la modification de variables dans une fonction en passant les adresses de ces variables à la fonction ainsi que la possibilité de retourner plus d'une valeur. wink

   Nous allons donc voir comment contourner ces obstacles liés aux passages de paramètres en utilisant les références dont nous avons parlé dans le Chapitre 4 : Pointeurs et références.

 

Retrouvez les projets complets de ce chapitre :

  

Remarque : A partir de ce chapitre, tous les exemples sont compilés avec VS 2015. Vous pourrez les recompiler avec un autre compilateur si vous le désirez.

 

   1 – Utilisation de pointeurs ou de références dans une fonction.

         1.1 - Un exemple de fonction qui permute deux nombres

  Le passage de paramètres par références peut se faire soit en passant des pointeurs soit en passant des références à la fonction. Dans le premier cas, ce sont les adresses des variables qui sont passées et leurs contenus modifiés à l'intérieur de la fonction, tandis que dans le second cas il s'agit de références aux variables. Nous allons voir l'exemple d'une fonction qui permute deux nombres. smiley

   Nous écrirons d'abord ce programme en utilisant le passage de paramètres par valeurs, ainsi nous pourrons mieux analyser ce problème pour voir les modifications à apporter pour obtenir la permutation. wink

 

   Premier exemple : passage de paramètres par valeurs :

//Projet 047Fonctions10
//Pointeurs et références dans les fonctions
//Permutation de 2 nombres
//Passage de paramètres par valeurs
#include <iostream>
 
using namespace std;
using uint = unsigned int;
 
// Déclaration de la fonction Permute
uint Permute(uint valeur1, uint valeur2);
 
 
int main()
{
 
uint nombre1(17), nombre2(34);
 
cout << "Dans main(), avant appel de la fonction Permute(nombre1,nombre2)" << endl;
cout << "nombre1 = " << nombre1 << " nombre2 = " << nombre2 << endl << endl;
 
//Appel de la fonction Permute()
Permute(nombre1, nombre2);
 
cout << "Dans main(), apres appel de la fonction Permute(nombre1,nombre2)" << endl;
cout << "nombre1 = " << nombre1 << " nombre2 = " << nombre2 << endl;
 
cin.get();
return 0;
 
}
 
 
uint Permute(uint val1, uint val2)
{
uint temp;
 
cout << "Dans la fonction Permute(val1,val2), avant permutation" << endl;
cout << "nombre1 = " << val1 << " nombre2 = " << val2 << endl << endl;;
 
temp = val1;
val1 = val2;
val2 = temp;
 
cout << "Dans la fonction Permute(val1,val2), apres permutation" << endl;
cout << "nombre1 = " << val1 << " nombre2 = " << val2 << endl << endl;
 
return 0;
}

   Ce qui donne dans la console :

 

   Au début de la fonction main() on donne respectivement les valeurs 17 et 34 à deux variables ''nombre1'' et ''nombre2'' de type unsigned int. On affiche les valeurs de ces variables avant l'appel à la fonction Permute() puis on appelle celle-ci.

   Dans la fonction Permute(), on utilise une variable temporaire nommée ''temp'' afin d'effectuer la permutation des valeurs des variables ''val1'' et ''val2'' passées en paramètres. Nous voyons que les valeurs sont bien échangées dans la fonction Permute() mais dès que l'on retourne dans la fonction main(), on retrouve les valeurs initiales de nos variables d'origine. Ce n'est manifestement pas ce que nous voulions faire... surprise

   Depuis le chapitre 6, nous savons pourquoi cela ne marche pas et nous allons en faire un bref rappel. wink Quand dans main() on fait appel à la fonction Permute(nombre1, nombre2), il s'agit en fait des copies de ces variables qui sont passées à la fonction. Ces variables agissent en variables locales dans la fonction et sont détruites au sortir de celle-ci. Donc, bien que les valeurs de ces variables aient été permutées à l'intérieur de la fonction, elles sont détruites dès que la fonction repasse la main à la fonction main(). Et voila pourquoi nous retrouvons nos valeurs initiales dans main(), après l'appel à la fonction Permute()indecision

   La solution consiste à passer les adresses de nos variables à la fonction Permute(), plutôt que les variables elles-mêmes. C'est ce que l'on appelle le passage de valeurs par références, nous l'avons signalé plus haut et nous pouvons le faire de deux manières :
- par l'utilisation de pointeurs
- par l'utilisation de références


   Deuxième exemple : permutation de deux nombres à l'aide de pointeurs :

//Projet 048Fonctions11
//Pointeurs et références dans les fonctions
//Permutation de 2 nombres
//Passage des adresses à l'aide de pointeurs
#include <iostream>
 
using namespace std;
using uint = unsigned int;
 
// Déclaration de la fonction Permute
uint Permute(uint *valeur1, uint *valeur2);
 
 
int main()
{
 
uint nombre1(17), nombre2(34);
 
cout << "Dans main(), avant appel de la fonction Permute(&nombre1,&nombre2)" << endl;
cout << "nombre1 = " << nombre1 << " nombre2 = " << nombre2 << endl << endl;
 
//Appel de la fonction Permute()
Permute(&nombre1, &nombre2);
 
cout << "Dans main(), apres appel de la fonction Permute(&nombre1,&nombre2)" << endl;
cout << "nombre1 = " << nombre1 << " nombre2 = " << nombre2 << endl;
 
cin.get();
return 0;
 
}
 
 
uint Permute(uint *val1, uint *val2)
{
uint temp;
 
cout << "Dans la fonction Permute(&val1,&val2), avant permutation" << endl;
cout << "nombre1 = " << *val1 << " nombre2 = " << *val2 << endl << endl;;
 
temp = *val1;
*val1 = *val2;
*val2 = temp;
 
cout << "Dans la fonction Permute(&val1,&val2), apres permutation" << endl;
cout << "nombre1 = " << *val1 << " nombre2 = " << *val2 << endl << endl;
 
return 0;
}

 

   Ce qui donne dans la console :

 

   Ok, cette fois ça marche... laugh

   Dans la déclaration de la fonction Permute(), nous utilisons deux pointeurs comme arguments, *valeur1 et *valeur2. Et quand dans main(), nous appelons la fonction Permute(&nombre1, &nombre2), ce n'est plus les copies des variables ''nombre1'' et ''nombre2'' qui sont passées à la fonction mais bien les adresses de ces variables. Nous voyons ensuite dans la définition de la fonction Permute() que ce sont les valeurs contenues à ces adresses qui sont échangées (la permutation se fait à l'aide de la variable ''temp'' ainsi que des pointeurs déréférencés).

   Finalement, dans la fonction main(), après appel à la fonction Permute(), nous retrouvons nos variables ''nombre1'' et nombre2'' dont les valeurs ont bien été permutées. Nous allons maintenant voir notre dernier exemple de permutation de deux valeurs à l'aide de références. wink

 

   Troisième exemple : permutation de deux nombres à l'aide de références :

//Projet 049Fonctions12
//Pointeurs et références dans les fonctions
//Permutation de 2 nombres
//Passage des adresses à l'aide de références
#include <iostream>
 
using namespace std;
using uint = unsigned int;
 
// Déclaration de la fonction Permute
uint Permute(uint &rvaleur1, uint &rvaleur2);
 
 
int main()
{
 
uint nombre1(17), nombre2(34);
 
cout << "Dans main(), avant appel de la fonction Permute(nombre1,nombre2)" << endl;
cout << "nombre1 = " << nombre1 << " nombre2 = " << nombre2 << endl << endl;
 
//Appel de la fonction Permute()
Permute(nombre1, nombre2);
 
cout << "Dans main(), apres appel de la fonction Permute(nombre1,nombre2)" << endl;
cout << "nombre1 = " << nombre1 << " nombre2 = " << nombre2 << endl;
 
cin.get();
return 0;
 
}
 
 
uint Permute(uint &rval1, uint &rval2)
{
uint temp;
 
cout << "Dans la fonction Permute(val1,val2), avant permutation" << endl;
cout << "nombre1 = " << rval1 << " nombre2 = " << rval2 << endl << endl;;
 
temp = rval1;
rval1 = rval2;
rval2 = temp;
 
cout << "Dans la fonction Permute(val1,val2), apres permutation" << endl;
cout << "nombre1 = " << rval1 << " nombre2 = " << rval2 << endl << endl;
 
return 0;
}

 

   Les résultats dans la console sont ceux du précédent projet, il n'y a donc pas lieu de les afficher. smiley
   Lorsqu'on appelle la fonction Permute(nombre1, nombre2), ce sont les variables ''nombre1'' et nombre2'' qui sont passées en paramètres et non leurs adresses. Cependant, dans la définition de cette fonction, les paramètres sont identifiés comme étant des références de ces variables et c'est sur ces références que s'opère la permutation (dans le chapitre précédent nous avons vu que toute modification d'une référence est répercutée sur la variable à laquelle est liée la référence wink).

   Par rapport au projet précédent utilisant des pointeurs, celui-ci, utilisant des références se trouve quelque peu allégé. L'appel de la fonction Permute() à qui l'on passe les variables en paramètres réels se révèle un peu moins lourd que le passage de paramètres avec des pointeurs.

   Il s'ensuit de ces exemples que si, pour l'écriture d'une fonction, vous avez le choix entre pointeurs ou références, préférez ces dernières, le code est plus léger à implémenter et le risque d'erreurs lié à une utilisation plus massive des pointeurs est moins grand. cool

 

        1.2 – Le spécificateur const et passage d'adresses par références

   Si pour l'une ou l'autre raison, les paramètres que vous voulez passer à une fonction et quel que soit leur type, ne peuvent absolument pas être modifiés, vous avez tout intérêt à utiliser le spécificateur ''const'' dans la déclaration et la définition de votre fonction. De même que dans le projet précédent, les paramètres passés à la fonction du projet suivant sont identifiés comme références (mais à des valeurs constantes, cette fois). Un premier exemple simple va vous en démontrer toute l'utilité. angel

//Projet 050Fonctions13
//Pointeurs et références dans les fonctions
//Passage des adresses à l'aide de références sur des constantes
#include <iostream>
#include <string>
 
using namespace std;
using uint = unsigned int;
 
// Déclaration de la fonction Somme
uint Somme( const uint &nombre1, const uint &nombre2);
 
 
int main()
{
 
const uint nb1(12); // Valeur constante
const uint nb2(18); // Valeur constante
uint resultat(0);
cout << "On definit 2 constantes unsigned int: nb1 = 12 et nb2 = 18" << endl;
cout << "La fonction Somme() retourne la somme des references a ces valeurs" << endl << endl;
 
resultat = Somme(nb1, nb2);
 
cout << "Le resultat de la somme de 12 et 18 est : " << resultat << endl;
 
cin.get();
return 0;
 
}
 
 
uint Somme(const uint &rvaleur1, const uint &rvaleur2)
{
return rvaleur1 + rvaleur2;
}

 

   Ce qui donne dans la console :

 

   Les variables nb1 et nb2 ayant été définies comme constantes, il est donc impossible de modifier les valeurs de leurs références dans la fonction Somme().

   Allez... indecision Une petite question : Aurions-nous pu, à titre d'exemple, dans la définition de la fonction Somme(), lier une seconde référence à la valeur ''rvaleur1'' passée en paramètre à la fonction...? surprise

   La réponse est oui (pour autant que cette référence soit elle-même une référence d'un const unsigned int) car de même que &rvaleur1 est un alias de la constante nb1, si nous lions une référence ''&ref'' à la constante rvaleur1, la nouvelle référence sera également un alias de la constante nb1 (voir chapitre 4 – paragraphe 1.3 : les références et le qualificateur const pour réviser ! laugh).

   Dans ce cas nous pourrions écrire la fonction Somme() comme ceci : 

uint Somme(const uint &rvaleur1, const uint &rvaleur2)
{
const uint &ref = rvaleur1;
return ref + rvaleur2;
}

   Avec le même résultat que dans la console ci-dessus. wink 
   Cela n'a bien entendu pas d'utilité dans cet exemple mais n'est présenté que dans un but pédagogique. cheeky
   Et vous pouvez refaire l'exemple du projet en utilisant des pointeurs cette fois. wink Cela pourra aider les débutants en C++ à bien appréhender les différences entre pointeurs et références dans les fonctions (Exercice 1).

   Je voudrais apporter une précision au sujet de ce qui a été dit dans le chapitre 6 lors du projet 045Fonctions8 quand j'ai parlé de constantes ''top-level''. Il est bien entendu que c'est lors de la déclaration d'une référence ou d'un pointeur constants que l'on parlera de constante de haut niveau ou top-level const. A contrario, une constante alphanumérique ou de type string sera déclarée comme constante de bas niveau ou low-level const.


   Cette précision étant apportée, nous allons maintenant montrer un second exemple, tiré du projet 035Strings3 (Chapitre 5 – Autres exemples d'opérations sur les chaînes), dans lequel nous comparions la longueur de deux chaînes. Mais ici nous allons écrire une fonction retournant un booléen qui nous permettra de retrouver la chaîne la plus longue. wink

//Projet 051Fonctions14
//Pointeurs et références dans les fonctions
//Comparaison de la longueur de deux chaînes
#include <iostream>
#include <string>
 
using namespace std;
using uint = unsigned int;
 
// Déclaration de la fonction EstPlusGrand()
bool EstPlusGrand(const string &chaine1, const string &chaine2);
 
 
int main()
{
 
const string ch1 { "Assourbanipal" };
const string ch2 { "Assourdan" };
 
if (EstPlusGrand(ch1, ch2))
cout << "La chaine " << ch1 << " est plus grande que la chaine " << ch2 << endl;
else
cout << "La chaine " << ch2 << " est plus grande que la chaine " << ch1 << endl;
 
cout << "La longueur de " << ch1 << " est de " << ch1.size() << " caracteres" << endl;
cout << "La longueur de " << ch2 << " est de " << ch2.size() << " caracteres" << endl;
 
cin.get();
return 0;
 
}
 
 
bool EstPlusGrand(const string &rchaine1, const string &rchaine2)
{
return (rchaine1 > rchaine2);
}

 

   Et le résultat dans la console :

 

   Il n'y avait pas besoin de passer par une fonction pour connaître la plus longue des deux chaînes, mais comme nous étudions le passage de paramètres par références dans les fonctions, cet exemple est intéressant à plus d'un titre.cool

   Nous déclarons une fonction ''EstPlusGrand'', contenant deux ''const string'' en paramètres et retournant un booléen. Dans la définition de la fonction, les paramètres ch1 et ch2 sont identifiés comme étant des références et la fonction ne fait que retourner une expression booléenne (rchaine1 > rchaine2), et que cette expression soit vraie ou fausse, elle va être testée dans la fonction main().

   En effet, dans la fonction main(), la valeur de retour est reçue en testant : if (EstPlusGrand(ch1, ch2))

   Or nous savons que cette valeur de retour sera vraie si l'expression : return (rchaine1 > rchaine2) est vraie, et fausse dans le cas contraire. wink

   Et pour terminer l'exemple, nous affichons le nombre de caractères des chaînes avec ch1.size() et ch2.size().

   Je rappelle que la longueur de deux chaînes de caractères n'est pas nécessairement liée au nombre de leurs caractères (voir chapitre 5). Donc dans les chaînes ''Assourdan'' et ''Assourbanipal'', la chaîne la plus grande est bien entendu ''Assourdan'' car le premier caractère différent des deux chaînes est le ''d'' qui a une valeur supérieure à ''b''. wink


   Le type chaîne ''size_type''

   Nous savons maintenant que ''size()'' retourne le nombre de caractères d'un tableau de type ''string''. Il semblerait donc logique que size() retourne un entier ou mieux, un unsigned int mais il n'en est rien ; à la place, size() retourne une valeur de type string::size_type.

   Il se fait que la classe ''string'' ainsi que d'autres types de librairies définissent un certain nombre de ce qu'on appelle des ''types compagnons'' ou ''companions types''. Le type size_type est l'un de ces types compagnons et pour pouvoir l'utiliser nous devons ajouter l'opérateur de résolution de portée pour signaler qu'il est défini dans la classe <string>.

   Bien que l'on ne connaisse pas le type précis d'un type ''string::size_type'', nous savons qu'il s'agit d'un type non-signé, assez grand pour contenir n'importe quelle chaîne de caractères. Ceci nous rappelle le type ''size_t'' défini dans le fichier <cstddef> et dont nous avons parlé dans le chapitre 6.

   Le nouveau standard du C++ 11 permet le raccourci de la forme ''string::size_type'' en utilisant soit le spécificateur de type ''auto'' soit ''decltype''. Dans l'exemple précédent nous aurions pu déclarer deux variables ''longueurChaine1'' et longueurChaine2 comme ceci :
string::size_type longueurChaine1 = ch1.size();
string::size_type longueurChaine2 = ch1.size();
   ou mieux :
auto longueurChaine1 = ch2.size();
auto longueurChaine2 = ch2.size();

   Et en affichant le nombre de caractères des chaînes avec les variables longueurChaine1 et longueurChaine2 plutôt que ch1.size() et ch2.size(). Dans ce cas, les variables longueurChaine1 et longueurChaine2 sont de type string::size_typewink


   2 – Renvoi de plusieurs valeurs à l'aide de références


        2.1 – Renvoi de valeurs à l'aide de pointeurs

   Une fonction ne peut retourner qu'une seule valeur... frown Qui a dit cela ? surprise Il existe cependant des cas où nous avons besoin qu'une fonction renvoie plusieurs valeurs. blush Le C++ nous le permet en effectuant le passage de valeurs par références. Dire que l'on passe des valeurs par références est un terme général qui inclut aussi bien les pointeurs que les références elles-mêmes. angel

   Nous allons présenter maintenant un exemple ludique renvoyant plusieurs valeurs à l'aide de pointeurs. wink

   Vous avez envoyé 10 fantassins et 10 archers en reconnaissance. L'ennemi leur tend une embuscade et certains d'entre eux sont tués. Nous créons une fonction Survivants() qui vous demandera d'entrer le nombre de fantassins et d'archers tués et elle renverra alors le nombre d'archers et le nombre de fantassins survivants ainsi que le nombre total de survivants. cool

//Projet 052Fonctions15
//Pointeurs et références dans les fonctions
//Renvoi de plusieurs valeurs à l'aide de pointeurs
#include <iostream>
#include <conio.h>
#include <string>
 
using namespace std;
using uint = unsigned int;
 
// Déclaration de la fonction Survivants()
uint Survivants(uint *nb_fantassins, uint *nb_archers);
 
 
int main()
{
uint nb_fantassins(10);
uint nb_archers(10);
uint nb_survivants(0);
 
nb_survivants = Survivants(&nb_fantassins, &nb_archers);
 
cout << "Le nombre de fantassins survivants est : " << nb_fantassins << endl;
cout << "Le nombre d'archers survivants est : " << nb_archers << endl;
cout << "Le nombre total de survivants est " << nb_survivants << endl << endl;
 
_getch();
return 0;
}
 
 
 
uint Survivants(uint *nb_fantassins, uint *nb_archers)
{
uint nb_fantassins_perdus(0);
uint nb_archers_perdus(0);
 
cout << "ENTREZ IMPERATIVEMENT DES NOMBRES COMPRIS ENTRE ( 0 - 10 )" << endl << endl;
 
cout << "Combien de fantassins avez-vous perdus ";
cin >> nb_fantassins_perdus;
 
while ((nb_fantassins_perdus < 0) || (nb_fantassins_perdus > 10))
{
cout << "Entrez un nb >=0 ou <=10 ";
cin >> nb_fantassins_perdus;
}
 
cout << endl;
cout << "Combien d'archers avez-vous perdus ";
cin >> nb_archers_perdus;
 
while ((nb_archers_perdus < 0) || (nb_archers_perdus > 10))
{
cout << "Entrez un nb >=0 ou <=10 ";
cin >> nb_archers_perdus;
}
 
*nb_fantassins -= nb_fantassins_perdus;
*nb_archers -= nb_archers_perdus;
 
return *nb_fantassins + *nb_archers;
}

 

   Ce qui pourrait par exemple donner dans la console :

 

   Si vous entrez des valeurs supérieures aux limites fixées, la fonction vous redemandera d'entrer des nouvelles valeurs ne dépassant pas ces limites. Celles-ci sont bien entendu 0, si vous sortez indemne de cette embuscade et du nombre maximum de 10 fantassins et 10 archers que vous avez envoyés en éclaireurs. laugh

   Ce qui pourrait avoir pour résultats :

 

   Nous déclarons une fonction Survivants() qui prend en paramètres un pointeur sur nb_fantassins ainsi qu'un autre pointeur sur nb_archers. Dans la définition de cette fonction, nous déclarons deux variables locales de type unsigned int, nb_fantassins_perdus et nb_archers_perdus. On demande alors à l'utilisateur d'entrer des valeurs qui seront stockées dans ces variables ; ces valeurs doivent être comprises ente 0 et 10 puisque 10, nous venons d'en parler plus haut, est le nombre de fantassins ainsi que le nombre d'archers que vous avez envoyés au casse-pipe ! indecision

   Le nombre de fantassins et d'archers perdus sont ensuite soustraits du contenu des adresses passées à la fonction par les pointeurs *nb_fantassins et *nb_archers afin d'obtenir le nombre de leurs survivants. Pour terminer, nous retournons le nombre total de survivants à l'aide des pointeurs déréférencés *nb_fantassins et *nb_archersangel

   Voilà pour ce qui est de cet exemple. Les débutants en C++ qui le désirent, pourront également refaire cet exemple à l'aide des références (Exercice 2).


2.2 – Utilisation de ''string::size_type'' comme type de retour d'une fonction

   Nous allons présenter un troisième et dernier exemple en ce qui concerne le renvoi de plusieurs valeurs à l'aide de références dans ce chapitre. Dans cet exemple nous allons rechercher le nombre de fois qu'un certain caractère se retrouve dans une chaîne (le nombre d'occurrences) ainsi que la position de ce premier caractère dans la chaîne. wink

   La fonction, nommée Recherche_char(), retournera le type ''string::size_type'' et utilisera les spécificateurs de types ''auto'' et ''decltype'' dans sa définition.

//Projet 053Fonctions16
//Pointeurs et références dans les fonctions
//Une fonction qui renvoie string::size_type comme type de retour
#include <iostream>
#include <conio.h>
#include <string>
 
using namespace std;
using uint = unsigned int;
 
// Déclaration de la fonction Recherche_char()
string::size_type Recherche_char(const string &chaine, const char c, string::size_type
&nb_occurrences);
 
 
int main()
{
//La chaine sur laquelle se porte la recherche
const string chaine{ "Nabuchodonosor" };
 
//Le caractère à rechercher
const char c = 'o';
 
//Le nb d'occurrences de 'o' dans "Nabuchodonosor"
string::size_type compteur(0);
 
//Recherche_char() renverra la 1ère position de 'o' dans la chaîne
auto pos1 = Recherche_char(chaine, c, compteur);
 
cout << endl;
cout << "Il y a " << compteur << " 'o' dans " << chaine << endl;
cout << "Le premier 'o' se trouve en position " << pos1 << endl;
 
_getch();
return 0;
}
 
 
string::size_type Recherche_char(const string &chaine, const char caract, string::size_type &nb_occurrences)
{
//Raccourci pour string::size_type position1 = chaine.size()
auto position1 = chaine.size();
 
//decltype extrait le type de position1 comme étant de type string::size_type
for (decltype (position1) i = 0; i != chaine.size(); ++i)
{
if (chaine[i] == caract) // caractère trouvé
{
if (position1 == chaine.size()) // Toujours vrai donc :
position1 = i; // On se souvient de la 1ère position
 
++nb_occurrences;
}
}
 
return position1;
}

 

   Et les résultats dans la console : 

 

   Et bien, un peu d'explications ne ferait pas de mal... laugh

   Voyons la fonction Recherche_char() en premier. Celle-ci accepte en paramètres une référence à une chaîne de caractères, une variable const char représentant le caractère à rechercher ainsi qu'une référence du nombre d'occurrences du caractère dans la chaîne. Son type de retour est de type string::size_type.

   Dans l'implémentation de la fonction, une variable ''position1'', qui représentera la position de la première occurrence du caractère à rechercher est initialisée à la valeur de la longueur de la chaîne, nous allons voir pourquoi. wink

   Nous parcourons une boucle de 0 à chaine_size() - 1 pour rechercher toutes les occurrences de notre caractère. Pour chaque caractère trouvé, on teste ensuite si la variable position1 est bien égale à chaine_size(). Elle l'est, nous l'avons définie plus haut et qui plus est, elle l'est toujours, puisque chaine_size() ne varie pas. Nous donnons donc la valeur de la position du premier caractère trouvé à la variable position1 et on incrémente le nombre d'occurrences. La fonction retourne ensuite la valeur de la variable position1.

   Nous passons maintenant à la fonction main().

   Nous définissons ''Nabuchodonosor'' comme chaîne de type const string ainsi que le caractère 'o' dont nous allons devoir trouver le nombre d'occurrences dans la chaîne. Une variable ''compteur'' de type string::size_type est ensuite initialisée à 0. C'est cette variable qui sera passée en paramètre à la fonction Recherche_char() pour trouver le nombre d'occurrences du caractère 'o' de la chaîne.

   On appelle la fonction Recherche_char() en passant la chaîne de caractères, le caractère à retrouver ainsi que le nombre d'occurrences de ce caractère qui, nous venons de le voir est égal à 0 au départ. On affiche ensuite le nombre d'occurrences du caractère 'o' dans ''Nabuchodonosor'' ainsi que la position de ce premier caractère dans la chaîne. cool


   Un petit challenge (Exercice 3)

   Je vous propose de modifier ce programme en y ajoutant la position de chaque occurrence de 'o' dans la chaîne ''Nabuchodonosor'' (en utilisant ce que nous avons appris jusqu'à présent, bien entendu wink).
1. Soit vous ajoutez un tableau d'unsigned int en paramètre de la fonction Recherche_char(). Par exemple : uint tab[]. Ce tableau sera destiné à acquérir les valeurs des positions des caractères 'o' dans la chaîne. La fonction doit retourner le tableau. wink
2. Soit vous ajoutez un pointeur unsigned int en paramètre de la fonction Recherche_char(). Par exemple : uint *ptrTab. La fonction doit retourner le pointeur. wink

   Dans les deux cas, vous devriez avoir un résultat de ce genre dans la console: 

 

   Les corrigés des trois exercices proposés seront présentés à la fin du chapitre 8. angel

@ bientôt pour le Chapitre 8 - Les fonctions (3) !

Gondulzak. 
   

 

Connexion

CoalaWeb Traffic

Today136
Yesterday178
This week636
This month4310
Total1743517

25/04/24