Définir un type à soi : Pour cela, vous devez d'abord déclarer votre type en utilisant le mot-clé C++ struct.
struct eleve { char nom[50]; char prenom[50]; char diplome[20]; int age; int moyenneT1; int moyenneT2; };
Bon, je vous explique! Je viens de déclarer un nouveau type. Ce nouveau type, je l'ai appelé eleve. Le nom de votre type doit
suivre le mot-clé struct puis vous créez un bloc (entre { }) afin de définir votre type.
Ici, mon type eleve est composé de 6 champs. Pour chaque champ, vous devez préciser son type et son nom. Vous voyez que ça a une autre gueule allure qu'un simple int !
Attention de ne pas oublier le ; à la fin du bloc de définition!
Donc, une fois déclaré mon type eleve, je peux déclarer des variables de ce type. Toutes ces variables auront ces 6 champs. Un exemple ?
struct eleve { char nom[50]; char prenom[50]; char diplome[20]; int age; int moyenneT1; int moyenneT2; }; int main() { eleve e1, e2, e3; eleve classe[13]; return 0; }
Dans l'exemple ci-dessus, j'ai déclaré mon nouveau type eleve puis dans mon main, j'ai créé 3 variables de type eleve (e1, e2 et e3), j'ai également déclaré une variable nommée classe de type "tableau de 13 éléments, chaque élément étant de type eleve". Les 3 variables e1, e2, e3 ainsi que chaque élément du tableau classe ont les 6 champs nom, prenom, ..., moyenneT2.
- Ok mais comment j'accède aux différents champs d'une variable de type eleve ?!
- C'est très simple !
Pour accéder à un des champs d'une variable de type eleve, il suffit d'écrire le nom de votre variable suivi du "." puis le nom du champ auquel
vous voulez accéder. Je vous donne un exemple !
struct eleve { char nom[50]; char prenom[50]; char diplome[20]; int age; int moyenneT1; int moyenneT2; }; int main() { eleve e1, e2, e3; eleve classe[13]; // La variable classe est un tableau de 13 éléments. Chaque élément étant de type (srtucture) eleve. // Le champ age de l'eleve e1 prend la valeur 15 e1.age = 15; cout << "Donner un nom à l'élève e1 : "; // Le champ nom de l'eleve e1 prend pour valeur ce qu'a saisi l'utilisateur cin >> e1.nom; for(int i=0; i<13; i++) { // Le champ age de chaque eleve du tableau classe prend la valeur 20+i classe[i].age = 20+i; } return 0; }
Le programme ci-dessus montre comment accéder à quelques champs d'une variable de type eleve.
La seule difficulté est la variable classe. Et encore...
Répondez aux questions suivantes et vous verrez que ce n'est pas si compliqué que ça !
- Quel est le type de cette variable ?
- Un tableau !!!
- Oui mais un tableau de quoi ?! N'oubliez pas une chose : Quand vous parlez de tableau, il est très important de toujours préciser le type des
éléments du tableau !!! TOUJOURS !
- Ah ! pardon... Tu as tout à fait raison. La variable classe est de type tableau d'eleve.
- Bien. Maintenant, de quel type est "classe[i]" ?
- "classe[i]" est le i+1ème élément du tableau classe. Comme tous les éléments du tableau classe sont de type eleve, j'en conclue que
"classe[i]" est de type eleve.
- Exact ! Et "classe[i]" étant de type eleve, je peux accéder à n'importe lequel de ses champs. Si, par exemple, je veux accéder au champ moyenneT2,
il me suffit d'écrire "classe[i].moyenneT2". Ou encore, si je veux accéder au champ prenom du 3ème eleve de classe, j'écrirai "classe[2].prenom".
- Ahhh j'ai tout compris !
- Je résume : classe est un tableau d'eleve. "classe[0]", "classe[1]", ou encore "classe[i]" sont tous de type eleve. Donc "classe[0].nom" me
permet d'accéder au champ nom du 1er eleve de mon tableau classe, comme "classe[9].diplome" me permet d'accéder au champ diplome du 10è eleve...
Pour résumer : En C++, on peut définir nos propres types de variables grâce au mot-clé struct. Une structure est un type complexe
contenant un ou plusieurs champs. Pour accéder à un des champs d'une structure, il suffit d'écrire le nom de la variable suivi d'un point "." et
indiquer le nom du champ désiré. C'est aussi simple que ça !
Il est important de noter que les champs d'une structure peuvent être de n'importe quel type: int, char, string ou même structure! Vous verrez dans les exercices
ci-dessous quelques exemples.
struct eleve { int age; float moyenne; };
Ici, pas vraiment de piège. On continue !
struct eleve { char nomEleve[50]; matiere matieres[3]; };
En suivant scrupuleusement l'énoncé, il ne devrait pas y avoir de problème. Une remarque cependant: Étant donné que le type eleve contient un champ utilisant le type matiere, il faut déclarer le type matiere avant de déclarer le type eleve. Voici le corrigé complet:
struct matiere { char nomMatiere[50]; float note; }; struct eleve { char nomEleve[50]; matiere matieres[3]; };
matiere creerMatiere(char nom[50], float n) { matiere m; strcpy(m.nomMatiere, nom); m.note = n; return m; }
Le tableau de caractères nom est copié dans le champ nomMatiere de m. Puis le champ note de m prend la valeur du paramètre n. Pas d'énorme difficulté non plus...
Par contre, la fonction qui suit est d'un autre niveau ! Accrochez-vous !
eleve creerEleve(char nom[50]) { eleve e; int note; char nomMatiere[50]; strcpy(e.nomEleve, nom); for(int i=0; i<3; i++) { cout << "Entrer le nom de la matiere " << i+1 << " : "; cin >> nomMatiere; cout << "Entrer la note dans cette matiere : "; cin >> note; e.matieres[i] = creerMatiere(nomMatiere, note); } return e; }
Ok, elle n'était pas évidente. Essayez de bien comprendre ce que fait cette fonction: Elle crée une variable de type eleve. Puis elle va
remplir chacun des champs de cette variable e. Le champ nomEleve ne pose pas de problème: on utilise la fonction C++ strcpy.
Par contre le champ matieres est plus compliqué à remplir. En effet, non seulement il est de type tableau (donc il contient
plusieurs éléments) mais en plus chaque élément est de type matiere (donc il contient plusieurs champs).
- Le champ matieres est un champ contenant plusieurs éléments qui eux-mêmes contiennent plusieurs champs ! Wahouah !!! Désolé mais c'est trop pour moi!
Je te rapelle que je suis un dangereux du C++ moi ! Je crois que là je suis trop en danger pour continuer...
- Oh ! attends ! Je sais que l'exo est vache mais bon, c'est comme ça qu'on apprend ! Il faut s'accrocher ! Ne paniquons pas et allons-y en douceur:
Ma variable e est de type eleve. Elle contient donc un champ matieres qui n'est rien d'autre qu'un tableau de 3
matiere. Donc, chaque élément du tableau matieres est un objet de type matiere.
- Jusque là, je te suis !
- La fonction creerMatiere crée puis remplit et enfin retourne un objet de type matiere.
- Ouais...
- Il suffit donc d'appeler ma fonction creerMatiere, de récupérer son retour et de l'affecter à un élément de mon tableau matieres.
Répéter cette action pour chaque élément du tableau matieres et le tour est joué!
- T'as oublié que la fonction creerMatiere prend 2 paramètres. Qu'est-ce qu'on met dans ces 2 paramètres ?!
- Eh bien là, on n'a pas vraiment le choix: on va demander à l'utilisateur de saisir un nom de matière et une note ! Et ce pour chacune des 3 matières.
- Ahhh j'ai tout compris !
- Alors on continue !
float calculMoyenne(eleve e) { float somme = 0; for(int i=0; i<3; i++) { somme = somme + e.matieres[i].note; } return (somme / 3); }
Ici non plus ce n'est pas très compliqué ! Allez courage, nous en avons presque terminé avec les exercices.
int main() { eleve e; e = creerEleve("Mr Dangereux"); cout << "moyenne = " << calculMoyenne(e) << endl; system("pause"); return 0; }
Et voilà ! En appelant simplement la fonction creerEleve, vous avez non seulement créé un eleve mais vous avez aussi créé ses 3 matières (nom + note)! C'est pourquoi vous pouvez afficher la moyenne de l'eleve. Pas mal hein ?!
struct classe { char nomClasse[50]; eleve eleves[10]; }; classe creerClasse(char nom[50]) { classe c; char nomEleve[50]; strcpy(c.nomClasse, nom); for(int i=0; i<10; i++) { cout << "Entrer le nom de l'eleve " << i+1 << " : "; cin >> nomEleve; c.eleves[i] = creerEleve(nomEleve); } return c; } float moyenneClasse(classe c) { float somme = 0; for(int i=0; i<10; i++) { for(int j=0; j<3; j++) { somme = somme + c.eleves[i].matieres[j].note; } } return (somme / 30); }
La fonction creerClasse n'a rien d'original.
Par contre la fonction moyenneClasse est assez tordue: Nous
utilisons 2 boucles for. Une première pour parcourir nos 10 eleve et une seconde pour parcourir nos 3 matiere.
Regardez la ligne somme = somme + c.eleves[i].matieres[j].note;. Elle est très longue. Trop longue même!
Ne voyez-vous pas un moyen de simplifier la fonction moyenneClasse ?
Essayez en appelant la fonction calculMoyenne!
float moyenneClasse(classe c) { float somme = 0; for(int i=0; i<10; i++) { somme = somme + calculMoyenne(c.eleves[i]); } return (somme / 10); }
Plus qu'une seule boucle for ! C'est bien plus simple à lire et donc à comprendre. Vous ne trouvez pas ?
Ouf ! On y est arrivé sain et sauf ! Encore bravo si vous êtes parvenu à faire ces exercices. Je vous invite à souffler un peu et quand vous serez remis, vous pourrez aller jeter un oeil du côté des pointeurs :D !
return nextChapter;