凯撒密码:如何计算移位值> 10(或更大)?
Caesar cipher : how to calculate with shifting value > 10 ( or larger )?
据我所知,凯撒移位的“公式”是(x + k ) % 26,其中k是移位值,解密只是将“+”替换为“-”。
但是我的代码在k > 10时不起作用(我测试了 k = 10 后发现前几个字符的 "shift" 是错误的,所以我估计 k > 10 会出错(错误字符的数量也会增加)。)。我首先将字符更改为 ASCII,然后进行计算。最后改回字符。
这是我的代码。
#include <iostream>
#include <string>
using namespace std;
int main() {
string target;
char s;
int k, i, num, length, j;
cin >> s >> k;
getline(cin, target);
for (j = 0; j <= (int)target.length(); j++) {
if ((target[j]) = ' ') {
target.erase(j, 1);
}
}
length = (int)target.length();
if (s == 'e') {
for (num = 0; num <= length; num++) {
if (isupper(target[num]))
target[num] = tolower(char(int(target[num] + k - 65) % 26 + 65));
else if (islower(target[num]))
target[num] = toupper(char(int(target[num] + k - 97) % 26 + 97));
}
}
else if (s == 'd') {
for (num = 0; num <= length; num++) {
if (isupper(target[num]))
target[num] = tolower(char(int(target[num] - k - 65) % 26 + 65));
else if (islower(target[num]))
target[num] = toupper(char(int(target[num] - k - 97) % 26 + 97));
}
}
cout << target;
return 0;
}
让我放下我失败的案例运行。
输入:
d 10 n 3 V 3 D 3 N _ M Y N 3 _ S C _ N 3 L E
(先输入d/e,然后移位值,最后字符串序列要求“改变”,space需要删除。)
预期输出:
D3l3t3d_cod3_is_d3bu
我的输出:
D3l3:3d_cod3_i9_d3b;
谢谢!
你的问题是解码时你得到的是负数。对于 k == 13
,表达式 'T' - k - 65
给出 -7
。 -7 % 26
仍然是 -7
。 -7+65
是 58
这不是一个字母。
你可以通过在解码时简单地将k设置为26 - k
来避免负数。
您的代码将简化为:
if (s == 'd') {
k = 26 - k;
}
for (num = 0; num <= length; num++) {
if (isupper(target[num]))
target[num] = tolower(char(int(target[num] + k - 'A') % 26 + 'A'));
else if (islower(target[num]))
target[num] = toupper(char(int(target[num] + k - 'a') % 26 + 'a'));
}
请注意,我已将您的整数常量替换为它们的等效字符,这使得代码更容易理解。
请注意,您的第一个循环中也有一个错误 (target[j]) = ' '
应该是 (target[j]) == ' '
.
使用所有 c++ 必须提供的功能,您可以将代码减少到:
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string target = "mXLM";
char s = 'e';
int k = 7;
target.erase(std::remove(target.begin(), target.end(), ' '), target.end());
if (s == 'd') {
k = 26 - k;
}
std::string result;
std::transform(target.begin(), target.end(), std::back_inserter(result), [k](char in) {
if (isalpha(in)) {
char inputOffset = isupper(in) ? 'A' : 'a';
char outputOffset = isupper(in) ? 'a' : 'A';
return char(int(in + k - inputOffset) % 26 + outputOffset);
}
return in;
});
std::cout << result;
return 0;
}
据我所知,凯撒移位的“公式”是(x + k ) % 26,其中k是移位值,解密只是将“+”替换为“-”。
但是我的代码在k > 10时不起作用(我测试了 k = 10 后发现前几个字符的 "shift" 是错误的,所以我估计 k > 10 会出错(错误字符的数量也会增加)。)。我首先将字符更改为 ASCII,然后进行计算。最后改回字符。
这是我的代码。
#include <iostream>
#include <string>
using namespace std;
int main() {
string target;
char s;
int k, i, num, length, j;
cin >> s >> k;
getline(cin, target);
for (j = 0; j <= (int)target.length(); j++) {
if ((target[j]) = ' ') {
target.erase(j, 1);
}
}
length = (int)target.length();
if (s == 'e') {
for (num = 0; num <= length; num++) {
if (isupper(target[num]))
target[num] = tolower(char(int(target[num] + k - 65) % 26 + 65));
else if (islower(target[num]))
target[num] = toupper(char(int(target[num] + k - 97) % 26 + 97));
}
}
else if (s == 'd') {
for (num = 0; num <= length; num++) {
if (isupper(target[num]))
target[num] = tolower(char(int(target[num] - k - 65) % 26 + 65));
else if (islower(target[num]))
target[num] = toupper(char(int(target[num] - k - 97) % 26 + 97));
}
}
cout << target;
return 0;
}
让我放下我失败的案例运行。
输入:
d 10 n 3 V 3 D 3 N _ M Y N 3 _ S C _ N 3 L E
(先输入d/e,然后移位值,最后字符串序列要求“改变”,space需要删除。)
预期输出:
D3l3t3d_cod3_is_d3bu
我的输出:
D3l3:3d_cod3_i9_d3b;
谢谢!
你的问题是解码时你得到的是负数。对于 k == 13
,表达式 'T' - k - 65
给出 -7
。 -7 % 26
仍然是 -7
。 -7+65
是 58
这不是一个字母。
你可以通过在解码时简单地将k设置为26 - k
来避免负数。
您的代码将简化为:
if (s == 'd') {
k = 26 - k;
}
for (num = 0; num <= length; num++) {
if (isupper(target[num]))
target[num] = tolower(char(int(target[num] + k - 'A') % 26 + 'A'));
else if (islower(target[num]))
target[num] = toupper(char(int(target[num] + k - 'a') % 26 + 'a'));
}
请注意,我已将您的整数常量替换为它们的等效字符,这使得代码更容易理解。
请注意,您的第一个循环中也有一个错误 (target[j]) = ' '
应该是 (target[j]) == ' '
.
使用所有 c++ 必须提供的功能,您可以将代码减少到:
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string target = "mXLM";
char s = 'e';
int k = 7;
target.erase(std::remove(target.begin(), target.end(), ' '), target.end());
if (s == 'd') {
k = 26 - k;
}
std::string result;
std::transform(target.begin(), target.end(), std::back_inserter(result), [k](char in) {
if (isalpha(in)) {
char inputOffset = isupper(in) ? 'A' : 'a';
char outputOffset = isupper(in) ? 'a' : 'A';
return char(int(in + k - inputOffset) % 26 + outputOffset);
}
return in;
});
std::cout << result;
return 0;
}