Voila
Ca doit forcement etre con. Mais j’ai vu ce qu’etais les exception maintenant. Pourquoi pop_back()
ne jetterais pas une exception quand il opere
sur une chaine ou un tableau vide? C’est pareil pour les acces en dehors du tableau. Pourquoi partout des UB? J’ai meme verifier j’avais du mal a y croire
Pour renvoier une valeur…
c’est "renvoyer" je penses ici.
Certains reprochent son côté « rigide » à ce mot-clé. En effet, auto seul dégage la référence.
À l’inverse, auto & sera toujours une référence. Et il en est de même pour const : auto const
sera toujours constant et auto const & sera toujours une référence sur un objet constant.
ça doit certainement venir de moi mes "dégage" ici me parait un peu obscur. C’est très bien explique
ensuite et exemple a l’appui en plus, mais quand je fais la relecture pour la 3 eme fois et que j’arrive toujours a
penser dans un premier temps que quelque chose comme 'auto var { refint }' signifie var
est une int reference
ici (en résumé) ça me semble limpide
Le mot-clef auto ne conserve pas les références, mais le nouveau mot-clef que nous avons
introduit, decltype
, si.
Il manque le cas terminal pour l’algorithme est_impair
. J’ai l’impression que c’est fait expres.
ca me fait penser a ce que tu avais fait de std::cin.ignore( )
et std::numeric_limits<std::streamsize>::max()
en hardcodant d’abord la valeur max a 255.
14.2.1. Contrats assurés par le compilateur
15.Le typage
Il manque du texte entre les deux. Enfin c’est ce que j’ai d’abord cru. C’est le pdf qui est genere qui a comme un bug sur la numerotation des titres. J’imagine que je suis un peu hors sujet.
Rappelez-vous, nous avons défini les postconditions comme étant les contrats que doit respecter
une fonction si ses préconditions le sont. Nous pouvons, grâce aux tests unitaires, vérifier que la
fonction fait bien son travail en lui fournissant des paramètres corrects et en vérifiant que les
résultats sont valides et correspondent à ce qui est attendu.
Est ce que les tests qu’on a effectues juste avant cette remarque verifient des posconditions ( c’est l’impression que j’ai ).
void test_push_back_taille_augmentee ( ) {
std::vector<int> tableau { 1, 2, 3 }
assert ( std::size ( tableau ) == 3 && "La taille doit être de 3 avant l'insertion." )
tableau.push_back ( -78 )
assert ( std::size ( tableau ) == 4 && "La taille doit être de 4 après l'insertion." )
}
void test_push_back_element_bonne_position ( ) {
std::vector<int> tableau { 1, 2, 3, 4 }
int const element { 1 }
tableau.push_back ( element )
assert ( tableau [ std::size ( tableau ) - 1 ] == element && "Le dernier élément doit être 1." )
}
Le cas echeant, ce serait bien que ce soit souligne ici je crois. On pourrait
avoir par exemple:
void test_push_back_element_bonne_position ( ) {
std::vector<int> tableau { 1, 2, 3, 4 };
int const element { 1 };
tableau.push_back ( element );
assert ( tableau [ std::size ( tableau ) - 1 ] == element && "Le dernier élément doit être 1." );
}
Mais je comprendrais si on me répondait que vu le chemin parcouru jusqu’ici on
ne va plus autant se faire tenir par la main que durant le premier chapitre
Indice
N’oubliez pas que s’il y a fermeture de flux, il faudra lancer une exception puisque la
lambda sera incapable de vérifier la postcondition « affecter une valeur correcte fournie
par le flux à la variable ».
La lambda!?? Comme dans III-16. Des fonctions somme toute lambdas?
###Contenu masqué n°37 : Correction
#include <iostream>
#include <limits>
int main()
{
std::cout << "Quel jour es-tu né ? ";
int jour { 0 };
while (!(std::cin >> jour) || jour < 1 || jour > 31)
{
if (std::cin.eof())
{
exception.
throw std::runtime_error("Le flux a été fermé !");
C’est pas juste un contenue masqué. C’est la correction du TP Partie V.
std::for_each(std::begin(chaines), std::end(chaines),
[](std::string const & message) -> void
{
std::cout << "Message reçu : " << message << std::endl;
});
L’exemple précédent montre une lambda qui ne prend qu’un paramètre. En
effet,std::for_each
attend un prédicat unaire, c’est-à-dire que l’algorithme travaille sur un seul
élément à la fois. La lambda ne prend donc qu’un seul paramètre.
La lambda renvoie void
.
Un prédicat est une expression qui prend, ou non, des arguments et renvoie un booléen.
Par contre std::sort
attend bien un predicat binaire mais cette lambda assure
renvoyer un double
std::sort(std::begin(tableau), std::end(tableau),
[](double a, double b) -> double
{
return a > b;
})
int const diviseur { 2 }
int const diviseur { 2 }
int somme { 0 }
// Il n'y a aucun problème à mélanger les captures par valeur
et par référence.
std::for_each(std::cbegin(nombres), std::cend(nombres),
[diviseur, &somme](int element) -> void
{
if (element % diviseur == 0)
{
somme += element;
}
On dirait que les lambda ont été conçues exprès pour encourager a ne pas accéder
a l’environnement externe. Pourquoi fait-on ça aussi souvent?
On peut faire encore mieux : on se fiche du type réel du conteneur, du moment qu’il est
itérable. Essayons d’appliquer ce principe et d’écrire une fonction afficher qui marche avec
n’importe quel type de conteneur itérable.
… et dont chaque element e
est affichable.
template <typename Collection>
void afficher(Collection const & iterable)
{
for (auto const & e : iterable)
{
std::cout << e << std::endl;
}
}
la e
est toujours passé par référence. c’est contre la culture C++ qui consiste a passer toujours les
types primitifs par valeur mais j’imagine que la culture n’est rien face au gain et qu’un trop d’opti vaut
mieux que pas du tout.
void afficher(std::vector<int> const & iterable)
{
for (auto const & e : iterable)
{
std::cout << e << std::endl;
}
}
Des structures de données.
En fait, on a vu et utilisé un nombre incalculable de fonctions génériques dans la
bibliothèque standard : celles renvoyant des itérateurs ( std::begin , std::end , etc), les
conteneurs, les algorithmes, etc.
Est ce que les conteneurs sont des fonctions aussi? ou alors tu parles de
fonctions dans le sens de fonctionnalités.
Les tableaux, en informatique, font partie de la grande famille des structures de données
. Ces structures de données sont des façons particulières d’organiser et de stocker des
données. Il y a ainsi des structures pour stocker un nombre fixe de données du même type,
d’autres pour un nombre variable, d’autre encore pour stocker des données de types différents.
Ces objets, conçus spécialement pour stocker des données, sont appelés conteneurs.
###Contenu masqué n°42 : Correction T.P partie VIII
Il n’y pas de prédicat(je veux dire que je n’en vois pas dans l’entete template). Les lignes …
else
{
std::cout << "Le prédicat n'est pas respecté !" << '\n');
std::endl;
}
et aussi …
template<typename T>
void entree_securisee(T& variable)
{
+>....
else
{
std::cout << "Le prédicat n'est pas respecté !" << '\n');
std::endl;
}
}
}
sont en trop dans la fonction.
std::tuple tuple1 { 2, "bool"s, "sup"s, "Numeric"s };
auto tuple2 = std::make_tuple ( 2, "bool"s, "sup"s, "Numeric"s );
Du coup std::make_tuple
c’est un cadavre? Moi ca m’a l’air de faire doublon en plus d’etre moins confortable.C’est le truc avec l’inference des types template; pour moi ca suicide tous les helpers. Je soupconne que je sois certainement un peu naif.
if (std::get<1>(coordonnees) < 0)
{
// On ne continue plus la simulation dès que y est au
niveau du sol.
break;
}
Sans vouloir en faire un cour de physique, en considérant bien sur que le lancement se fasse depuis le sol.
On pourrait preciser dans l’ennonce.
Vous voulez un exemple concret d’utilisation des std::tuple
? Vous aimez la physique ? Vous
allez être servi. Nous allons coder une fonction retournant les coordonnées (x; y) d’un objet
lancé à une vitesse v 0 et à un angle α, en fonction du temps t.
… d’un objet lancé depuis le sol à une vitesse v 0 et à un angle α, en fonction du temps t.
On s’en sert typiquement pour limiter le champs des possibilités pour un type. Ainsi, au
lieu de stocker le jour de la semaine sous forme de std::string
, ce qui n’offre pas de protection
si l’utilisateur rentre n’importe quoi, on va utiliser une énumération. Ainsi, celui-ci n’a pas
d’autres choix que d’utiliser une des valeurs que nous avons nous-mêmes définis. C’est beaucoup
plus souple que de devoir faire plein de vérifications sur une chaîne de
caractères.
J' ai plutôt l’impression que c’est le programmeur qui est contraint par ses
valeurs limites. Tu dis un peu ça ensuite je pense. Si je trompe veillez toujours a me remettre sur le droit chemin
Grâce aux tuples et aux structures, nous sommes en mesure de retourner plusieurs
variables d’un coup.
Plusieurs variables de type differents types! Ici(Distributeur d’argent) on avait retourne un vecteur
std::string enregistrer_infos(std::string const & nom, std::string
const & prenom, std::string const & sexe, int age)
{
std::string nom_fichier { prenom + "." + nom + ".csv" };
std::ofstream fichier { nom_fichier };
fichier << nom << ',' << prenom << ',' << sexe << ',' << age;
return nom_fichier;
}
Tu utilises la concaténation que tu n’as pas encore expliqué à ce stade du
cours.
Un autre avantage, c’est de pouvoir réutiliser une même variable plusieurs fois, alors que la
décomposition C++17 ne nous le permet pas.
Je ne comprends pas bien j’ai essaye d’utiliser une variable de strutured binding
plusieurs fois ça a marché.
Et puis pour moi le comité est parfois lent un peu. On aurait pu facilement faire (moi ça me saute aux yeux):
[ nom, void, age ] = std::tuple { "kill", "Bill", 24 };
[ nom, _, age ] = std::tuple { "kill", "Bill", 24 };
et puis comme ça on bute std::tie
et std::ignore
. Tranquille.
C’est en découvrant que les opérateurs de flux étaient binaires et qu’il ne font que faire
"une donnée D sur un flux F égal un flux F" (en modifiant le flux F et certainement 2,
3 trucs en interne mais j’imagine qu’on s’en fout ) que j’ai compris pourquoi cette notation était possible.
std::getline(fichier >> std::ws, phrase);
Avant ça j’avais un peu l’impression (je savais que c’était pas possible hein) que c’était une construction particulière que le langage autorisait.
Si j’avais sérieusement considéré que c’était juste une écriture particulière et non un assemblage cohérent de brique logique préexistante (soit déjà vu dans le cours, soit un peu obscur) je me serais découragé.
Voila juste pour faire part de ce qu’il y a parfois des moments ou j’étais un peu beaucoup inquiet pendant mon évolution sur ce cours.
C’est vrai qu’on nous dit de relire pour bien assimiler mais c’est vrai aussi que
parfois juste avancé et découvrir le "plus" permet d’arriver a comprendre le
"moins".
Fraction const un_demi { 1, 2 };
Fraction const trois_quarts { 3, 4 };
Fraction const deux_huitièmes { 2, 8 };
Fraction const resultat { un_demi + trois_quarts - deux_huitièmes };
std::cout << "1/2 + 3/4 - 2/8 font " << resultat.numerateur << "/" << resultat.denominateur << std::endl;
On peut faire encore mieux non?
using f = Fraction;
Fraction const resultat { f{1,2} + f{3,4} - f{2,8} };
std::cout << "1/2 + 3/4 - 2/8 font " << resultat.numerateur << "/" << resultat.denominateur << std::endl;
Avec le support de operator<<
using f = Fraction;
std::cout << "1/2 + 3/4 - 2/8 font " << f{1,2} + f{3,4} - f{2,8} << std::endl;
Mais je comprends que faire tout en même temps ça puisse un peu embrouiller
bool operator==(Fractionconst& a, Fractionconst& b)
{
Fractionconstgauche { a.numerateur* b.denominateur,a.denominateur* b.denominateur };
Fractionconstdroite { b.numerateur* a.denominateur,b.denominateur* a.denominateur };
return gauche.numerateur== droite.numerateur && gauche.denominateur== droite.denominateur;
}
On peut difficilement faire plus verbeux. La encore je me trompe peut-être. J’ai personne a cote de moi
pour vérifier si je dis une connerie ou ne serait-ce qu’en discuter.
Mieux(plus cour et plus lisible):
bool operator==(Fractionconst& a, Fractionconst& b)
{
return { b.numerateur* a.denominateur == a.numerateur * b.denominateur };
}
Il faudrait peut être aussi expliqué pourquoi la solution naïve qui
consisterait a évaluer l’égalité des division des deux membres est trop
fragile. Je pense en particulier a la représentation des nombres en mémoire
et aussi au nombre irrationnels. Et si je dis une bêtise une fois de plus, soyez attentif a me corriger.