IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Correction de mes exercices en C++ moderne


Sujet :

C++

  1. #41
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Citation Envoyé par toto81 Voir le message
    Pourrais-tu me dire ce qu'il ne va pas dans ce code?
    C'est simple: ce code n'est pas du C++.

    Ce n'est même pas du C standard. Sûr qu'à l'époque, strcpy_s n'était pas normalisé.

    Je ne connais pas le nom du bouquin, mais tu peux déjà le mettre au fond de ton étagère.

    (Sinon, le code "fonctionne".)

  2. #42
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Aussi, le nom de la fonction est mauvais: La sortie est peut-être les N premiers nombres naturels, mais ce n'est certainement pas des nombres premiers.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #43
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    #include "stdafx.h"
    #include <iostream>
    #include <string>

    int main()
    {
    char prenom[] = "Jojo";
    char initiales[] = "J";
    char nom[] = "Lapatate";
    char nomcomplet[50];
    int offset = 0;

    strcpy_s(nomcomplet, prenom);
    offset = strlen(prenom);
    strcpy_s(nomcomplet + offset, " ");
    offset++;
    strcpy_s(nomcomplet + offset, initiales);
    offset += strlen(initiales);
    strcpy_s(nomcomplet + offset, ". ");
    offset += 2;
    strcpy_s(nomcomplet + offset, nom);
    std::cout << "Vous vous appelez: " << nomcomplet << std::endl;

    return 0;
    }
    C'est typiquement le genre d'exemples qui 1) sont plus du C que du C++ et 2) qui donnent l'impression qu'on ne peut rien faire en C++ en moins de deux-cents lignes de code. En C++ moderne on écrirait:

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include <iostream>
    #include <string>
     
    int main() {
        std::string prenom("Jojo"), initiale("J"), nom("Lapatate");
        auto nom_complet = prenom + " " + initiale +  ". " + nom;
        std::cout << "Votre nom est: " << nom_complet << std::endl;
    }

    Pour un tâche où la performance importe peu, il faut choisir le code le plus clair et le plus court.

    Fais-moi signe quand tu veux passer à une autre leçon et d'autres exercices (de C++ vraiment moderne)

  4. #44
    Membre du Club Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Points : 52
    Points
    52
    Par défaut
    Pfff... Le pire c'est que j'avais à peu près ca en tête pour faire l'exo à la différence de "string" plutôt que "auto" dans la déclaration de la variable "nomcomplet"

    J'me disais bien que c'était un code bien trop complexe pour un effet tout bête. Le livre que j'ai suivi c'est: http://cpp.developpez.com/livres/ind...us#L2744025461 .....en édition mise à jour pour le c++11.

    Apparemment, les Français sont pas très bon pour faire des bouquin sur le C++ :/

    Stend, je suis actuellement en train de bucher sur la suite des exos que tu m'a déjà donné ! Attendons que je finisse ceux là ^^

  5. #45
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Ok tu me diras pour les exos, comme j'ai un peu de temps aujourd'hui je t'écris la leçon 2 de Stendhal's modern C++, le tutoriel en français qui ne pense pas qu'apprendre le C++ c'est jouer avec des bits et des pointeurs sans recourir aux bibliothèques standard!

    Je ne fais qu'un exposé rapide. S'il y des choses que tu ne comprends pas, ce n'est pas grave! N'hésite pas à poser des questions. Les exercices viendront un peu plus tard quand tu auras terminé ceux de la leçon précédente (ou si tu en as marre). On pourra revenir plus en profondeur sur des points si tu veux.

    Big leçon n°2: Itérateurs, voitures et fonctions lambda

    Comme tu l'as justement remarqué dans le code:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    auto nom_complet = prenom + " " + initiale +  ". " + nom;
    on peut utiliser auto pour demander au compilateur de déduire le type de la variable qu'on déclare. C'est vrai depuis C++11 (donc depuis 2011).
    En l'occurrence, le compilateur sait que l'opérateur + dont une opérande est: std::string et l'autre: const char* retourne une std::string.
    Utiliser auto est recommandé pour trois raisons:
    1. cela évite de taper des types particulièrement compliqués, comme std::unordered_map<std::maxint_t, std::vector<std::pair<std::fast_uint16_t, std::shared_ptr<my_own_hash_map_type>>>>::iterator
    2. si on modifie le type à un endroit, le compilateur infère le type modifié partout ailleurs. Par exemple, si je change le type de nom et prenom pour en faire une std::wstring, le type de nom_complet est modifié aussi, par le compilateur. Je ne risque pas d'oublier de le faire avec peut-être une conversion inopportune ou une erreur de compilation à la clé
    3. il arrive qu'on ne connaisse pas le type de la variable qu'on déclare. C'est le cas pour les fonctions lambda: il n'y a pas deux lambdas du même type, un type spécifique est créé chaque fois par le compilateur. Mais qu'est-ce qu'une fonction lambda?



    Les fonctions lambda

    Tu sais ce que c'est qu'une fonction. Prenons un exemple:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    auto fois_deux(int i) { // auto peut aussi inférer le type de retour d'une fonction, à certaines conditions
      return i*2;
    }
    Que peut-on faire de cette fonction? C'est assez limité: elle doit être déclarée dans l'espace global (pas à l'intérieur d'une autre fonction, par exemple), ce qui veut dire qu'elle ne peut pas non plus être générée par une autre fonction. On peut essentiellement l'appeler et prendre son adresse.
    - l'appeler:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    auto deux_x = fois_deux(x);
    - prendre son adresse:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    auto fp = fois_deux;
    auto deux_x = fp(x); // on l'appelle via le pointeur sur son adresse

    Une fonction lambda c'est une fonction qui peut être utilisée comme une variable ordinaire. Voici un exemple, à méditer un bon moment parce-que, mine de rien, ça retourne un peu le cerveau:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    auto fois_x(int x) { // une fonction qui retourne une fonction lambda
        return [=](int y) { return y*x; }; // c'est la fonction lambda. Elle n'a pas de nom
    }
     
    int main() {
        auto fois_10 = fois_x(10); // fn contient une fonction lambda créée par fois_x(10), qui multiplie par 10 son argument
        std::cout << fois_10(5); // affiche 5*10 = 50
    }

    Un petit mot sur la syntaxe des fonctions lambda:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    [=] // entre crochet ce qu'il faut faire du contexte: = pour en faire une copie, & pour prendre en référence et pouvoir le modifier
    (int x) // l'argument de la lambda, il peut y en avoir plusieurs. Il peut même être déduit dans certains cas
    { return y*x; } // le corps de la fonction.

    Les fonctions lambda sont extrêmement utiles pour tirer parti de la bibliothèque standard. Pour cela, il faut connaître également les itérateurs. Mais que sont les itérateurs?

    Les itérateurs
    Un itérateur est une abstraction. Elle permet de parcourir des choses très dissemblables, comme un vecteur, une liste, un dictionnaire, un fichier... comme s'ils étaient semblables. Par exemple:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #include <iostream>
    #include <string>
    #include <vector>
    #include <set>
    #include <list>
     
    int main() {
        std::string str = "abcdef";
        std::vector<int> vec = {1,2,3,4,5};
        std::list<double> lst = {6., 7., 8., 9.};
        std::set<char> ensemble = { 'g', 'h', 'i'};
     
        for (auto it = std::begin(str); it != std::end(str); ++it) { // it est un itérateur
            std::cout << *it << ' ';
        }
        for (auto it = std::begin(vec); it != std::end(vec); ++it) { // la boucle est identique
            std::cout << *it << ' ';
        }
        for (auto it = std::begin(lst); it != std::end(lst); ++it) { // idem
            std::cout << *it << ' ';
        }
        for (auto it = std::begin(ensemble); it != std::end(ensemble); ++it) { // idem
            std::cout << *it << ' ';
        }  
    }

    Un itérateur pointe sur un élément d'une séquence. Pour connaître l'élément pointé, on utilise l'opérateur * . Par exemple, std::cout << *iterateur;Pour avancer d'un élément, on utilise l'opérateur ++. Par exemple: ++iterateurLes fonctions std::begin et std::end renvoie un itérateur respectivement sur le début et la fin d'une séquence.

    Pour reprendre l'exercice 4 du précédent épisode, tu aurais pu écrire:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void print_vec(const std::vector<int>& vec) {
        auto it = std::begin(vec);
        std::cout << '{' << *it++;
        for ( ; it != std::end(vec); ++it) {
            std::cout << ", " << *it;
        }
        std::cout << '}';
    }

    NB: l'opérateur ++ peut se placer avant ou après son opérande. Quand il est placé avant, il incrémente son opérande et la renvoie incrémentée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    auto x = 0;
    std::cout << ++x << " -> " << x; // 1 -> 1
    Quand il est placé après, il copie son opérande, l'incrémente et renvoie la copie non-incrémentée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    auto x = 0;
    std::cout << x++ << " -> " << x; // 0 -> 1

    Itérateurs et fonctions lambda

    Itérateurs et fonctions lambda permettent de tirer partie de la bibliothèque standard. En particulier des algorithmes qu'elle définit. C'est un des points-clé du C++ moderne de bien utiliser ces algorithmes. Ils sont dans l'en-tête <algorithm>. Prenons en exemple un des plus souvent utiles: std::sort:
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::vector<int> v = {9,3,7,3,1};
    std::sort(std::begin(v), std::end(v));
    print_vec(v); // {1, 3, 3, 7, 9}
    std::sort peut prendre un troisième argument pour préciser comment on compare deux éléments. Par défaut, on prend le plus petit élément. Mais on pourrait vouloir trier dans l'ordre inverse. Il faut alors fournir un autre critère de comparaison. On peut utiliser une fonction, un foncteur (on verra plus tard) ou une fonction lambda. L'avantage de la fonction lambda c'est qu'on peut la définir à l'endroit où on l'utilise et qu'on a pas besoin de lui donner un nom:
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::vector<int> v = {9,3,7,3,1};
    std::sort(std::begin(v), std::end(v), [](int a, int b) { return a > b; });
    print_vec(v); // {9, 7, 3, 3, 1}

    C'est tout pour aujourd'hui!!
    N'hésite pas à poser des questions.

  6. #46
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Citation Envoyé par stendhal666 Voir le message
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::vector<int> v = {9,3,7,3,1};
    std::sort(std::begin(v), std::end(v), [=](int a, int b) { return a >= b; });
    print_vec(v); // {9, 7, 3, 3, 1}
    Je n'ai rien lu de la conversion ni du message mais dans la lambda passée à std::sort :
    • Pas besoin de capture donc autant mettre [] et non [=] (coding style)
    • Le 3ème argument passé doit respecter le concept de comparateur établissant un ordre total strict ce que ne fais pas pas >=.
      (Si a == b, a >= b et b >= a renvoie true)
      Il faut donc utiliser > au lieu de >=.

  7. #47
    Membre du Club Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Points : 52
    Points
    52
    Par défaut
    C'est vraiment un super geste que tu me fais là! Merci Stend, bien que c'est pas facile à faire rentrer dans le cerveau, j'ai de quoi bucher!

    J'ai des questions mais on verra après les premiers exos car sinon je vais trop m'embrouiller...

    Voici mon programme pour le crible d’Ératosthène:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    #include "stdafx.h"
    #include <iostream>
    #include <vector>
    #include <string>
    #include <random>
     
    std::vector<bool> nombresPremiers(int choix) //Fonction appelé dans le main par la création du tableau "tabPremiers" qui permet de differencier les nombres premiers
    {
    	std::vector<bool> tab(choix);
    	tab[0] = false;
    	tab[1] = false;
    	tab[2] = true;
     
    	for (int x = 3; x < tab.size(); x++)
    	{
    		tab[x] = true;
    	}
     
    	for (int a = 2; a < tab.size(); a++)
    	{
    		if (tab[a] == true)
    		{
    			for (int b = a*2; b < tab.size(); b += a)
    			{
    				tab[b] = false;
    			}
    		}
    	}
     
    	return tab;
    }
     
    int nombreAleatoire(int choix) //Fonction appelé dans le main pour obtenir un nombre aléatoire par rapport à la taille du tableau
    {
    	std::random_device a;
    	std::default_random_engine b(a());
    	std::uniform_int_distribution<int> uniform_dist(2, choix);
    	int nombre = uniform_dist(b);
     
    	return nombre;
    }
     
    void reponseProg(std::vector<bool> tab,std::string choix,int nombreTab) //Fonction qui donne une réponse au joueur par rapport a son choix
    {
    	if (choix == "o" || choix == "O")
    	{
    		if (tab[nombreTab] == 1)
    		{
    			std::cout << "Bravo! " << nombreTab << " est bien un nombre premier :)" << std::endl << std::endl;
    		}
    		else if (tab[nombreTab] == 0)
    		{
    			std::cout << "Aie, desole! " << nombreTab << " n'est pas un nombre premier :'(" << std::endl << std::endl;
    		}
    	}
    	else if (choix == "n" || choix == "N")
    	{
    		if (tab[nombreTab] == 1)
    		{
    			std::cout << "Aie, desole! " << nombreTab << " est bien un nombre premier :'(" << std::endl << std::endl;
    		}
    		else if (tab[nombreTab] == 0)
    		{
    			std::cout << "Bravo! " << nombreTab << " n'est pas un nombre premier :)" << std::endl << std::endl;
    		}
    	}
    }
     
    int main()
    {
    	std::vector<bool> tabPremiers(nombresPremiers(256));
    	bool recommencer(true);
     
    	std::cout << "Bienvenue dans le jeu du crible d'Eratosthene!\n\nLa regle est simple, je vous donne si un nombre et";
    	std::cout << " vous me dites si c'est un\nnombre premier ou pas. Repondez simplement par O pour oui ou par N pour non.\n\nC'est parti!" << std::endl << std::endl;
     
    	do
    	{
    		int nombreTableau;
    		std::string choixQuestion, choixRecommencer;
    		nombreTableau = nombreAleatoire(255); //Appel de la fonction nombreAleatoire pour obtenir un nombre entre 0 et 255
     
    		std::cout << "Le nombre " << nombreTableau << " est-il un nombre premier?" << std::endl;
    		std::cin >> choixQuestion; //L'utilisateur répond à la question
    		std::cout << std::endl;
     
    		reponseProg(tabPremiers, choixQuestion, nombreTableau); //Appel la fonction reponseProg pour donne rune réponse à l'utilisateur par rapport à son choix
     
    		std::cout << "Voulez vous recommencer une partie? o/n" << std::endl;
    		std::cin >> choixRecommencer;
     
    		if (choixRecommencer == "n" || choixRecommencer == "N") //Si l'utilisateur répond "n", la partie s'arrête
    		{
    			recommencer = false;
    		}
    	} while (recommencer);
     
        return 0;
    }
    Il fonctionne bien, maintenant à voir si j'ai pas fait d'erreur ou mal compris la consigne!

    J'ai piqué la fonction random sur cppreference car j'ai vu que ce que j'utilisais avant était obsolète (rand de <cstdlib>) et j'avoue avoir recopié bêtement car je ne l'ai pas très bien comprise :/

  8. #48
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Citation Envoyé par Ehonn Voir le message
    Je n'ai rien lu de la conversion ni du message mais dans la lambda passée à std::sort :
    • Pas besoin de capture donc autant mettre [] et non [=] (coding style)
    • Le 3ème argument passé doit respecter le concept de comparateur établissant un ordre total strict ce que ne fais pas pas >=.
      (Si a == b, a >= b et b >= a renvoie true)
      Il faut donc utiliser > au lieu de >=.
    Bien vu, merci! Je modifie en conséquence

  9. #49
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Voici mon programme pour le crible d’Ératosthène:
    Très bien! J'ai compilé et testé, il marche "au poil".

    Pour la correction, je pense que tu auras des remarques des uns et des autres. Je te donne une solution qui n'est pas meilleure que la tienne pour le crible lui-même. J'ai choisi de ne traiter que les cas où n > 2 car 0 et 1 ne sont pas premiers, tout le monde le sait, mais avec le recul je pense que ta sémantique est plus consistante et évite des complications.
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    std::vector<bool> erathostene(unsigned n) { // un nombre premier est positif, donc j'utilise un entier non-signé, unsigned
        if (n < 2) return std::vector<bool>();
        auto zn = n-2; // on décale de deux rangs à gauche: 0 == 2
        std::vector<bool> crible(zn+1, true); // le constructeur à deux arguments: taille et valeur par défaut. Tous les éléments sont true
        for (unsigned i = 0; i < zn/2+1 ; ++i) { // zn/2 est le dernier à pouvoir être doublé en restant < zn
            if (crible[i] == true) {
                for (unsigned j = 2*i+2; j < zn+1; j += (i+2)) {
                    crible[j] = false;
                }
            }
        }
        return crible;
    }

    Pour l'aspect aléatoire:
    J'ai piqué la fonction random sur cppreference car j'ai vu que ce que j'utilisais avant était obsolète (rand de <cstdlib>) et j'avoue avoir recopié bêtement car je ne l'ai pas très bien comprise :/
    Très bien!! c'est comme ça qu'on apprend! Et en recopiant la référence tu as peu de chances de te tromper

    Pour l'interface utilisateur, quelques remarques:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void reponseProg(std::vector<bool> tab,std::string choix,int nombreTab)
    La signature de ta fonction implique que tu copies les arguments. Lorsque l'argument n'est pas d'un type primitif (int, bool, char, etc.), il peut être de taile importante et long à copier. On utilise alors une référence. Si on ne compte pas modifier l'argument, on utilise une référence constante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void reponseProg(const std::vector<bool>& tab, const std::string& choix,int nombreTab)
    A retenir:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void f(std::string s); // réalise une copie de la string passée en argument
    void f(std::string& s); // référence sur la string qui pourra être modifiée par la fonction
    void f(const std::string& s); // référence sur la string qui ne pourra pas être modifiée. S'écrit aussi (std::string const&)
    Autres remarques:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (tab[nombreTab] == 1)
    Préférer:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (tab[nombreTab] == true) // ou if (tab[nombreTab])
    // et de la même façon
    if (tab[nombreTab] == false) // ou if (!tab[nombreTab])
    Cela indique plus clairement qu'on a affaire à un bool

    Sur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int nombreTableau;
    std::string choixQuestion, choixRecommencer;
    nombreTableau = nombreAleatoire(255);
    La bonne pratique est d'initialiser immédiatement les variables (surtout celles de type primitif qui n'ont pas de valeur par défaut). D'où:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    auto nombreTableau = nombreAleatoire(255);
    Quand tu commenceras à utiliser des exceptions, tu verras que ça peut éviter des gros bugs bien m...iques.

    Et maintenant que tu t'y connais en auto:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<bool> tabPremiers(nombresPremiers(256)); // pourquoi pas auto tabPremiers = nombresPremiers(256); ?
    Bon il est un peu tard...
    Bon courage et bravo, reste à persévérer!

  10. #50
    Membre du Club Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Points : 52
    Points
    52
    Par défaut
    J'ai modifié mon code avec tes recommandations et en effet c'est plus rapide et plus simple à lire!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    #include "stdafx.h"
    #include <iostream>
    #include <vector>
    #include <string>
    #include <random>
     
    std::vector<bool> nombresPremiers(int choix) //Fonction appelé dans le main par la création du tableau "tabPremiers" qui permet de differencier les nombres premiers
    {
    	std::vector<bool> tab(choix,true);
    	tab[0] = false;
    	tab[1] = false;
     
    	for (int a = 2; a < tab.size(); a++)
    	{
    		if (tab[a] == true)
    		{
    			for (int b = a*2; b < tab.size(); b += a)
    			{
    				tab[b] = false;
    			}
    		}
    	}
     
    	return tab;
    }
     
    int nombreAleatoire(int choix) //Fonction appelé dans le main pour obtenir un nombre aléatoire par rapport à la taille du tableau
    {
    	std::random_device a;
    	std::default_random_engine b(a());
    	std::uniform_int_distribution<int> uniform_dist(2, choix);
    	int nombre = uniform_dist(b);
     
    	return nombre;
    }
     
    void reponseProg(const std::vector<bool>& tab, const std::string& choix, const int& nombreTab) //Fonction qui donne une réponse au joueur par rapport a son choix
    {
    	if (choix == "o" || choix == "O")
    	{
    		if (tab[nombreTab] == true)
    		{
    			std::cout << "Bravo! " << nombreTab << " est bien un nombre premier :)" << std::endl << std::endl;
    		}
    		else if (tab[nombreTab] == false)
    		{
    			std::cout << "Aie, desole! " << nombreTab << " n'est pas un nombre premier :'(" << std::endl << std::endl;
    		}
    	}
    	else if (choix == "n" || choix == "N")
    	{
    		if (tab[nombreTab] == true)
    		{
    			std::cout << "Aie, desole! " << nombreTab << " est bien un nombre premier :'(" << std::endl << std::endl;
    		}
    		else if (tab[nombreTab] == false)
    		{
    			std::cout << "Bravo! " << nombreTab << " n'est pas un nombre premier :)" << std::endl << std::endl;
    		}
    	}
    }
     
    int main()
    {
    	auto tabPremiers(nombresPremiers(256));
    	bool recommencer(true);
     
    	std::cout << "Bienvenue dans le jeu du crible d'Eratosthene!\n\nLa regle est simple, je vous donne si un nombre et";
    	std::cout << " vous me dites si c'est un\nnombre premier ou pas. Repondez simplement par O pour oui ou par N pour non.\n\nC'est parti!" << std::endl << std::endl;
     
    	do
    	{
    		std::string choixQuestion, choixRecommencer;
    		auto nombreTableau = nombreAleatoire(255); //Appel de la fonction nombreAleatoire pour obtenir un nombre entre 0 et 255
     
    		std::cout << "Le nombre " << nombreTableau << " est-il un nombre premier?" << std::endl;
    		std::cin >> choixQuestion; //L'utilisateur répond à la question
    		std::cout << std::endl;
     
    		reponseProg(tabPremiers, choixQuestion, nombreTableau); //Appel la fonction reponseProg pour donne rune réponse à l'utilisateur par rapport à son choix
     
    		std::cout << "Voulez vous recommencer une partie? o/n" << std::endl;
    		std::cin >> choixRecommencer;
     
    		if (choixRecommencer == "n" || choixRecommencer == "N") //Si l'utilisateur répond "n", la partie s'arrête
    		{
    			recommencer = false;
    		}
    	} while (recommencer);
     
        return 0;
    }
    Super exo, ca m'a fait travailler pas mal de chose! J'en attends des nouveaux alors ^^

  11. #51
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut Exercices leçon 2
    Alors en voilà un autre. Il tourne autour du jeu de poker. L'idée est d'utiliser les concepts de la leçon n°2: les algorithmes de la bibliothèque standard, les itérateurs et, quand nécessaire, les fonctions lambda.

    Le jeu de poker (étape 1);

    Une carte est représentée par deux entiers non-signés contenus dans une paire (std::pair):
    - regarder la documentation de std::pair dans la référence
    - la première valeur de la paire représente le rang de la carte: 0 = 2, 1 = 3, ... , 9 = valet, 10 = dame, ... , 12 = as. La deuxième valeur contient la couleur: 0 = carreau, ... 3 = trèfle.
    - générer le jeu de 52 cartes dans l'ordre:
    a) utiliser la fonction standard std::iota (dans le header <numeric>) pour générer 52 paires: { {0,0}, {1,1}, ... {51,51}}. Pour que iota fonctionne pour des paires, il faut d'abord définir un opérateur ++ pour les paires. En voici une implémentation possible:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    std::pair<unsigned, unsigned>& operator++(std::pair<unsigned, unsigned>& p) {
        ++p.first;
        ++p.second;
        return p;
    }
    b) utiliser la fonction standard std::transform (dans le header <algorithm>) pour transformer le tableau de paires croissantes en un jeu de cartes. Il est possible de recourir à une lambda, utilisant pourquoi pas l'opérateur modulo (11 % 2 == "11 modulo 2" == reste de la division de 11 par 2 == 1)
    - écrire une fonction pour mélanger le paquet de cartes. S'appuyer sur l'algorithme std::shuffle.
    - écrire une fonction pour "couper" le paquet de cartes. S'appuyer sur l'algorithme std::rotate
    - écrire une fonction pour transformer une paire d'entiers non signés en une string de type "as de trèfle", "deux de carreau", etc.

  12. #52
    Membre du Club Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Points : 52
    Points
    52
    Par défaut
    T'as monté la barre de plusieurs niveaux là!

    J'vais d'abord bucher chaque point individuellement avant de tester ton exo car là pour le moment, ca donnerait rien ^^


    Et sinon j'ai une question, je l'ai posé à Gbdivers sur le forum d'OC et je voudrais avoir votre point de vue aussi:

    Nul part je n'ai justifié du pourquoi j'apprenais le C++ et ca serait bien d'en parler avant de continuer. J'aimerais acquérir les capacités pour coder des jeux vidéo 2D voir 2D en 3D.

    Je me suis dit, quitte à apprendre un langage, autant apprendre un comme le C++ qui peut faire un peu de tout mais maintenant que je me rend compte de la complexité, je me
    dis que peut être un langage plus haut niveau serait peut être plus adapté et serait moins dur. Qu'en pensez-vous?

    Le peu que j'ai appris en C++, j'ai complétement accroché mais j'ai l'impression qu'il me manque des bases d'algo et autre pour vraiment en profiter pleinement.

  13. #53
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    T'as monté la barre de plusieurs niveaux là!

    J'vais d'abord bucher chaque point individuellement avant de tester ton exo car là pour le moment, ca donnerait rien ^^
    Oui c'est plus dur. L'avantage du forum c'est qu'on peut faire interactif: si tu bloques ou que tu as besoin de compléments, tu peux me demander. Je ferai peut-être un vrai tutoriel pour le site à partir de nos échanges.

    Et sinon j'ai une question, je l'ai posé à Gbdivers sur le forum d'OC et je voudrais avoir votre point de vue aussi:

    Nul part je n'ai justifié du pourquoi j'apprenais le C++ et ca serait bien d'en parler avant de continuer. J'aimerais acquérir les capacités pour coder des jeux vidéo 2D voir 2D en 3D.
    Oui, C++ est un bon choix pour écrire des jeux 2D/3D. Une série d'articles très bien va paraître à ce sujet sur le site dans quelques temps: les premiers sont en phase de relecture technique. Cela étant, en C++ ou dans un autre langage, c'est un gros morceau.

    Je me suis dit, quitte à apprendre un langage, autant apprendre un comme le C++ qui peut faire un peu de tout mais maintenant que je me rend compte de la complexité, je me
    dis que peut être un langage plus haut niveau serait peut être plus adapté et serait moins dur. Qu'en pensez-vous?
    L'avantage d'être autodidacte, c'est qu'on peut choisir un, plusieurs langages, passer de l'un à l'autre selon l'inspiration du moment et son bon plaisir. Si tu sens que C++ n'est pas fait pour toi en ce moment, il y a en effet des langages plus simples, comme Python ou, dans une moindre mesure, Java. Ils sont populaires, de nombreuses bibliothèques sont disponibles, y compris pour écrire des jeux. Tu peux regarder Pygame, par exemple: http://pygame.org/hifi.html. Il y a un sous-forum sur le site qui propose des discussions sur les mérites relatifs des différents langages. C'est difficile de se faire un avis à partir de ce genre de discussions mais tu peux au moins voir l'avis des autres.

    Le peu que j'ai appris en C++, j'ai complétement accroché mais j'ai l'impression qu'il me manque des bases d'algo et autre pour vraiment en profiter pleinement.
    Les algorithmes c'est de toute façon quelque chose à voir à un moment ou à un autre, quel que soit le langage. Peut-être même plus dans des langages plus lents que C++: quand on est déjà un peu handicapé par le langage, il faut être certain d'utiliser l'algorithme le plus efficace.
    Cependant -et c'est mon objectif de te le montrer- on peut repousser ce moment en utilisant les bibliothèques déjà disponibles, qui offrent des algorithmes ou des briques d'algorithme prêts à l'emploi. La bibliothèque standard de C++ est, à mon avis, un des sommets de la programmation. Boost met aussi beaucoup de ressources à disposition. Donc je dirais que tu auras plutôt besoin de bases d'algo pour continuer que pour commencer.

  14. #54
    Membre du Club Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Points : 52
    Points
    52
    Par défaut
    Salut!

    Merci, je voulais juste être sûr du chemin que je prends, car si c'est au bout d'un an que je me rend compte que j'ai fais le mauvais choix, ca la fou mal..

    Je vais rester sur du C++, c'est p'tete un des plus dur mais au moins j'aurais plus de portes ouvertes. Je vais faire un peu de cours d'algo débutant à coter et commencer
    à toucher un peu de unreal 4. Ca me permettra de varier un peu et de pas toujours faire la même chose.

    J’espère juste ne pas m'y prendre trop tard, à 27 ans, j'commence à me faire fais vieux ^^

    Je sais que ca va être long à apprendre tout ça mais j'ai surtout peur que tout seul, je n'arrive jamais au bout... Heureusement qu'il y a les forum pour que des personnes
    comme vous, aide les personnes comme moi.. Merci les gars

  15. #55
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Je sais que ca va être long à apprendre tout ça
    Pas forcément. Si tu travailles régulièrement c'est l'affaire de quelques mois pour être capable de faire un jeu pas trop difficile.
    Tu t'en sors avec l'exo? J'ai peut-être frappé trop fort sans m'en rendre compte?

  16. #56
    Membre du Club Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Points : 52
    Points
    52
    Par défaut
    Alors j'ai buché la leçon 2, j'ai compris les iterateurs mais les lambda j'avoue que je suis un peu encore dessus... Mais pour le début de l'exo, j'ai compris a
    quoi sert chaque fonction, je sais utiliser chaque partie indépendamment mais j'avoue pas trop savoir par quoi commencer, j'ai pas trouvé beaucoup de détail
    sur std::pair et std::iota :/

  17. #57
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    std::pair est un type générique, comme std::vector; mais au lieu de n'avoir qu'un autre type en paramètre, il en a deux:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::pair<int, char> p1;
    std::pair<std::string, std::vector<int>> p2;
    etc.
    Un type pour chacun des membres de la paire (il y en a deux comme le nom l'indique). On peut créer une paire avec std::make_pair:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    auto contact = std::make_pair("Fred", "0612345678"); // les types paramétrant pair sont déduits par make_pair
    Le premier membre s'appelle first, le second second:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::cout << contact.first << " Tel: " << contact.second; // Fred Tel: 0612345678
    il y a un mot-clé très pratique de c++: using, qui permet de donner un nom plus expressif ou plus court à un type compliqué:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    using Card = std::pair<unsigned, unsigned>;
    Card card; // card est de type std::pair<unsigned, unsigned>
    Mettons maintenant qu'on veuille créer un paquet de cartes pour le jeu de poker. On peut choisir un std::array, puisque le jeu a toujours 52 cartes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    using Deck = std::array<Card, 52>; // Deck = paquet de cartes en anglais
    // Pour l'instant les cartes sont toutes égales à {0,0}
    L'idée est d'utiliser les algorithmes de la bibliothèque standard pour faire l'exercice. Pour initialiser les cartes on peut utiliser std::iota et std::transform.

    std::iota fournit une suite croissante à partir d'une valeur intiale:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::vector<unsigned> entiers_positifs(5); // de la place pour 5 entiers positifs
    std::iota(std::begin(entiers_positifs), std::end(entiers_positifs), 1); // 1 est le premier entier positif
    print_vec(entiers_positifs); // {1,2,3,4,5}
    Pour connaître la prochaine valeur de la série, iota utilise l'opérateur++ (voir la leçon n°2) qui incrémente de 1 son opérande.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    auto x = 2;
    ++x;
    std::cout << x; // 3
    La difficulté est que les paires n'ont pas d'opérateur ++ prédéfini.
    C'est la raison pour laquelle il faut en définir un; les opérateurs en c++ peuvent être redéfinis pour des types non primitifs (c'est-à-dire tous les types qui ne sont pas int, char, float, etc.). Voici la syntaxe, qui est très proche d'une fonction normale:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    type_retour operator++(type_operande);
    type_retour operator/(type_operande1, type_operande2);
    etc.
    Dans l'énoncé de l'exercice, je te proposais une définition de l'opérateur++ pour les paires. Tu peux y jeter un coup d'oeil maintenant. Il incrémente chacun des membres de la paire de 1. Donc {0,0} donne {1,1}, {1,1} donne {2,2}, etc.
    Du coup, après avoir défini cet opérateur tu peux écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Deck deck;
    std::iota(std::begin(deck), std::end(deck), Card(0,0)); // deck = { {0,0}, {1,1}, ..., {51,51}}
    Bien entendu cela ne forme pas un paquet de carte. Pour faire une carte valide il faut un premier membre entre 0 et 12 (c-à-d entre 2 et as) et un deuxième entre 0 et 3 (c'est-à-dire entre "coeur" et "trèfle"). Il nous faut un moyen de réduire les valeurs des paires que nous avons créées pour qu'elles rentrent entre ces bornes.

    L'opérateur % ("modulo") peut être utilisé pour cela. Cet opérateur donne le reste de la division entière entre ses opérandes:
    11 / 2 = 5 reste 1 <=> 11 % 2 = 1
    14 / 2 = 7 reste 0 <=> 14 % 2 = 0
    Comme il s'agit du reste d'une division, il est nécessairement compris entre 0 et l'opérande de droite - 1

    Prenons la 42ème carte. Elle est égale à {41,41}. Si j'applique l'opérateur % 13 (le nombre de cartes par couleur) au premier membre, j'aurai une carte de rang valide; si j'applique l'opérateur % 4 au deuxième membre, j'obtiens une couleur valide. D'où:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Card make_valid(Card c) {
      c.first = c.first % 13; // plus court et équivalent: c.first %= 13
      c.second = c.second % 4; // c.second %= 4
      return c;
    }
    std::transform permet d'appliquer cette fonction à tout le paquet de cartes créé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::transform(std::begin(deck), std::end(deck), make_valid);
    Néanmoins il est un peu ennuyeux de devoir définir des fonctions comme make_valid: elles servent une seule fois, leur définition sera éloignée de l'endroit où elles sont utilisées, et il faut leur trouver un nom; s'il y a d'autres choses à valider dans le programme, le nom pourrait déjà être pris... D'où l'intérêt d'utiliser une lambda:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::transform(std::begin(deck), std::end(deck), [](Card c) { c.first %= 13; c.second %= 4; return c});
    Maintenant je pense que tu es paré pour faire la suite des exercices...

  18. #58
    Membre du Club Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Points : 52
    Points
    52
    Par défaut
    Coucou!

    Merci pour ces détails en plus ça m'a bien aidé à comprendre mais malgré que tu m’aies mâché le travail à 95%, je bloque sur std::iota
    et l'operator++, je sais pas ou placer la fonction ou comment l'appeler.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    #include "stdafx.h"
    #include <iostream>
    #include <utility>
    #include <array>
    #include <numeric>
     
    using Carte = std::pair<unsigned, unsigned>;
    using Deck = std::array<Carte, 52>;
     
    Carte& operator++(Carte& p)
    {
    	++p.first;
    	++p.second;
    	return p;
    }
     
    int main() {
     
    	Deck jeuDeCarte;
     
    	std::iota(std::begin(jeuDeCarte), std::end(jeuDeCarte), Carte(0, 0));
     
    	std::transform(std::begin(jeuDeCarte), std::begin(jeuDeCarte), std::end(jeuDeCarte), [](Carte c) { c.first %= 13; c.second %= 4; return c; });
     
    	for (int x = 0; x < jeuDeCarte.size(); x++)
    	{
    		std::cout << jeuDeCarte[0].first << jeuDeCarte[0].second << std::endl;
    	}
    }
    Et tant qu'à faire, j'ai des question pour qui peut y répondre:

    1- A quoi sert std::print (ou printf ou print_vec)? Ca ressemble à std::cout?
    2- Typedef est obsolète par rapport à Using? On doit les utiliser avant le main ou après?
    3- J'ai pas saisie la différence entre std::pair<*,*>; et std::make_pair(*,*);

    Merci

  19. #59
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    0) L'opérateur ++ est appelé par la fonction std::iota, qui est définie dans la bibliothèque standard: c'est normal que tu ne vois pas l'appel à l'opérateur puisqu'il est fait dans la définition (cachée) de cette fonction. Il faut qu'il soit défini avant l'appel de la fonction iota pour qu'elle puisse l'appeler à son tour. Fais-le test, enlève la définition de l'opérateur avant d'appeler std::iota: que se passe-t-il? que te dit le compilateur?

    1) std::print, je ne connais pas. printf est la fonction standard de C pour afficher à l'écran; il n'est pas recommandé de l'utiliser en C++. print_vec est une fonction que j'ai définie, qui ressemble à la fonction que tu avais définie dans le premier exercice pour afficher les éléments d'un vecteur, séparés par une virgule, entre accolades.

    2) oui, typedef est plutôt obsolète. using est plus puissant. En particulier on peut paramétrer une directive using (c'est une notion un peu plus avancée, mais ça ne peut pas te faire de mal de voir à quoi cela ressemble):
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    template <type T>
    using Tableau = std::vector<T>;
    ...
    Tableau<unsigned> nombres_premiers; // nombres premiers est de type std::vector<unsigned>
     
    // au contraire, un typedef par type de std::vector:
    typedef std::vector<unsigned> Tableau_entiers_nonsignes;

    On peut les utiliser avant le main, dans le main, dans une fonction... Ce qui change c'est leur portée. La portée va de la directive using à la fin du bloc où elle est utilisée:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    using Tag = std::string; // Tag est utilisable dans tout le fichier à  partir de cette ligne
    int main() {
      Tag a;
      using Bi_tag = std::pair<Tag, int>; // Bi_tag est utilisable de cette ligne jusqu'à la fin de main
    }
     
    Bi_tag mon_bi_tag; // erreur!

    3) std::pair<T, U> est un type; std::make_pair(T t, U u) est une fonction.
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::pair<unsigned, unsigned> p1(0,1); // syntaxe avant C++11
    std::pair<unsigned, unsigned> p2 = {0,1}; // syntaxe C++11 premier choix. {0,1} peut être autre chose qu'une paire, il faut donc déclarer le type de p2
    auto p3 = std::make_pair(0u,1u); // u après un littéral (ex: 56u) signifie que ce littéral est de type unsigned int. on connaît le type de retour de make_pair, on peut donc utiliser auto

  20. #60
    Membre du Club Avatar de toto81
    Homme Profil pro
    Agent TNT Express
    Inscrit en
    Mai 2012
    Messages
    67
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Agent TNT Express
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2012
    Messages : 67
    Points : 52
    Points
    52
    Par défaut
    Ok mais alors qu'est-ce qui cloche dans mon code? Mon std::array reste à 0,0 dans chaque case grrr

    A oui aussi, j'ai du écrire ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::transform(std::begin(jeuDeCarte), std::begin(jeuDeCarte), std::end(jeuDeCarte), [](Carte c) { c.first %= 13; c.second %= 4; return c; });
    au lieu de comme toi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::transform(std::begin(jeuDeCarte), std::end(jeuDeCarte), [](Carte c) { c.first %= 13; c.second %= 4; return c; });
    Il me demandait 4 arguments obligatoires alors j'ai doublé le premier mais sans trop savoir pourquoi.

Discussions similaires

  1. Problème dans la page de correction d'un exercice?
    Par menoulette dans le forum Langage
    Réponses: 4
    Dernier message: 30/08/2009, 23h57
  2. Réponses: 11
    Dernier message: 04/02/2008, 20h37
  3. Correction d'un exercice en C++
    Par aniscpp dans le forum C++
    Réponses: 2
    Dernier message: 07/12/2006, 14h01
  4. besoin d'une correction sur un exercice.
    Par phakso dans le forum Algorithmes et structures de données
    Réponses: 13
    Dernier message: 03/03/2006, 10h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo