Для назначения в классе я должен был написать функцию, которая помещает строку ввода пользователя через шифр Vigenere с дополнительной помощью вспомогательной функции. Мне удалось найти частичное решение, используя вспомогательную функцию, которая получает правильный сдвиг для символа на основе его места в алфавите, а также другую функцию, которая сдвигает символы в строке на это место, если они являются буквами.
Программа работает только с одним примером: «Привет, мир!» с ключевым словом «торт», должным образом зашифрованным в «Jevpq, Wyvnd!», однако ввод автогрейдерами «hDcT + T EtL5V71» и ключевое слово «vpkbncc» возвращает «cSmU + V OuY5Q71» вместо «cSmU +» G GvG5K71 ". Я знаю, почему это происходит; первый символ пропускается через каждую итерацию, поэтому «торт» в конечном итоге становится «ake», однако я понятия не имею, как это исправить. Вот мой код:
/*Author: Xavier f.*/
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int getShift(char c); // helper function that converts chars into their place in the alphabet as an int
char shiftChar(char c, int rshift); // this function handles the character value shifting part of the problem
string encryptVigenere(string plaintext, string keyword); //implemntation of Vigenere cypher , needs to loop around keyword
int main(){
string text, key, debug;
cout << "Enter a sentence: ";
getline(cin, text);
cout << "Enter the keyword : ";
getline(cin, key);
debug = encryptVigenere(text, key);
cout << "Ciphertext : " << debug;
return 0;
}
int getShift(char c) {
if (isupper(c)) {
return (int)c-(int)'A';
}
else {
return (int)c-(int)'a';
}
}
char shiftChar(char c, int rshift) {
char shifted;
if (isalpha(c)) { //if it is a letter
if (isupper(c)){
shifted = ((int)c + rshift - 'A')%26 + 'A'; //65-90 for uppercase , 97-122 for lowercase
}
else { //dont have to put condition since if its not uppercase its obviously lowercase
shifted = ((int)c + rshift - 'a')%26 + 'a';
}
return shifted;
}
else {
return c;
}
}
string encryptVigenere(string plaintext, string keyword){
char encrypted;
string vigenere;
int ciphercount = 0;
for(int i = 0; i < plaintext.length(); ++i) {
if(isalpha(plaintext[i])) {
encrypted = shiftChar(plaintext[i], getShift(keyword[ciphercount]));
vigenere += encrypted;
ciphercount ++;
}
else {
ciphercount -= keyword.length();
vigenere += plaintext[i];
}
ciphercount = ciphercount % keyword.length();
}
return vigenere;
}
Как я уже говорил, «Здравствуй, мир!» пример работает, хотя первый символ в торт по какой-то причине пропущен в цикле for:
Enter a sentence: Hello, world!
Enter the keyword : cake
Ciphertext : Jevpq, wyvnd!
debug: og ciphercount: c/ debug: plaintext[i]: H / debug: keyword[ciphercount]: a / debug: cyphercount isalpha: 1 / debug: encrypted: J / debug: vigenere: J
debug: cyphercount loop through: 1
Однако с участием автогрейдеров эта проблема становится более катастрофической:
Enter a sentence: hDcT+T EtL5V71
Enter the keyword : vpkbncc
Ciphertext : cSmU+V OuY5Q71
debug: og ciphercount: v / debug: plaintext[i]: h / debug: keyword[ciphercount]: p / debug: cyphercount isalpha: 1 / debug: encrypted: c / debug: vigenere: c
debug: cyphercount loop through: 1
Предполагается, что выводом будет «cSmU + G GvG5K71», но, поскольку первый символ сдвига пропущен, сдвиг, через который вводится текст, является pkbn_bn_c_p__, что неверно.
Кто-нибудь знает, как я могу исправить это?