Почему мой код печатает неправильный зашифрованный текст? - PullRequest
0 голосов
/ 14 мая 2019

Я пытаюсь создать программу, которая превращает строку в шифрование, опережая каждую букву на десять букв. https://gyazo.com/86f9d708c2f02cf2d70dbc1cd9fa9a06 Я делаю часть 2. Когда я ввожу "helloworld" что-то вроде 0x45, что-то появляется. Пожалуйста помоги! Это скоро!

Я пытался возиться с циклами for, но это не помогло.

#include <iostream>

using namespace std;

int main()
{
    //Input Message
    cout << "Enter a message" << endl;
    string message;
    getline(cin, message);

    //Convert Message to Numbers
    int numMess[message.length()];
    for (int i = 0; i<message.length(); i++) {
        numMess[i] = (int)message[i];
    }

    cout << numMess << endl;

    //Encrypt Number Message by adding ten to each one
    int encryptNumMess[message.length()];
    for (int a = 0; a < message.length(); a++){
        encryptNumMess[a] = numMess[a] + 10;
        if (encryptNumMess[a] > 122) {
            encryptNumMess[a] = 97;
        }
    }
    cout << encryptNumMess << endl;

    //Convert Encrypted Number Message to letters
    string encryption[message.length()];
    for (int b = 0; b<message.length(); b++) {
        encryption[b] = (char)encryptNumMess[b];
    }

    cout << encryption << endl;
    return 0;
}

Я ожидаю, когда я наберу "helloworld", конечный продукт будет "rovvygybvn"

Ответы [ 3 ]

2 голосов
/ 14 мая 2019

Если вы хотите удалить циклы, закодированные вручную, вы можете использовать алгоритмы STL, такие как std :: transform , чтобы выполнить это:

Но сначала нужно сделать несколько вещей:

Не используйте магические числа, такие как 122, 97 и т. Д. Вместо этого используйте фактические символьные константы, например a, b и т. Д. Однако, если мы предположим ASCII, где буквенные коды символов являются смежными, ваш конкретная программа может просто использовать постоянную строку для обозначения алфавита, а затем использовать простое индексирование для выделения символа.

const char *alphabet = "abcdefghijklmnopqrstuvwxyz";

Затем, чтобы получить букву a, для получения индекса достаточно простого вычитания:

char ch = 'b';
int index = ch - 'a'; // same as 'b' - 'a' == 98 - 97 == 1
std::cout << alphabet[index]; // will print 'b'

Учитывая это, следующее - выяснить, какой символ достигается, если вы добавите 10 к значению, а если больше 26, переходите к началу алфавита. Это можно сделать с помощью модуля (остаток после деления)

char ch = 'x';
int index = (ch - 'a' + 10) % 26; // Same as ('x' - 'a' + 10) % 26 == (120 - 97 + 10) % 26  == 33 % 26 == 7
std::cout << alphabet[index]; // will print 'h'

Следующее, что нужно сделать, это выяснить обратное, где для заданного зашифрованного символа вы должны найти незашифрованный символ, вычитая 10. Здесь это оборачивает противоположный путь, поэтому нужно выполнить немного больше работы (не показано, но пример кода отражает то, что сделано).

Собрав все это вместе и используя std::transform и лямбды, мы получим следующую маленькую программу:

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

int main()
{
    //Input Message
    const char *alphabet="abcdefghijklmnopqrstuvwxyz";
    std::string message = "helloworld";
    std::string result;

    // set the encrypted string using the formula above and std::transform
    std::transform(message.begin(), message.end(), std::back_inserter(result),
                  [&](char ch) { return alphabet[(ch - 'a' + 10) % 26]; });
    std::cout << "Encrypted: " << result << '\n';  

    // convert back to unencrypted using the above formula and std::transform
    std::string result2;
    std::transform(result.begin(), result.end(), std::back_inserter(result2),
                  [&](char ch) 
                  { int index = ch - 'a' - 10;  index = index < 0?26 - (abs(index) % 26):index % 26; return alphabet[index];});
    std::cout << "Unencrypted: " << result2;                  
}

Вывод:

 Encrypted: rovvygybvn
 Unencrypted: helloworld
1 голос
/ 14 мая 2019

Этот код работает для шифрования, если вы хотите расшифровать, вы должны изменить newAlphabet и oldAlphabet

Я комментирую в коде, что newAlphabet и oldAlphabet предназначены для шифрования и которыедля расшифровки

#include <windows.h>
#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;

int main()
{
    // For Encrypt
    string newAlphabet = "abcdefghijklmnopqrstuvwxyz";
    string oldAlphabet = "klmnopqrstuvwxyzabcdefghij";

    // For Decrypt
    //string newAlphabet = "klmnopqrstuvwxyzabcdefghij";
    //string oldAlphabet = "abcdefghijklmnopqrstuvwxyz";


    string input = "";
    string output = "";

    getline(cin, input);
    int inputLen = input.size();

    if (oldAlphabet.size() != newAlphabet.size())
        return false;

    for (int i = 0; i < inputLen; ++i)
    {
        int oldCharIndex = oldAlphabet.find(tolower(input[i]));

        if (oldCharIndex >= 0)
            output += isupper(input[i]) ? toupper(newAlphabet[oldCharIndex]) : newAlphabet[oldCharIndex];
        else
            output += input[i];
    }
    cout << output << endl;
    return 0;
}
0 голосов
/ 14 мая 2019

Как уже упоминалось, int numMess[message.length()]; недопустимо с ++. Если это работает для вас, вы используете расширение компилятора, на которое вы действительно не должны полагаться. Правильный путь будет:

std::vector <int> numMess(message.length());

Для получения дополнительной информации посмотрите std :: vector reference .

Далее int encryptNumMess[100]; создает массив стилей массива C. encryptNumMess - базовый указатель на массив. при попытке std::cout << encryptNumMess он выведет значение указателя, а НЕ массив. Для этого вам понадобится цикл for, например:

for(int i = 0; i < 100; ++i)
    std::cout << encryptNumMess[i] << " ";
std::cout << endl;

Выше также работает, когда вы конвертируете это в вектор, как мы сделали с numMess, тогда как в этом случае std::cout << encryptNumMess даже не скомпилируется.

В-третьих, string encryption[100] создает массив из 100 строк! Не строка размером 100. Для этого:

std::string foo(message.length(), '\0');

Мы должны указать, каким символом заполнять строку. Таким образом, нас '\0'. И теперь для вывода строки вы можете использовать std::cout << foo.

Наконец, так как арифметика разрешена на char, вся программа может быть сокращена до этой

#include <iostream>

int main()
{
    // Input Message
    std::cout << "Enter a message" << std::endl;
    std::string message, encryption;
    getline(std::cin, message);

    // Resize encryption string to the desired length
    encryption.resize(message.length());

    // Do the encryption
    for(size_t i = 0; i < message.length(); ++i) {
        encryption[i] = message[i] + 10;
        if (encryption[i] > 122) {
            encryption[i] = 97;
        }
    }

    // Output the string
    std::cout << encryption << std::endl;

    return 0;
}

Конечно, ваш алгоритм шифрования все еще не верен согласно инструкциям, но я оставлю это для вас, чтобы выяснить. Я считаю, что @PaulMcKenzie уже рассказал вам о том, как исправить это, а также не использовать магические числа.

...