2017-02-18 3 views
0

Редактирование: это известно как шифр Цезаря. Я пытался сделать программу, которая имела основную цель шифрования данной (короткой и строчной) строки. Это сделало бы, сдвинув все буквы n пробелов вправо (шифрование) или влево (декодирование).Шифрование заданной строки текста - Цезарный шифр

Вот что я написал до сих пор (под редакцией)

#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; 
} 

Теперь проблема я получаю ужасно строку, которую я даже не знаю, как она была создана. И есть одна ошибка.

This is the result

+1

Если не требуется использовать массивы символов, рекомендуется использовать 'зЬй :: string' и' зЬй :: rotate'. – user4581301

+2

'sizeof (cadena)' равно 1. 'i <= sizeof (cadena);' будет запускать 2 итерации. 'f <= 26' запустит 27 итераций – user4581301

+1

Похоже, вы пытаетесь сделать [Цезарский шифр] (https://en.wikipedia.org/wiki/Caesar_cipher). Можете ли вы подтвердить свою конечную цель? Я не думаю, что вам нужно что-то вращать. – user4581301

ответ

3

Давайте начнем с быстрой ходьбы через код.

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) 
{ 
    char cadena; 

Определяет одинокий символ. Мы увидим позже, что это не то, что вы хотите.

char * cadena_ptr = &cadena; 

В нормальных условиях, это хорошая идея, но с одним символом, не столь полезного

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

Вот где вещи начинают идти не так. Код просто читается одним и только одним символом из-за того, как был определен cadena.

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

Как упоминалось ранее cadena один символ, так i <= sizeof(cadena) такая же, как i <= 1. это приводит к 2 итерациям цикла. Один для i=0 (0<=1) и один для i=1 (1<=1). Это означает, что цикл будет выходить за пределы cadena с одного символа. Результаты этого не определены. Программа может потерпеть крах. Программа может перезаписывать и испортить данные около cadena. Программа может съесть кошку вашего соседа. Все было бы совершенно правильно, но первые два гораздо более вероятны, чем третья.

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

Это также проходит за пределами границ. Этот цикл также может и не понадобиться. В 2017 году очень маловероятно, что вы когда-либо увидите кодировку символов, которая не сохранит все символы в восходящем непрерывном блоке. Тем не менее, эта петля грубой силы исключает возможность использования кодировки старого или бизаро-символа, которая скремблирует порядок символов.

Я собираюсь придерживаться этой петли, потому что вопрос не касается арифметики ASCII.

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

Весь этот блок выглядит хорошо и должен работать после устранения проблем с индексацией. Однако есть одно улучшение. Как только вы найдете один матч, вы можете перестать искать больше. Также необходимо использовать , который следует заменить.

  } 
     } 

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

Очистка его стадия 1:

Закрепить офф одной индексации. Это довольно быстро:

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

Следующая чтение более чем один символ:

правильный путь! Используйте a std::string и 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"); 
} 

Я не собираюсь тратить свое время на неправильном пути. Это не правильно. Научитесь использовать std::string.

Если требования к проекту говорят, что нет std::string, не делайте это неправильно. Сделайте что-то совершенно другое! Прочитайте символы один за другим, преобразуйте их и распечатайте. Чтобы зашифровать, пока мы не найдем символ, который не может быть преобразован, мы могли бы сделать что-то вроде:

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

Клянусь богом. Я никогда бы не подумал, что такие удивительные люди способны населять Интернет. Большое спасибо! Я планировал использовать строку (я даже включил ее в заголовок), но когда вы говорите «мы нашли ее, перестаем смотреть», она действительно не выполняет свою работу. Я имею в виду, что строка текста имеет разные символы, которые имеют разные значения и, в свою очередь, разные новые значения, поэтому я не совсем понимаю вашу мысль ... Я буду редактировать программу утром и расскажу вам об этом больше. Благодаря!! – Zashuiba

+0

@ Zashuiba Есть две петли. Внешний цикл проходит через все символы в строке. Ты прав. Вы хотите, чтобы это продолжалось. Внутренний цикл проверяет символ 'ch' из внешнего цикла на каждый символ в' abc'. В 'abc' нет повторений, поэтому, как только' ch' соответствует элементу 'abc', нет необходимости проверять' ch' на 'abc'. [Оператор 'break'] (http://en.cppreference.com/w/cpp/language/break) выходит из внутреннего цикла раньше, но не внешнего цикла. – user4581301

+0

Другое примечание. Поскольку 'abc' красиво упорядочен, вы можете [использовать' std :: find' для выполнения высокоскоростного поиска для вас] (http://en.cppreference.com/w/cpp/algorithm/find). – user4581301

Смежные вопросы