用于 vigenere 密码的 C++ 函数仅有时有效(适用于某些输入,跳过其他输入)
C++ function for vigenere cipher only sometimes working (works for some inputs, skips shifts for others)
对于 class 中的作业,我必须编写一个函数,在辅助函数的可选帮助下,通过 vigenere 密码输入用户输入的字符串。我能够使用一个辅助函数获得部分解决方案,该函数根据字符在字母表中的位置获得正确的字符移位,以及另一个函数,如果它们是字母,则将字符串中的字符移位到这个位置。
该程序偶尔会使用一个示例 "Hello, world!",关键字 "cake" 被正确加密为 "Jevpq, Wyvnd!",但是自动评分器的输入 "hDcT+T EtL5V71" 和关键字 "vpkbncc" returns "cSmU+V OuY5Q71" 而不是 "cSmU+G GvG5K71"。我知道为什么会这样;每次迭代都会跳过第一个字符,因此 "cake" 最终成为 "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;
}
就像我之前提到的,即使 cake 中的第一个字符由于某种原因在 for 循环中被跳过,"Hello, world!" 示例仍然有效:
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__,这是错误的。
有人知道我该如何解决这个问题吗?
这里的问题不是关键字的第一个字母被忽略(尝试 fake
而不是 cake
并确认它确实改变了输出)。
看来您真正的问题在于 encryptVigenere
函数的编写方式。
我不是密码学专家,我不能告诉你这是否是实现 vigenere 密码的正确方法,但我无法理解这一行:
ciphercount -= keyword.length();
事实证明,如果删除它,您将获得想要的结果。
那么,这是您的新 encryptVigenere
函数:
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;
}
对于 class 中的作业,我必须编写一个函数,在辅助函数的可选帮助下,通过 vigenere 密码输入用户输入的字符串。我能够使用一个辅助函数获得部分解决方案,该函数根据字符在字母表中的位置获得正确的字符移位,以及另一个函数,如果它们是字母,则将字符串中的字符移位到这个位置。
该程序偶尔会使用一个示例 "Hello, world!",关键字 "cake" 被正确加密为 "Jevpq, Wyvnd!",但是自动评分器的输入 "hDcT+T EtL5V71" 和关键字 "vpkbncc" returns "cSmU+V OuY5Q71" 而不是 "cSmU+G GvG5K71"。我知道为什么会这样;每次迭代都会跳过第一个字符,因此 "cake" 最终成为 "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;
}
就像我之前提到的,即使 cake 中的第一个字符由于某种原因在 for 循环中被跳过,"Hello, world!" 示例仍然有效:
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__,这是错误的。
有人知道我该如何解决这个问题吗?
这里的问题不是关键字的第一个字母被忽略(尝试 fake
而不是 cake
并确认它确实改变了输出)。
看来您真正的问题在于 encryptVigenere
函数的编写方式。
我不是密码学专家,我不能告诉你这是否是实现 vigenere 密码的正确方法,但我无法理解这一行:
ciphercount -= keyword.length();
事实证明,如果删除它,您将获得想要的结果。
那么,这是您的新 encryptVigenere
函数:
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;
}