2017-02-18 2 views
0

Éditer: ceci est connu sous le nom de chiffrement Caesar. J'essayais de créer un programme qui avait pour but principal de crypter une chaîne donnée (courte et minuscule). Il le ferait en déplaçant toutes les lettres n espaces vers la droite (cryptage) ou vers la gauche (décodage).Chiffrement d'une chaîne de texte donnée - Chiffrement Caesar

Voici ce que j'ai écrit jusqu'à présent (modifié)

#include "stdafx.h" 
#include <iostream> 
#include <string> 
using namespace std; 

char abc[26] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 
       'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 
       's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; 

void code(int n) { 
    string cadena; 
    cout << "Introduzca la cadena a cifrar : " << '\n'; 
    cin >> cadena; 

    for (int i(0); i < cadena.length; i++) { 
    for (int f(0); f < strlen(abc); f++) { 
     if (cadena[i] == abc[f]) { 
     int w; 
     w = f + n; 
     if (w > strlen(abc)) { 
      w -= strlen(abc); 
     } 
     cadena[i] = abc[w]; 
     } 
    } 
    } 
    cout << cadena << '\n'; 
    system("pause"); 
} 

void decode(int n) { 
    string cadena; 
    cout << "Introduzca la cadena a cifrar : " << '\n'; 
    cin >> cadena; 

    for (int i(0); i < cadena.length; i++) { 
    for (int f(0); f < strlen(abc); f++) { 
     if (cadena[i] == abc[f]) { 
     int w; 
     w = f - n; 
     if (w < 0) { 
      w--; 
      w = strlen(abc) - w; 
     } 
     cadena[i] = abc[w]; 
     } 
    } 
    } 
    cout << cadena << '\n'; 
    system("pause"); 
} 

int main() { 
    int n; 
    cout << "Introduzca el numero del cesar " << '\n'; 
    cin >> n; 
    cout << "Desea usted cifrar o descifrar?" << '\n'; 
    cout << "Introduzca c para cifrar o d para descifrar" << '\n'; 
    char chos; 
    cin >> chos; 
    if (chos == 'c') 
    code(n); 
    else 
    decode(n); 

    return 0; 
} 

Maintenant, le problème est que je reçois une chaîne terrible que je ne savais même pas comment il a été formé. Et il y a aussi une erreur par une erreur.

This is the result

+1

Si vous n'êtes pas obligé d'utiliser des tableaux char, envisagez d'utiliser 'std :: string' et' std :: rotate'. – user4581301

+2

'sizeof (cadena)' est 1. 'i <= sizeof (cadena);' exécutera 2 itérations. 'f <= 26' va tourner 27 itérations – user4581301

+1

On dirait que vous essayez de faire un [Chiffrement Caesar] (https://en.wikipedia.org/wiki/Caesar_cipher). Pouvez-vous confirmer quel est votre objectif final? Je ne pense pas que tu doives faire quoi que ce soit. – user4581301

Répondre

3

Commençons par une promenade rapide à travers le code.

char abc[26] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 
       'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 
       'y', 'z' }; 

C'est bon. Il ne gère pas les majuscules, mais un bon démarrage

void code(int n) 
{ 
    char cadena; 

Définit un caractère isolé. Nous verrons plus tard que ce n'est pas ce que vous voulez.

char * cadena_ptr = &cadena; 

Dans des circonstances normales, cela est une bonne idée, mais avec un seul caractère, pas si utile

cout << "Introduzca la cadena a cifrar : " << '\n'; 
    cin >> cadena; 

Voici où les choses commencent à aller mal. Le code vient de lire en un seul caractère en raison de la façon dont cadena a été défini.

for (int i(0); i <= sizeof(cadena); i++) 

Comme mentionné précédemment cadena est un caractère si i <= sizeof(cadena) est le même que i <= 1. ceci se traduit par 2 itérations de la boucle. Un pour i=0 (0<=1) et un pour i=1 (1<=1). Cela signifie que la boucle dépassera les limites de cadena s un caractère. Les résultats de ceci sont indéfinis. Le programme peut tomber en panne. Le programme peut remplacer et corrompre les données autour de cadena. Le programme peut manger le chat de votre voisin. Tout serait parfaitement valide, mais les deux premiers sont beaucoup plus probables que le troisième.

{ 
     for (int f(0); f <= 26; f++) 

Cela s'exécute également en dehors des limites. Cette boucle peut également ne pas être nécessaire. En 2017, il est très peu probable que vous puissiez voir un encodage de caractères qui ne stocke pas tous les caractères dans un bloc contigu ascendant. Cela dit, cette boucle de force brute élimine la possibilité d'aller à l'encontre d'un encodage de caractères hérités ou bizzaro qui brouille l'ordre des caractères.

Je vais m'en tenir à cette boucle parce que la question n'est pas vraiment sur l'arithmétique ASCII.

 { 
      if (*cadena_ptr == abc[f]) 
      { 
       int w; 
       w = f + n; 
       if (w >= 26) 
       { 
        w -= 26; 
       } 
       *cadena_ptr = abc[w]; 

Ce bloc entier semble bon et devrait fonctionner une fois que les problèmes d'indexation sont résolus. Il y a une amélioration, cependant. Dès que vous avez trouvé un match, vous pouvez arrêter de chercher plus. Aussi beaucoup d'utilisation de qui devrait être remplacé.

  } 
     } 

    } 
    cout << cadena << '\n'; 
    system("pause"); 
} 

dépollution étape 1:

Fixer le large par une indexation. C'est assez rapide:

for (int i(0); i < sizeof(cadena); i++) 
    { 
     for (int f(0); f < sizeof(abc); f++) // death to magic number! 

Suivant la lecture dans plus d'un caractère:

La bonne façon! Utilisez a std::string et range-based for loop

void code(int n) 
{ 
    std::string cadena; 
    //char * cadena_ptr = &cadena; obsoleted by std::string 

    cout << "Introduzca la cadena a cifrar : " << '\n'; 
    cin >> cadena; 

    for (char & ch:cadena)// loop through all characters in cadena 
    { 
     for (int f(0); f < sizeof(abc) ; f++) 
     { 
      if (ch == abc[f]) 
      { 
       int w; 
       w = f + n; 
       if (w >= sizeof(abc)) 
       { 
        w -= sizeof(abc); 
       } 
       ch = abc[w]; 
       break;// we found it! Stop looking. 
      } 
     } 
    } 
    cout << cadena << '\n'; 
    system("pause"); 
} 

Je ne vais pas perdre mon temps sur la mauvaise façon. C'est faux. Apprenez à utiliser std::string.

Si les conditions du projet ne sont pas std::string, ne le faites pas dans le mauvais sens. Faites quelque chose de complètement différent! Lisez les caractères un par un, convertissez-les et imprimez-les. Pour chiffrer jusqu'à ce que nous trouvons un caractère qui ne peut pas être converti, nous pourrions faire quelque chose comme:

bool goodchar(char & cadena, int n) 
{ 
    for (int f(0); f < sizeof(abc) ; f++) 
    { 
     if (cadena == abc[f]) 
     { 
      int w; 
      w = f + n; 
      if (w >= sizeof(abc)) 
      { 
       w -= sizeof(abc); 
      } 
      cadena = abc[w]; 
      return true; 
     } 
    } 
    return false; 
} 

void code(int n) 
{ 
    char cadena; 

    cout << "Introduzca la cadena a cifrar : " << '\n'; 
    cin >> cadena; // get first character 

    while (goodchar(cadena)) // keep looping until we find a character that's 
          // not in the list  
    { 
     cout << cadena << '\n'; 
     cin >> cadena; // get next character 
    } 
    cout << '\n'; 
    system("pause"); 
} 
+0

Je jure devant Dieu. Je n'aurais jamais pensé que des gens aussi formidables étaient capables d'habiter sur Internet. Merci beaucoup! J'avais prévu d'utiliser de la ficelle (je l'ai même incluse dans l'en-tête), mais quand vous dites "nous l'avons trouvé, arrêtez de chercher", ça ne fait pas vraiment le travail. Je veux dire, la chaîne de texte a différents caractères qui ont des valeurs différentes et à leur tour, de nouvelles valeurs différentes, donc je ne comprends pas vraiment votre point de vue ... Je vais éditer le programme le matin et vous en dire plus. Merci!! – Zashuiba

+0

@Zashuiba Il y a deux boucles. La boucle externe traverse tous les caractères de la chaîne. Tu as raison. Vous voulez que ça continue. La boucle interne vérifie le caractère 'ch' de la boucle externe contre chaque caractère dans' abc'. Il n'y a pas de répétitions dans 'abc', donc dès que' ch' correspond à un élément de 'abc', il n'est pas nécessaire de vérifier' ch' par rapport 'abc'. [L'instruction 'break'] (http://en.cppreference.com/w/cpp/language/break) quitte la boucle interne au début, mais pas la boucle externe. – user4581301

+0

Une autre note. Comme 'abc' est bien ordonné, vous pouvez [utiliser' std :: find' pour effectuer une recherche à grande vitesse pour vous] (http://fr.cppreference.com/w/cpp/algorithm/find). – user4581301