La programmation en C++ moderne

Apprenez la programmation de zéro jusqu'à l'infini !

a marqué ce sujet comme résolu.

Reprise du dernier message de la page précédente

Je n’avais pas très bien lu. ce que j’aurais du dire c’est qu’on peut caster i ou utiliser std::to_string() et le concatener a prefix. Mais tu sembles dire qu’il y a un problème avec cette façon de faire.

Par contre pour formater finement comme dans l’exemple que tu viens de donner, un champ de 4 caractères commençant au pire par 0, je pourrais envisager que les string soit véritablement insuffisants.

Je tiens a préciser que je ne cherche en aucun cas a démontrer que tu as tort. En réalité, si je suis aussi transparent quant a mon désaccord avec ce que tu m’as expliqué c’est seulement pour que tu puisses mieux évaluer ce qui me bloque. Donc merci de pas te décourager. C’est vraiment important que je comprenne là. Sinon je vais passer la deuxième alors que je sais a peine démarrer.

Édité par mougnolribama

in medio stat virtus

+0 -0

https://en.cppreference.com/w/cpp/string/basic_string/to_string est récent, ça n’ouvre aucun contrôle sur le format, et c’est limité aux types scalaires. Et appelé de nombreuses fois, c’est moins efficace qu’un flux-chaine.

Les flux, ça fait plus.

Les strings, c’est notre objectif. C’est ce que l’on veut au final. On veut construire une chaine à partir d’informations qui ne sont pas des chaines. Peu importe l’objectif, même si le plus usuel consiste à fabriquer un nom de fichier (et c’est loin d’être le seul; c’est juste un des premiers que des débutants rencontrent). Le moyen, c’est les stringstream.

PS: on ne caste pas un entier en chaine. Ca n’a pas de sens. En revanche, on peut vouloir le représenter dans un format textuel selon une base de notre choix (généralement décimale).

+2 -0

J’ai voulu faire tourner le code que tu m’as donnee tout a l’heure en exemple avec DesGrosTrucs et j’ai une erreur que je ne comprend pas bien: Une "funcion deleted".

stringstream.cpp:38:23: error: use of deleted function ‘std::basic_ofstream<_CharT, _Traits>::basic_ofstream(const std::basic_ofstream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]’ if (!(f « v[i])) throw std::runtime_error("Cannot store truc in file "+filename);

Et mon code:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

using namespace std::literals;

class DesGrosTrucs {
    public:
    DesGrosTrucs ( std::string const & str_): str ( str_ ) {

    }
    std::string toStr() const {
        return str;
    }

    private:
    std::string str;
};

std::ofstream & ::operator<<( std::ofstream  flux, DesGrosTrucs const & grosTruc)
{
    flux << grosTruc.toStr();
    return flux;
}

void save(std::vector<DesGrosTrucs> const& v, std::string const& prefix)
{
    std::ostringstream oss;
    for( std::size_t i = 0; i != v.size(); ++i)
    {
        oss.str(""); // RAZ
        oss << prefix << i; // possibilité de jouer avec des formats avec une syntaxe dont je ne me souviens jamais
        auto const filename = oss.str();
        std::ofstream f(filename);
        if (!f) throw std::runtime_error("Cannot open file "+filename);
        if (!(f << v[i])) throw std::runtime_error("Cannot store truc in file "+filename);
    }
}

auto main () -> int {
    std::vector v1 { 
        DesGrosTrucs{ "gros un"s },
        DesGrosTrucs{ "gros deux"s },
        DesGrosTrucs{ "gros trois"s }
    };
    save( v1, "pref");
}

Édité par mougnolribama

in medio stat virtus

+0 -0

l.22. Copier un flux n’a aucun sens -> ils se passent par référence. Toujours.

NB: les messages d’erreurs sont toujours plus complet. En particulier ils sont contextualisés. Tu as à minima, j’en suis sûr, un truc genre "note: called from blabla ligne 22"

+0 -0

effectivement. Merci. :)

stringstream.cpp:22:15: note: candidate 2: std::ofstream operator«(std::ofstream, const DesGrosTrucs&) std::ofstream operator«( std::ofstream flux, DesGrosTrucs const & grosTruc)

stringstream.cpp: In function ‘void save(const std::vector<DesGrosTrucs>&, const string&)’: stringstream.cpp:38:23: error: use of deleted function ‘std::basic_ofstream<_CharT, _Traits>::basic_ofstream(const std::basic_ofstream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]’ if (!(f « v[i])) throw std::runtime_error("Cannot store truc in file "+filename);

In file included from stringstream.cpp:2:0: /usr/include/c++/7/fstream:723:7: note: declared here basic_ofstream(const basic_ofstream&) = delete;

stringstream.cpp:22:15: note: initializing argument 1 of ‘std::ofstream operator«(std::ofstream, const DesGrosTrucs&)’ std::ofstream operator«( std::ofstream flux, DesGrosTrucs const & grosTruc)

Makefile:2: recipe for target 'teststringstream' failed make: *** [teststringstream] Error 1

La note dont tu parles c’est plus tot celle avant ou apres l’erreur?

Édité par mougnolribama

in medio stat virtus

+0 -0

Merci @lmghs et @romantik. Après quelque essais avec les stringstream, Je fini par comprendre je crois.

Les strings, c’est notre objectif. C’est ce que l’on veut au final. On veut construire une chaine à partir d’informations qui ne sont pas des chaines. Peu importe l’objectif, même si le plus usuel consiste à fabriquer un nom de fichier (et c’est loin d’être le seul; c’est juste un des premiers que des débutants rencontrent). Le moyen, c’est les stringstream.

lmghs

Et c’est bête que je n’est pas su pour la conversion chaine a entier. Ca me paraissait couler de source pourtant. Merci beaucoup.

in medio stat virtus

+0 -0

Salut à tous,

Plus d’un mois et demi sans nouvelle, pas cool de notre part. Le tutoriel avance, pas aussi rapidement que je ne le souhaiterais, mais on a quand même une bonne nouvelle : je suis en train d’écrire le premier T.P de la partie POO. Dès que c’est fini, on va pouvoir l’envoyer en validation.

Le temps que celle-ci soit validée, ça nous laissera le temps de travailler sur la suite, notamment la sémantique d’entité, la move-semantic et d’autres notions encore.

J’en profite encore une fois pour remercier tous ceux qui nous aident, que ce soit par leurs questions, leurs suggestions, leurs corrections. Toute l’aide apportée est très précieuse et on apprécié beaucoup, même si on met parfois du temps à répondre et que les modifications ne sont pas immédiatement visibles en ligne.

Merci beaucoup à tous et à bientôt. :)

@informaticienzero

Édité par informaticienzero

Petite remarque suite a une discussion sur le discord NaN :

Sa signifie quoi ? "Je n’utilise le français que dans le cadre de votre apprentissage. Quand vous aurez pris un peu de bouteille, je vous encouragerai à utiliser l’anglais."

(source : https://zestedesavoir.com/tutoriels/822/la-programmation-en-c-moderne/le-debut-du-voyage/une-super-memoire/)

La personne a 18 ans et ne connaît pas cette expression avec les bouteilles. Pour faciliter la lecture du tuto (pour les jeunes et les non-français d’origine), il serait peut etre mieux de remplacer ce type d’expression par quelque chose de plus simple. Par exemple "Quand vous aurez plus d’expérience". Les expressions de langages sont parfois compréhensible que pour des cultures spécifiques.

Pour poser des questions ou simplement discuter informatique, vous pouvez rejoindre le discord NaN.

+4 -0

Je viens de donner des explications sur l’extension de duree de vie de temporaire sur le forum : https://zestedesavoir.com/forums/sujet/13417/question-sur-les-references

Je ne me souviens plus des explications données dans le cours, il faudra que je relise pour comparer.


Au fait, pour info, je pense refaire des lives sur le twitch de NaN pour faire du "co-working". Je pensais en particulier refaire une relecture du cours C++ en live, pour des corrections, des propositions d’explications, répondre aux questions, proposer des exos, des sources pour aller plus loin, etc. Je commencerais ca probablement en janvier ou février. (Mais ca sera aux horaires de la californie)

Pour poser des questions ou simplement discuter informatique, vous pouvez rejoindre le discord NaN.

+2 -0

Ça pourrait être une bonne idée !

mehdidou99

Ou pas.

Je suis déjà tombé dans ce piège, donc je vais me permettre un conseil. On passe son temps a avoir des idées de contenu à ajouter. "On pourrait ajouter ça. Et parler de ça. Et détailler ça. Etc.". Mais au final, on se retrouve avec un patchwork d’idées en vrac, sans cohérence pédagogique, assez indigeste pour le lecteur débutant.

Mon conseil : il faut aussi apprendre à supprimer et simplifier. Moins d’informations ne veut pas forcément dire moins bien. Il faut garder en tête le public cible.

Vous faites des résumés en fin de chapitre, c’est bien. Mais refaites de temps en temps des relectures de chapitre et comparez le contenu avec le résumé.

  • une idée est dans le résumé : ok
  • une explication permet de comprendre une idée qui est dans le résumé : ok
  • une explication ou une idée n’est pas dans le résumé : a-t-elle sa place dans le chapitre ?

Lors de ma prochaine relecture, j’essaierai de regarder la cohérence et la progression pédagogique.

Pour poser des questions ou simplement discuter informatique, vous pouvez rejoindre le discord NaN.

+1 -0

Bonjour, je suis le cours sur le c++, et depuis que j’ai commencé le chapitre sur les boucle, je galère pas mal, je rate les exos, mais au moins je les comprend, sauf celui ci, ça fait une demie heure que je cherche a comprendre mais je n’y arrive pas….

Je parle de l’exo ou l’ont doit créer un test de primalité, le résultat est celui ci :

bool est_premier { true };
for (int i { 2 }; i < nombre; ++i)
{
    if (nombre % i == 0)
    {
        // Si i divise nombre, alors nous savons que nombre n'est pas premier.
        est_premier = false;
        break;
    }
}

if (est_premier)
{
    std::cout << nombre << " est un nombre premier !" << std::endl;
}
else
{
    std::cout << nombre << " n'est pas premier." << std::endl;
}

return 0;

}

Ce que je ne comprend pas, c’est qu’en utilisant le programme " avec ma tête " juste en réfléchissant, ça marche uniquement avec 3… Je m’explique, on déclare une variable i à 2 déjà, je comprend pas pour quoi mettre 2, en suite ont dit que si i est inférieur a nombre alors on l’incrémente ( donc +1 ). Imaginons en nombre je souhaite mettre 7 qui est premier, i est inférieur a 7 donc je fais +1 donc i = 3 ?

Donc nombre % i = 7 % 3 = 1 ?? comment le programme renvoie 7 comme premier alors qu’on trouve 1 en modulo et non 0. Je sais très bien que c’est moi qui est mal compris quelque chose, une logique qui flanche, je sais pas, mais j’aimerai bien un peu d’aide svp ^^

+0 -0
Auteur du sujet

Salut !

Je vais t’aider à dérouler toute l’exécution du programme ; tu comprendras plus facilement. L’idée est la suivante :

  • On teste tous les diviseurs possibles de nombre, c’est-à-dire tous les entiers entre 2 et nombre.
  • Si l’un deux divise nombre, alorsnombre` n’est pas premier.
  • Sinon, nombre est premier.

Maintenant, pour comprendre plus précisément comment ça marche en pratique, déroulons l’exécution pour nombre = 7 par exemple. Déjà, un point important à noter, c’est que j’ai l’impression que tu n’as pas bien compris le fonctionnement de la boucle for : à chaque tour de boucle, on augmente i, et on ne s’arrête que lorsque le test i < nombre n’est plus vrai. En d’autres termes, i va prendre toutes les valeurs entre 2 et nombre - 1. A partir de ce constat, faisons un tableau décrivant la valeur des variables à chaque tour de boucle :

i nombre % i est_premier
2 1 true
3 1 true
4 3 true
5 2 true
6 1 true

Comme à chaque tour de boucle, nombre % i != 0, est_premier ne passe jamais à false. Donc à la fin, cela affiche bien « 7 est premier ».

Maintenant, que se passe-t-il avec un nombre non premier ? Essayons avec n = 9 :

i nombre % i est_premier
2 1 true
3 0 false

Comme 3 divise 9, au moment où on arrive à l’itération où i == 3, on va satisfaire la condition nombre % i == 0 et est_premier va donc passer à false ; de plus, l’instruction break fait sortir de la boucle ! On affiche alors bien « 9 n’est pas premier » !

Plus généralement, lorsque tu ne comprends pas comment fonctionne un morceau de code, si tu n’arrives pas à comprendre « de tête », prends un papier et un crayon et déroule l’exécution sur papier en gardant la trace des valeurs des variables. C’est beaucoup plus facile que de tout faire dans sa tête ! ;)

J’espère que c’est plus clair pour toi, n’hésite pas si tu as encore des questions ! :)

Édité par mehdidou99

Plus on apprend, et, euh… Plus on apprend. | Apprendre le C++ moderne

+2 -0

@mehdidou99

PARFAIT ! Effectivement je n’avais pas du tout bien compris comment fonctionnait "For", et c’est vrai que tout a l’heure, je me suis demandé si je devrai pas utiliser un papier plutôt que de me faire tout de tête et effectivement en testant la maintenant, ça m’a bien aidé !

Par contre, j’ai voulu refaire le tableau comme toi avec le 7, mais en faisant les modulo, je tombe pas tout le temps sur 1, notamment pour 7%4 et 7%5, même si oui effectivement il n’y a pas de 0, je pense que tout est limpide pour moi, j’espère que je serai plus efficace au prochain chapitre ^^

En tout cas merci pour ton temps accordé ! ;)

+0 -0
Auteur du sujet

Bonjour les agrumes !

La bêta a été mise à jour et décante sa pulpe à l’adresse suivante :

Au programme, on a pas mal avancé sur la sémantique d’entité et les handles ! @Ksass’Peuk, je serai curieux d’avoir ton avis sur cette nouvelle mouture. Je n’ai pas construit la progression exactement comme tu la décrivais, j’y réfléchis encore, mais du coup j’aimerais bien avoir un nouveau retour de tous les relecteurs, mais de toi en particulier. :)

Merci d’avance pour vos commentaires !

Édité par mehdidou99

Plus on apprend, et, euh… Plus on apprend. | Apprendre le C++ moderne

+2 -0
Auteur du sujet

Au passage, @informaticienzero et moi-même venons de recevoir des contrats d’édition pour ce livre, que nous allons signer incessamment sous peu : ce livre va exister en version papier, et c’est en partie grâce à vous, chers relecteurs ! C’est un vrai honneur pour nous, et je trouve que c’est une bonne occasion de vous remercier de votre précieuse aide, donc merci beaucoup, vraiment.

J’en profite pour préciser que cela ne change en rien le fait que le cours sera disponible gratuitement et librement sur Zeste de Savoir, notre contrat contient une clause spécialement dédiée à l’autorisation de publication sur ZdS ! :)

Édité par mehdidou99

Plus on apprend, et, euh… Plus on apprend. | Apprendre le C++ moderne

+27 -0

Bonjour, dans un premier temps, j’espère que je poste au bon endroit, je me demande si je ne dois pas créer un sujet uniquement me concernant ou j’y mettrai toute mes questions " bêtes " ou alors est ce qu’il n’existe pas un discord ?

Bref quoi qu’il en soit je suis au chapitre des tableaux, je suis au premier exo, et je commence a me rendre compte qu’un exo peut être "réussi" de différentes façons et j’imagine que plus on avancera et plus ce sera le cas, le soucis c’est que je ne sais pas si je dois éviter certaines pratiques, donc dois-je me faire confiance et faire confiance au résultat ou alors je dois suivre la solution à la lettre ?

Pour être franc, avant de voir la correction, je n’avais pas mis la partie qui protège l’entrée, cependant le reste fonctionne et me semble pas si mal…

Je vous mets donc ce que j’ai mis a l’exercice "Calcul de moyenne" :

std::cout << "Bienvenue dans notre logiciel de calcul de moyenne !" << std::endl;
std::cout << "Rentre tes notes et dès que tu as fini rentre un chiffre négatif pour passer a la suite." << std::endl;
double note{};
double total{};
double moyenne{};
std::vector<double> tableauNote{};


while (note >= 0)
{
    tableauNote.push_back(note);
    total += note;
    std::cin >> note;

    while (!(std::cin >> note))
    {
        std::cout << "Entrée invalide. Recommence." << std::endl;
        std::cin.clear();
        std::cin.ignore(255, '\n');
    }
}

tableauNote.pop_back();
moyenne = total / std::size(tableauNote);
std::cout << "Ta moyenne est de " << moyenne << std::endl;

EDIT : en passant a la suite je vois qu’effectivement que je n’ai pas non plus pensé a ce qu’il mette directement une note négative

Édité par jusdebaobab

+0 -0

Salut,
Tu devrais effectivement créer ton propre sujet pour chaque problème que tu rencontres ou questions que tu te poses, afin de laisser celui-ci libre pour les retours sur le cours. Si dans ton sujet les questions ou problèmes sont manifestement liés à un défaut du cours, il sera alors pertinent de venir le signaler ici.

Pour les pratiques essaie de découpler les fonctionnalités de ton programme, ici tu as la saisie utilisateur + le calcul de la moyenne + le retour à l’utilisateur, de la manière dont tu t’y es pris le total est calculé pendant la saisie, et donc le jour où tu veux faire évolué les entrées de ce programme ça va affecter ton calcul de moyenne. Déclare tes variables au plus proche de leurs utilisations (et limite donc leurs visibilités au minimal)

Ta solution est "fausse", car le tableau notes ne contient pas les notes entrés par l’utilisateur, tu y as ajouté un zéro au début (avant la première saisie utilisateur) et retire la dernière valeur saisie par l’utilisateur (pour que size te donne la valeur que tu cherches je suppose). ça fonctionne car un 0 n’influe pas sur le total, que tu calcul d’ailleurs au fil des saisie et pas au contenu du tableau notes. Le tableau ne te sert alors que pour sa taille et pourrait-être remplacé par un compteur du nombre de saisie incrémenté dans la boucle. Mais le but de l’exercice est de manipuler les tableaux, le calcul de moyenne doit être une fonction qui a pour entrée le tableau de note, la saisie utilisateur n’est la que pour pouvoir la tester, tu pourrais aussi bien travailler sur un tableau initialisé avec des valeurs en dur dans le code.

jadis @leroivi - all in all we’re just another brick in the wall

+3 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte