Изменить: это известно как шифр Цезаря.
Я пытался создать программу, основной целью которой было шифрование заданной (короткой и строчной) строки. Это будет сделано путем сдвига всех букв 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;
}
Теперь проблема в том, что я получаю ужасную строку, которую я даже не знаю, как она образовалась. И есть еще одна ошибка.
Давайте начнем с быстрой прогулки по коду.
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 году очень маловероятно, что вы когда-либо увидите кодировку символов, которая не хранит все символы в восходящем непрерывном блоке. Тем не менее, этот цикл грубой силы исключает возможность столкновения с устаревшей кодировкой или символом Bizzaro, который шифрует порядок символов.
Я собираюсь придерживаться этого цикла, потому что вопрос на самом деле не об арифметике ASCII.
{
if (*cadena_ptr == abc[f])
{
int w;
w = f + n;
if (w >= 26)
{
w -= 26;
}
*cadena_ptr = abc[w];
Весь этот блок выглядит хорошо и должен работать, как только будут решены проблемы с индексацией. Однако есть одно улучшение. Как только вы нашли один матч, вы можете перестать искать больше. Также много использования магическое число 26 это должно быть заменено.
}
}
}
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!
Следующее чтение более чем в одном символе:
Правильный путь! использование std::string
и Диапазон на основе for
петля
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");
}
Других решений пока нет …