As i know , the " formula " of Caesar Shifting is (x + k ) % 26 , where k is the shifting value and decryption just replace " + " to " - ".
but my code does not work when k > 10 (after i tested k = 10 , i find that the "shift" of the first few characters is wrong, so I estimate that k > 10 will be wrong (the number of incorrect characters increase) as well. ). I first change the characters to ASCII and then do the calculation. Finally change it back to characters.
Here are my code.
#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;
}
Let me put down the case which i failed to run.
input:
d 10 n 3 V 3 D 3 N _ M Y N 3 _ S C _ N 3 L E
( input d / e first, then shifting value, finally the sequence of string require to " change ", the space is required to delete. )
the expected output:
D3l3t3d_cod3_is_d3bu
my output:
D3l3:3d_cod3_i9_d3b;
Thanks!
Your issue is that when decoding you end up with negative numbers. With k == 13
the expression 'T' - k - 65
gives -7
. -7 % 26
is still -7
. -7+65
is 58
which isn't a letter.
You can avoid negative numbers by simply setting k to 26 - k
when decoding.
Your code then simplifies to:
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'));
}
Note I've replaced your integer constants with their equivalent characters which makes the code much easier to understand.
Note you also have a bug in your first loop (target[j]) = ' '
should be (target[j]) == ' '
.
Using all c++ has to offer you can reduce your code to:
#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;
}