Chiffrement de César

Fermé
Akalia Messages postés 34 Date d'inscription mercredi 25 juin 2014 Statut Membre Dernière intervention 17 août 2016 - Modifié par baladur13 le 17/08/2016 à 10:50
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 - 20 sept. 2016 à 10:18
Bonjour,

Je suis en train de reproduire le chiffrement de César, dont j'ai certaines conditions à respecter, travailler avec les foncteurs, les itérateurs et les algorithmes fournit par la STL.

J'arrive à effectuer correctement le décalage, je vais fournir le code après. Ma question ici, concernera une modification sur les string. Bien entendu, je consulte la doc, et je connais les différentes informations sur les méthodes liées aux string. En fait, après avoir effectué mon chiffrement par décalage à l'aide de mon foncteur, j'applique l'algorithme transform() sur le texte initial, et je stocke ça dans une autre chaîne de caractère. Mon soucis, est de modifier la dernière chaîne de caractère, je souhaiterai lui ajouter (ou insérer) après chaque caractère de la chaîne (donc en parcourant la chaîne) une virgule suivie d'un espace; c'est à dire de passer soit par un string, soit par deux char se suivant.

Le problème, c'est que je modifie la longueur de la chaîne, et j'ai l'impression que le compilateur n'aime pas ça, et c'est bien normal, mais je reste bloqué, car je n'arrive vraiment pas à comprendre comment faire pour réaliser cet ajout ou insertion (via les méthodes append() et insert() ).

Plus de compréhension via le code, car là j'explique de manière brute.

#include <iostream>
#include <string>
#include <cctype>
#include <iterator>
#include <algorithm>

using namespace std;

// Foncteur qui effectue un chiffrement par decalage
class ChiffrementDecal{

public:

  // Constructeur prenant le decalage voulu en argument
  ChiffrementDecal(int decalage): m_decalage(decalage)
  {

  }
  // Operateur() de surcharge
    char operator()(char c)
    {
        char d;
        if (isupper(c))
        {
            d = (c + m_decalage -'A')%26 + 'A';

        }
        else
        {
            d = c;
        }
        return d;
    }

private:

    int m_decalage; // Le decalage a appliquer au texte

};


int main()
{

  // Le message a crypter
  string texte("BIENVENUE SUR LE [/faq/37817-les-moocs-comment-ca-marche MOOC] C++ D'OCR !!");

  // Demande du decalage a l'utilisateur
  cout << "Quel decalage voulez-vous utiliser ? ";
  int decalage;
  cin >> decalage;

  // Creation du foncteur
    ChiffrementDecal foncteur(decalage);

  // Chaine de caracteres pour le message crypter
    string texte_crypte;
    back_insert_iterator<string> it1(texte_crypte); //Ajuste la longueur du string avec la première

    transform(texte.begin(), texte.end(), *it1, foncteur);

// Ici, la modification du string
 //  for (string::iterator it = texte_crypte.begin(); it != texte_crypte.end(); ++it)
 //   {
 //         texte_crypte.insert(*it, ", ");

  //  }


  // Affichage
    cout << texte_crypte << endl;
    cout << texte << endl;

  return 0;
}


Alors, l'autre problème est que j'ai l'impression que c'est un ajout que je ne peux faire qu'en dehors du foncteur étant donné que je travaille avec des char dans mon foncteur.

Je reste ouvert à toutes vos réponses que vous pourrez me fournir.


EDIT : Ajout des balises de code (la coloration syntaxique).
Explications disponibles ici : ICI

Merci d'y penser dans tes prochains messages.

2 réponses

Akalia Messages postés 34 Date d'inscription mercredi 25 juin 2014 Statut Membre Dernière intervention 17 août 2016
17 août 2016 à 10:35
J'ai finalement trouvé bêtement une solution sans directement modifier la chaîne de caractères, en mettant à la place du insert, tout simplement cette ligne:

cout << *it << ", ";


Cependant, je garde le sujet ouvert afin de savoir si le insert (ou append) est bel et bien possible, car le compilateur me le dit que c'est une histoire de out of range sur mon string, et j'aimerai bien savoir comment pallier ce problème là si je ne souhaite pas passer par cout et que je désire que ma chaîne de caractère comporte cette virgule et cet espace.
0
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 7 751
Modifié par mamiemando le 20/09/2016 à 10:21
Bonjour,

Disons qu'en terme de design n'y a aucune raison de recopier la chaîne sur laquelle tu appliques le traitement, ça peut se faire in place. Si ensuite tu veux conserver la chaîne original, c'est plutôt qu'il faut faire une copie en amont et altérer la copie.

Du coup tu vas plutôt passer un
std::string &
à ton foncteur (ou un
char *
). Ensuite qu'est ce qui différencie un foncteur d'une simple fonction ? En gros, il a un constructeur, typiquement quelque chose qui permet de paramétrer la fonction, typiquement le décalage que tu vas appliquer. On pourrait également s'en sortir avec une fonction qui prendrait un paramètre template entier.

Ensuite comme tu l'as indiqué, utiliser un iterator sur la chaîne est une bonne manière de l'altérer.

#include <string>
#include <iostream>

struct cesar_t {
  size_t m_decalage;

  cesar_t(size_t decalage):
    m_decalage(decalage)
  {}

  void operator()(std::string & s) {
    for (std::string::iterator it = s.begin(); it != s.end(); it++) {
      char & c = *it;
      if (c >= 'a' && c <= 'z') {
        c = (c + m_decalage - 'a') % 26 + 'a';
      } else if (c >= 'A' && c <= 'Z') {
        c = (c + m_decalage - 'A') % 26 + 'A';
      }
    }
  }
};

int main() {
  std::string s = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  std::cout << "s = " << s << std::endl;
  cesar_t cesar(13);
  cesar(s);
  std::cout << "s = " << s << std::endl;
  return 0;
}


Ce qui donne :

(mando@velvet) (~) $ g++ cesar.cpp 
(mando@velvet) (~) $ ./a.out
s = abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
s = nopqrstuvwxyzabcdefghijklm0123456789NOPQRSTUVWXYZABCDEFGHIJKLM



Ensuite pour ces histoires de append ou autre, il faut garder à l'esprit que c'est faisable mais une mauvaise approche. Chaque append provoque une potentielle réallocation du buffer de ta string ce qui est inutilement cher.

Note : pour faire bien les choses, tu peux également ajouter l'opérateur
void operator()(char * s)
.

Bonne chance
0