为什么我的字符串在凯撒密码期间发生变化?
Why my string change during a Caesar Cipher?
我制作凯撒密码是为了娱乐和训练。我在测试中发现 "strange" 行为。
最后两行return一个错误。他们不是 "ok"。我不知道我哪里错了。
您可以在 dotnetfiddle 上试用我的完整代码。
输出
0000 RandomUtil.GetRandomString(); // ? RandomUtil.GetRandomString(); // ? RandomUtil.GetRandomString(); // ? ok
0001 SboepnVujm.HfuSboepnTusjoh(); // ? RandomUtil.GetRandomString(); // ? RandomUtil.GetRandomString(); // ? ok
[...]
0030 VerhsqYxmp.KixVerhsqWxvmrk(); // ? RandomUtil.GetRandomString(); // ? RandomUtil.GetRandomString(); // ? ok
0031 WfsitrZynq.LjyWfsitrXywnsl(); // ? RandomUtil.GetRandomString(); // ? RandomUtil.GetRandomString(); // ? ok
0032 Xgtjus[zor.MkzXgtjusYzxotm(); // ? Random[til.GetRandomString(); // ? RandomUtil.GetRandomString(); // ? ko
0033 Yhukvt\{ps.Nl{YhukvtZ{ypun(); // ? Random\{il.Ge{RandomS{ring(); // ? RandomUtil.GetRandomString(); // ? ko
ok 32
ko 2
测试
public static void Main()
{
int okCounter = 0;
const string str = "RandomUtil.GetRandomString(); // ?";
int iter = str.Length;
for (int i = 0; i < iter; i++)
{
var e = CaesarCipher.Encrypt(str, i);
var d = CaesarCipher.Decrypt(e, i);
Console.WriteLine("{0:D4} {1} {2} {3} {4}", i, e, d, str, str == d ? "ok" : "ko");
if (str == d)
okCounter++;
}
Console.WriteLine("ok " + okCounter);
Console.WriteLine("ko " + (iter - okCounter));
}
凯撒密码Class
public static string Encrypt(string input, int code)
{
return RunCipher(input, code);
}
public static string Decrypt(string input, int code)
{
return RunCipher(input, -code);
}
private static string RunCipher(string letters, int shift)
{
return new String(MoveLetters(letters, shift).ToArray());
}
private static IEnumerable<char> MoveLetters(string letters, int shift)
{
return
from letter in letters
let l = (char)(letter + shift)
let diffCase = Char.IsLower(letter) ? 0 : 32
let max = 'z' - diffCase
let min = 'a' - diffCase
let isAsciiLetter = letter >= min && letter <= max
select isAsciiLetter ? (char)(l > max ? l - 26 : l < min ? l + 26 : l) : letter;
}
在 MoveLetter() 中你有行
let l = (char)(letter + shift)
移出字母表字符代码范围,当 shift > 26
所以你至少需要把它改成
let l = (char)(letter + shift%26)
或在您的代码中添加检查以避免 shift <= 0 和 shift >= 26,因为它们在凯撒密码中没有多大意义
我制作凯撒密码是为了娱乐和训练。我在测试中发现 "strange" 行为。
最后两行return一个错误。他们不是 "ok"。我不知道我哪里错了。
您可以在 dotnetfiddle 上试用我的完整代码。
输出
0000 RandomUtil.GetRandomString(); // ? RandomUtil.GetRandomString(); // ? RandomUtil.GetRandomString(); // ? ok
0001 SboepnVujm.HfuSboepnTusjoh(); // ? RandomUtil.GetRandomString(); // ? RandomUtil.GetRandomString(); // ? ok
[...]
0030 VerhsqYxmp.KixVerhsqWxvmrk(); // ? RandomUtil.GetRandomString(); // ? RandomUtil.GetRandomString(); // ? ok
0031 WfsitrZynq.LjyWfsitrXywnsl(); // ? RandomUtil.GetRandomString(); // ? RandomUtil.GetRandomString(); // ? ok
0032 Xgtjus[zor.MkzXgtjusYzxotm(); // ? Random[til.GetRandomString(); // ? RandomUtil.GetRandomString(); // ? ko
0033 Yhukvt\{ps.Nl{YhukvtZ{ypun(); // ? Random\{il.Ge{RandomS{ring(); // ? RandomUtil.GetRandomString(); // ? ko
ok 32
ko 2
测试
public static void Main()
{
int okCounter = 0;
const string str = "RandomUtil.GetRandomString(); // ?";
int iter = str.Length;
for (int i = 0; i < iter; i++)
{
var e = CaesarCipher.Encrypt(str, i);
var d = CaesarCipher.Decrypt(e, i);
Console.WriteLine("{0:D4} {1} {2} {3} {4}", i, e, d, str, str == d ? "ok" : "ko");
if (str == d)
okCounter++;
}
Console.WriteLine("ok " + okCounter);
Console.WriteLine("ko " + (iter - okCounter));
}
凯撒密码Class
public static string Encrypt(string input, int code)
{
return RunCipher(input, code);
}
public static string Decrypt(string input, int code)
{
return RunCipher(input, -code);
}
private static string RunCipher(string letters, int shift)
{
return new String(MoveLetters(letters, shift).ToArray());
}
private static IEnumerable<char> MoveLetters(string letters, int shift)
{
return
from letter in letters
let l = (char)(letter + shift)
let diffCase = Char.IsLower(letter) ? 0 : 32
let max = 'z' - diffCase
let min = 'a' - diffCase
let isAsciiLetter = letter >= min && letter <= max
select isAsciiLetter ? (char)(l > max ? l - 26 : l < min ? l + 26 : l) : letter;
}
在 MoveLetter() 中你有行
let l = (char)(letter + shift)
移出字母表字符代码范围,当 shift > 26
所以你至少需要把它改成
let l = (char)(letter + shift%26)
或在您的代码中添加检查以避免 shift <= 0 和 shift >= 26,因为它们在凯撒密码中没有多大意义