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 :

Algorithme de Vigenere


Sujet :

C++

  1. #1
    Membre à l'essai Avatar de tontonrichmon
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2016
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2016
    Messages : 16
    Points : 11
    Points
    11
    Par défaut Algorithme de Vigenere
    Bonjour tout le monde !

    J'étais entrain de réaliser un programme permettant de crypter un message selon l’algorithme de Vigenere en C++.

    A son lancement aucun problème problème ne s'affiche.
    Le message est correctement crypté, je l'affiche ensuite.

    Arrive alors la partie décryptage pour vérifier si j'arrivais à restituer le message, car c'est mieux de savoir décoder quand même
    J'appelle donc ma fonction de décryptage et utilise la même clé que celle utilisée pour le cryptage, mais, le message affiché ensuite ne correspond pas à mon texte d'origine.

    Voici mes fichiers:

    vigenere.h :

    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
     
     
    #ifndef VIGENERE_H
    #define VIGENERE_H
     
     
    #include <string>
    #include <iostream>
     
    using namespace std;
     
    class vigenere
    {
    private:
     
    public:
        vigenere();
        void vigenere_crypter(const string& input, string& output, const string& cle);
        void vigenere_decrypter(const string& input, string& output, string& cle);
    };
     
    #endif // VIGENERE_H

    vigenere.cpp :

    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
     
     
    #include "vigenere.h"
     
    vigenere::vigenere()
    {
     
    }
     
    void vigenere::vigenere_crypter(const string& input, string& output, const string& cle)
    {
        output.resize(input.size(),0);
        for(size_t i=0,j=0; i!=input.size(); ++i)
        {
            if(j==cle.size()) j = 0;
     
            output[i] = toupper(input[i]);
            if((output[i] >= 'A') && (output[i] <='Z'))
            {
                output[i] = ((output[i] + cle[j]-2*'A') % 26 + 'A');
                ++j;
            }
            else
            {
                output[i] = input[i];
            }
        }
    }
     
     
    void vigenere::vigenere_decrypter(const string& input, string& output, string& cle)
    {
        string cle_tmp = cle;
        for(size_t j=0; j!=cle_tmp.size(); ++j)
        {
            cle_tmp[j]= 26-(cle_tmp[j] - 'A') + 'A';
        }
        vigenere_crypter(input,output,cle_tmp);
    }

    main.cpp :

    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
     
     
    #include <iostream>
    #include "vigenere.h"
     
    using namespace std;
     
    int main()
    {
        vigenere cryp;
        string str_crypt;
        string str_decrypt;
        string cle = "hello";
     
        cryp.vigenere_crypter("salut ceci est un test",str_crypt,cle);
        cout << str_crypt << endl;
     
        cryp.vigenere_decrypter(str_crypt,str_decrypt,cle);
        cout << str_decrypt << endl;
     
        return 0;
    }
    Je pense que mon erreur est simple mais je n'arrive pas à la voir...
    Si vous pouviez m'éclairer, merci d'avance

  2. #2
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 110
    Points
    6 110
    Par défaut
    Bonjour.

    Citation Envoyé par tontonrichmon Voir le message
    Le message est correctement crypté
    En es-tu sûr ?

    Dans la logique de ton algorithme, les caractères de ta clé doivent être compris entre 'A' et 'Z'.
    Or, dans ton code, ta clé est en minuscules.

    A part ça, j'aurais plutôt écrit "vigenere.h" comme ceci :
    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
    #ifndef VIGENERE_H
    #define VIGENERE_H
     
    #include <string>
     
    class vigenere
    {
    public:
        vigenere(const std::string& cle);
        std::string crypter  (const std::string& input) const;
        std::string decrypter(const std::string& input) const;
    private:
        const std::string m_cle;
    };
     
    #endif // VIGENERE_H
    Motifs :
    • Pas besoin d'inclure <iostream> dans cet entête.
    • Il faut éviter d'écrire "using namespace std;" dans un entête. Autrement, cela impacte aussi tous les ".cpp" qui incluent cette entête. Il vaut mieux laisser la liberté aux ".cpp" de faire les "using" qu'ils veulent.
    • Tes fonctions "vigenere_crypter" et "vigenere_decrypter" sont non statiques alors que ta classe "vigenere" ne contient aucune variable membre qui modifie le fonctionnement de ces deux fonctions. Ce serait plus cohérent d'avoir des fonctions statiques, ou bien des fonctions globales dans un espace de nom "vigenere". Mais, dans cet exemple, il me semble logique que la clé soit une variable membre de la classe.
    • En C++, il est plus simple de manipuler des fonctions qui retournent un "std::string" plutôt que des fonctions qui retournent "void" avec un paramètre supplémentaire "std::string& output"
    • Dans tes fonctions "vigenere_crypter" et "vigenere_decrypter", le préfixe "vigenere_" est inutile.

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 631
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 631
    Points : 10 558
    Points
    10 558
    Par défaut
    Citation Envoyé par Pyramidev Voir le message
    En C++, il est plus simple de manipuler des fonctions qui retournent un "std::string" plutôt que des fonctions qui retournent "void" avec un paramètre supplémentaire "std::string& output"
    Bof

    Si tu ne retournes pas une référence, alors tu va créer un temporaire (donc une recopie à moins que le compilateur optimise) que tu pourras prolonger sa vie en le prenant en const.

    C'est juste un truc obscure que peu de gens savent. Avec un paramètre non const il y a [nettement] moins de comprenette

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    std::string func(/**/) { /**/ }
     
    // ...
     
        const std::string ret = func(/**/);

  4. #4
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 110
    Points
    6 110
    Par défaut
    Il est plus simple de manipuler des fonctions qui retournent un "std::string" plutôt que des fonctions qui retournent "void" avec un paramètre supplémentaire "std::string& output" dans le sens où, dans le deuxième cas, l'utilisateur de la fonction doit créer l'objet "std::string" avant d'appeler la fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    std::string foo();
    void bar(std::string& output);
     
    int main()
    {
        // une ligne :
        std::string fooResult = foo();
     
        // deux lignes, ce qui est moins pratique :
        std::string barResult;
        bar(barResult);
     
        return 0;
    }
    Citation Envoyé par foetus Voir le message
    Si tu ne retournes pas une référence, alors tu va créer un temporaire (donc une recopie à moins que le compilateur optimise) que tu pourras prolonger sa vie en le prenant en const.

    C'est juste un truc obscure que peu de gens savent. Avec un paramètre non const il y a [nettement] moins de comprenette

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    std::string func(/**/) { /**/ }
     
    // ...
     
        const std::string ret = func(/**/);
    Je n'ai pas compris ton message.
    A ma connaissance, ça se passe comme ça :
    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
    std::string foo() {
        std::string result("car");
        result += "table";
        return result;
    }
     
    int main()
    {
        std::string s1 = foo();
        // En théorie, il peut y avoir deux appels au constructeur de recopie de std::string :
        // -un pour créer le std::string retourné par la fonction à partir de "result" et
        // -un pour initialiser s1 à partir du std::string retourné par la fonction.
        // En pratique, le compilateur fait du NRVO et il n'y a aucun appel au constructeur de recopie de std::string.
     
        const std::string s2 = foo();
        // En théorie, il peut y avoir deux appels au constructeur de recopie de std::string ici aussi, non ?
        // En pratique, le compilateur fait du NRVO et il n'y a aucun appel au constructeur de recopie de std::string.
     
        return 0;
    }
    Aurais-je tort dans le cas de s2 ?

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 631
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 631
    Points : 10 558
    Points
    10 558
    Par défaut
    Dans ce cas


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    std::string foo() {
        return std::string("car");
     
    //  return "car";
    }

    Édit: GotW #88: A Candidate For the “Most Important const”

  6. #6
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 110
    Points
    6 110
    Par défaut
    Ta fonction foo a une instruction de la forme "return <objet temporaire>;"
    Ton lien GotW parles du cas où on initialise une référence constante à partir d'un objet temporaire.
    En prenant en compte ces cas aussi, je pense que ça marche comme ça :
    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
    std::string foo() {
        std::string result("car");
        result += "table";
        return result;
    }
     
    std::string bar() {
        return std::string("car");
    }
     
    int main()
    {
        std::string s1 = foo();
        // En théorie, il peut y avoir deux appels au constructeur de recopie de std::string :
        // -un pour créer le std::string retourné par la fonction à partir de "result" et
        // -un pour initialiser s1 à partir du std::string retourné par la fonction.
        // En pratique, le compilateur fait du NRVO (Named Return Value Optimization)
        // et il n'y a aucun appel au constructeur de recopie de std::string.
     
        const std::string cs1 = foo();
        // Idem.
     
        const std::string& crs1 = foo();
        // En théorie, il peut y avoir un appel au constructeur de recopie de std::string
        // pour créer le std::string retourné par la fonction à partir de "result".
        // En pratique, le compilateur fait du NRVO et il n'y a aucun appel au constructeur de recopie de std::string.
        // Dans les deux cas, crs1 réfère à un objet temporaire retourné par la fonction.
     
        std::string s2 = bar();
        // En théorie, il peut y avoir deux appels au constructeur de recopie de std::string :
        // -un pour créer le std::string retourné par la fonction à partir de "std::string("car")" et
        // -un pour initialiser s2 à partir du std::string retourné par la fonction.
        // En pratique, le compilateur fait du RVO (Return Value Optimization)
        // et il n'y a aucun appel au constructeur de recopie de std::string.
     
        const std::string cs2 = bar();
        // Idem.
     
        const std::string& crs2 = bar();
        // En théorie, il peut y avoir un appel au constructeur de recopie de std::string
        // pour créer le std::string retourné par la fonction à partir de "std::string("car")".
        // En pratique, le compilateur fait du RVO et il n'y a aucun appel au constructeur de recopie de std::string.
        // Dans les deux cas, crs2 réfère à un objet temporaire retourné par la fonction.
     
        return 0;
    }
    Rq : Pour ceux qui veulent plus de détails sur RVO et NRVO :

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 631
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 631
    Points : 10 558
    Points
    10 558
    Par défaut
    Désolé pour le dérangement , c'est ceci qui plante:

    invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘std::string {aka std::basic_string<char>}’

    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
    std::string foo() {
        std::string result("car");
        result += "table";
        return result;
    }
     
     
    std::string bar() {
        return std::string("car");
    }
     
     
    int main()
    {
        std::string& s1_1 = foo();
     
        std::string& s2_1 = bar();
     
        return 0;
    }

  8. #8
    Membre à l'essai Avatar de tontonrichmon
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2016
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2016
    Messages : 16
    Points : 11
    Points
    11
    Par défaut
    Merci d'avoir été nombreux à m'aider pour mon problème, donc au final l'erreur était toute simple... la clé en majuscule.
    Sur ce niveau tout est ok du coup.
    Par contre, auriez-vous une idée d'adaptation de ce code pour permettre de crypter des chiffres ?
    (des clés mac par exemple)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Algorithme de vigenere modifié
    Par ehounsou dans le forum C
    Réponses: 1
    Dernier message: 03/11/2012, 15h01
  2. Algorithme de randomisation ... ( Hasard ...? )
    Par Anonymous dans le forum Assembleur
    Réponses: 8
    Dernier message: 06/09/2002, 14h25
  3. recherches des cours ou des explications sur les algorithmes
    Par Marcus2211 dans le forum Algorithmes et structures de données
    Réponses: 6
    Dernier message: 19/05/2002, 22h18
  4. Recherche de documentation complète en algorithmes
    Par Anonymous dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 29/03/2002, 12h09
  5. Algorithme génétique
    Par Stephane.P_(dis Postef) dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 15/03/2002, 17h14

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