C++ propose différents conteneurs pour stocker des éléments de même type de manière ordonnée.
Il y a std::array pour les conteneurs de taille fixe et std::vector, qui offre des capacités de redimensionnement dynamique.
Quand on déclare un tableau ou un vecteur, il faut préciser le type des éléments que ce conteneur va contenir. Les tableaux nécessitent aussi une taille. Regarde ces exemples pour voir l'initialisation des deux types de conteneurs :
#include <array>
#include <string>
// std::array<element_type, size> variable_name {list of elements}
std::array<std::string, 3> indie_rock {"yeah", "yeah", "yeah"};
// indie_rock contains the elements "yeah" three times
Les vecteurs ont généralement besoin de plus d'espace, car ils allouent de la mémoire pour une croissance future. Tu n'as pas besoin de préciser une taille :
#include <vector>
// std::vector<element_type> variable_name {list of elements}
std::vector<int> countdown {3, 2, 1};
// countdown contains the elements 3, 2 and 1
Remarque : tu n'as pas besoin de connaître les mécanismes exacts derrière le concept de template pour l'instant, il aura son propre concept plus bas dans l'arbre du programme.
Les vecteurs et les tableaux partagent les mêmes fonctions pour accéder à leurs éléments.
On peut utiliser les fonctions membres front et back pour obtenir le premier et le dernier élément du conteneur.
Il y a aussi at et l'opérateur [] pour accéder à des éléments spécifiques.
countdown[0];
// => 3
countdown.at(2);
// => 1
countdown[1] = 4;
// countdown now contains 3, 4 and 1
indie_rock.back() = "yeahs";
// indie_rock is now "yeah", "yeah", "yeahs"
Remarque : si tu choisis une position qui n'est pas dans la plage de ton conteneur,
[]peut entraîner un comportement indéfini. La fonctionatlèvera une exception, ce qui pourrait te simplifier la vie à long terme.
Comme un vector n'a pas une taille fixe, il est possible d'ajouter ou de supprimer des éléments.
Deux fonctions courantes pour cela sont emplace_back et pop_back.
std::vector<std::string> witches {"Holly", "Alyssa", "Shannen"};
witches.pop_back();
// Shannen is no longer with the witches
witches.emplace_back("Rose");
// Rose has joined the team
Tu peux vérifier si les conteneurs sont vides avec la fonction membre empty.
Si tu veux connaître le nombre d'éléments, tu peux utiliser size.
Tu es assistant pédagogique et tu corriges les examens d'élèves. Garder la trace des résultats à la main devient à la fois fastidieux et propice aux erreurs. Tu décides de rendre la chose un peu plus intéressante en écrivant quelques fonctions pour compter et calculer les résultats de la classe.
Même si on peut accorder un « crédit partiel » sur les questions d'un examen, les notes globales de l'examen doivent être des ints.
Donc, avant de pouvoir faire quoi que ce soit d'autre avec les notes de la classe, il faut passer en revue toutes les notes et convertir les notes de type double en ints.
Crée la fonction round_down_scores() qui prend un vector de student_scores.
L'arrondi demandé par l'école est une troncature.
Heureusement pour toi, C++ peut convertir un type en un autre avec static_cast.
La conversion static_cast de double vers int supprime tous les chiffres après la virgule.
Cette fonction doit prendre le vector en entrée et return un nouveau vector dont toutes les notes sont converties en ints.
std::vector<double> student_scores {90.33, 40.5, 55.44, 70.05, 30.55, 25.45, 80.45, 95.3, 38.7, 40.3};
round_down_scores(student_scores)
// => {90, 40, 55, 70, 30, 25, 80, 95, 38, 40}
Il existe d'autres méthodes pour obtenir le même résultat, mais un cast est chose courante.
int new_PI{static_cast<int>(3.14) + static_cast<int>(0.001592653589)};
// new_PI is 3.
Pendant que tu corrigeais l'examen, tu as remarqué que certains élèves ne réussissaient pas aussi bien que tu l'espérais. Mais tu étais distrait, et tu as oublié de noter exactement combien d'élèves.
Crée la fonction count_failed_students() qui prend un vector de student_scores.
Cette fonction doit compter le nombre d'élèves qui n'ont pas la moyenne et renvoyer ce nombre sous forme d'entier.
Un élève doit obtenir une note supérieure à 40 pour réussir l'examen.
count_failed_students({90,40,55,70,30,25,80,95,38,40});
// => 5
L'enseignant que tu assistes aime attribuer des notes alphabétiques en plus des notes numériques. Comme les élèves obtiennent rarement 100 à un examen, les seuils inférieurs des « notes alphabétiques » sont calculés à partir de la meilleure note obtenue, et s'échelonnent régulièrement entre cette meilleure note et le seuil d'échec de <= 40.
Crée la fonction letter_grades() qui prend en paramètre la note la plus « haute » de l'examen, et renvoie un array (et non un vector) des seuils inférieurs pour chaque intervalle de note « à l'américaine » : ["D", "C", "B", "A"].
/*Where the highest score is 100, and failing is <= 40.
"F" <= 40
41 <= "D" <= 55
56 <= "C" <= 70
71 <= "B" <= 85
86 <= "A" <= 100
*/
letter_grades(100);
// => {41, 56, 71, 86}
/*Where the highest score is 88, and failing is <= 40.
"F" <= 40
41 <= "D" <= 52
53 <= "C" <= 64
65 <= "B" <= 76
77 <= "A" <= 88
*/
letter_grades(88);
// => {41, 53, 65, 77}
Tu as les notes d'examen par ordre décroissant, ainsi que les noms des élèves correspondants (triés dans l'ordre de leurs notes d'examen). Tu aimerais associer le nom de chaque élève à sa note d'examen et afficher un classement global de la classe.
Crée la fonction student_ranking() avec les paramètres student_scores et student_names.
Associe chaque nom d'élève du vector student_names à sa note du vector student_scores.
Tu peux supposer que chaque vector argument est trié du meilleur au moins bon.
La fonction doit renvoyer un vector de strings au format <rank>. <student name>: <student score>.
std::vector<int> student_scores {100, 99, 90, 84, 66, 53, 47};
std::vector<std::string> student_names {"Joci", "Sara","Kora","Jan","Indra","Bern", "Fred"};
student_ranking(student_scores, student_names)
// =>
// {"1. Joci: 100", "2. Sara: 99", "3. Kora: 90", "4. Jan: 84", "5. Indra: 66", "6. Bern: 53", "7. Fred: 47"}
Bien qu'une note « parfaite » de 100 soit rare à un examen, il est intéressant de savoir si au moins un élève l'a obtenue.
Crée la fonction perfect_score() avec les paramètres student_scores et student_names.
Les listes sont les mêmes qu'à la tâche 4.
La fonction doit return le premier <name> (sous forme de string) de l'élève qui a obtenu 100 à l'examen.
Si aucune note de 100 n'est trouvée, une string vide "" doit être renvoyée.
perfect_score({"Nur", "Tony", "Fatima"}, {90, 80, 100});
// => "Fatima"
perfect_score({"Nur", "Tony"}, {90, 80});
// => ""
Inscris-toi sur Exercism pour apprendre et maîtriser C++ avec 19 concepts100 exercices, et un vrai mentorat humain, le tout gratuitement.