凯撒密码如何同时替换多个字母?
How can I replace multiple letters at the same time for Caesar cipher?
我目前正在开发一个程序,通过用自定义预设字母替换特定字母来加密(使用凯撒密码)用户输入的字符串。例如A = R, B = T, C = O等
当前节目:
using System;
class Program
{
static void Main(string[] args)
{
String decryptedInput = Console.ReadLine().ToUpper();
String encryptedOutput = decryptedInput.Replace("A", "R")
.Replace("B", "B")
.Replace("C", "T")
.Replace("D", "O")
.Replace("E", "P")
.Replace("F", "M")
.Replace("G", "Z")
.Replace("H", "S")
.Replace("I", "J")
.Replace("J", "K")
.Replace("K", "I")
.Replace("L", "Y")
.Replace("M", "P")
.Replace("N", "G")
.Replace("O", "L")
.Replace("P", "V")
.Replace("Q", "C")
.Replace("R", "X")
.Replace("S", "N")
.Replace("T", "E")
.Replace("U", "H")
.Replace("V", "F")
.Replace("P", "A")
.Replace("X", "U")
.Replace("Y", "Q")
.Replace("Z", "D");
Console.WriteLine(encryptedOutput);
Console.ReadKey();
}
}
我确实得到了输出,但是有一些加密错误。问题是,由于代码行 运行 一个接一个,已经转换的字母会再次转换。
例如:字母"A"是encrypted/converted到"R"。当程序到达字母 "R" 时,该字母再次为 encrypted/converted 并最终变为 "X",稍后在代码中将其转换为 "U"。几乎每个字母都会发生这种情况,然后我得到一个我永远无法解密的加密文本。
有什么办法可以同时替换所有的字母,或者你会推荐我使用另一个函数吗?
此处是您想要执行的操作的最简单表示
var dict = new Dictionary<Char, Char>();
// load dictionary here
var original = "ABC";
var newOne = new StringBuilder();
foreach (var c in original)
newOne.Append(dict[c]);
return newOne.ToString();
这是伪代码。但这很简单,你可以理解你需要构建新的字符串,因为字符串是不可变的
我发了Dictionary<string, string>
- 可以反向搜索。您可以使用 List<T>
。
class ED
{
public Char Enc {get; set;}
public Char Dec {get; set;}
}
var list = new List<ED>();
当你 encrypt/decrypt 时,你会更清楚。
对于加密做 list.First(c => c.Enc.Equals(inputChar))
和解密 list.First(c => c.Dec.Equals(inputChar))
我会在外面帮助你,了解它是如何工作的是对 Linq 和库的其他部分的一个很好的练习。
static void Main(string[] args)
{
string decryptedInput = "Hello World!";
string encryptedOutput = new string(decryptedInput.Select(EncryptChar).ToArray());
Console.WriteLine(encryptedOutput);
}
private static char EncryptChar(char arg)
{
return arg;
}
您的问题现在减少为编写更好的 EncryptChar()
如果你想保持你已经实现的简单替换策略,而不是做@T.S 的字典混淆。演示后,您可以执行以下操作,您的地图有 3 个不同的组需要这种处理,因此需要空白。
- 按连接对地图进行排序
- 通过将一个循环映射到外部值来打破任何循环
- 向后处理您的地图
- 将步骤 2 设置为更正值
代码:
var encryptedOutput = decryptedInput
.Replace("A", "AA")
.Replace("P", "A")
.Replace("M", "P")
.Replace("F", "M")
.Replace("V", "F")
.Replace("P", "V")
.Replace("E", "P")
.Replace("T", "E")
.Replace("C", "T")
.Replace("Q", "C")
.Replace("Y", "Q")
.Replace("L", "Y")
.Replace("O", "L")
.Replace("D", "O")
.Replace("Z", "D")
.Replace("G", "Z")
.Replace("N", "G")
.Replace("S", "N")
.Replace("H", "S")
.Replace("U", "H")
.Replace("X", "U")
.Replace("R", "X")
.Replace("AA", "R")
.Replace("B", "B")
.Replace("I", "II")
.Replace("K", "I")
.Replace("J", "K")
.Replace("II", "J");
我会使用 Dictionary
和 linq 来做到这一点。请注意,不在字典中的任何字符(数字、空格、符号)都不会被转换。当我针对 Dictionary
执行查找时,请注意我如何将输出 char
设置为 foreach 的当前 char
值。此外,由于这是区分大小写的,因此我必须将字符串转换为大写。
public class Program
{
public static void Main(string[] args)
{
string encryptedOutput = "";
var decryptedInput = "this is a test string";
Dictionary<char,char> cipherTable =
new Dictionary<char,char>{
{'A', 'R'},
{'B', 'B'},
{'C', 'T'},
{'D', 'O'},
{'E', 'P'},
{'F', 'M'},
{'G', 'Z'},
{'H', 'S'},
{'I', 'J'},
{'J', 'K'},
{'K', 'I'},
{'L', 'Y'},
{'M', 'P'},
{'N', 'G'},
{'O', 'L'},
{'P', 'V'},
{'Q', 'C'},
{'R', 'X'},
{'S', 'N'},
{'T', 'E'},
{'U', 'H'},
{'V', 'F'},
{'W', 'A'},
{'X', 'U'},
{'Y', 'Q'},
{'Z', 'D'}
};
encryptedOutput = string.Join("",decryptedInput
.ToUpper()
.ToArray()
.Select(c => {char outChar = c; cipherTable.TryGetValue(c, out outChar); return outChar;}));
Console.WriteLine(encryptedOutput);
}
}
就像其他人提到的那样,您替换了一些字符的倍数。这可能不是期望的行为:
eg: A -> R -> X -> U
此外,这些行似乎有错别字:
.Replace("V", "F")
.Replace("P", "A") // should this be W->A ?
.Replace("X", "U")
所有这些都可能导致了您的问题。
为了防止这种情况,只需要单传替换字符串:
// build up character mappings for decryption
const string EncryptedLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string DecryptedLetters = "RBTOPMZSJKIYPGLVCXNEHFAUQD";
var decryptionMapping = EncryptedLetters.Zip(DecryptedLetters, Tuple.Create)
.ToDictionary(x => x.Item1, x => x.Item2);
// decrypt the message
var encryptedMessage = "CTHC";
var decryptedMessage = encryptedMessage
.Select(x => decryptionMapping[x])
.Aggregate(new StringBuilder(), (sb, x) => sb.Append(x), sb => sb.ToString());
我目前正在开发一个程序,通过用自定义预设字母替换特定字母来加密(使用凯撒密码)用户输入的字符串。例如A = R, B = T, C = O等
当前节目:
using System;
class Program
{
static void Main(string[] args)
{
String decryptedInput = Console.ReadLine().ToUpper();
String encryptedOutput = decryptedInput.Replace("A", "R")
.Replace("B", "B")
.Replace("C", "T")
.Replace("D", "O")
.Replace("E", "P")
.Replace("F", "M")
.Replace("G", "Z")
.Replace("H", "S")
.Replace("I", "J")
.Replace("J", "K")
.Replace("K", "I")
.Replace("L", "Y")
.Replace("M", "P")
.Replace("N", "G")
.Replace("O", "L")
.Replace("P", "V")
.Replace("Q", "C")
.Replace("R", "X")
.Replace("S", "N")
.Replace("T", "E")
.Replace("U", "H")
.Replace("V", "F")
.Replace("P", "A")
.Replace("X", "U")
.Replace("Y", "Q")
.Replace("Z", "D");
Console.WriteLine(encryptedOutput);
Console.ReadKey();
}
}
我确实得到了输出,但是有一些加密错误。问题是,由于代码行 运行 一个接一个,已经转换的字母会再次转换。
例如:字母"A"是encrypted/converted到"R"。当程序到达字母 "R" 时,该字母再次为 encrypted/converted 并最终变为 "X",稍后在代码中将其转换为 "U"。几乎每个字母都会发生这种情况,然后我得到一个我永远无法解密的加密文本。
有什么办法可以同时替换所有的字母,或者你会推荐我使用另一个函数吗?
此处是您想要执行的操作的最简单表示
var dict = new Dictionary<Char, Char>();
// load dictionary here
var original = "ABC";
var newOne = new StringBuilder();
foreach (var c in original)
newOne.Append(dict[c]);
return newOne.ToString();
这是伪代码。但这很简单,你可以理解你需要构建新的字符串,因为字符串是不可变的
我发了Dictionary<string, string>
- 可以反向搜索。您可以使用 List<T>
。
class ED
{
public Char Enc {get; set;}
public Char Dec {get; set;}
}
var list = new List<ED>();
当你 encrypt/decrypt 时,你会更清楚。
对于加密做 list.First(c => c.Enc.Equals(inputChar))
和解密 list.First(c => c.Dec.Equals(inputChar))
我会在外面帮助你,了解它是如何工作的是对 Linq 和库的其他部分的一个很好的练习。
static void Main(string[] args)
{
string decryptedInput = "Hello World!";
string encryptedOutput = new string(decryptedInput.Select(EncryptChar).ToArray());
Console.WriteLine(encryptedOutput);
}
private static char EncryptChar(char arg)
{
return arg;
}
您的问题现在减少为编写更好的 EncryptChar()
如果你想保持你已经实现的简单替换策略,而不是做@T.S 的字典混淆。演示后,您可以执行以下操作,您的地图有 3 个不同的组需要这种处理,因此需要空白。
- 按连接对地图进行排序
- 通过将一个循环映射到外部值来打破任何循环
- 向后处理您的地图
- 将步骤 2 设置为更正值
代码:
var encryptedOutput = decryptedInput
.Replace("A", "AA")
.Replace("P", "A")
.Replace("M", "P")
.Replace("F", "M")
.Replace("V", "F")
.Replace("P", "V")
.Replace("E", "P")
.Replace("T", "E")
.Replace("C", "T")
.Replace("Q", "C")
.Replace("Y", "Q")
.Replace("L", "Y")
.Replace("O", "L")
.Replace("D", "O")
.Replace("Z", "D")
.Replace("G", "Z")
.Replace("N", "G")
.Replace("S", "N")
.Replace("H", "S")
.Replace("U", "H")
.Replace("X", "U")
.Replace("R", "X")
.Replace("AA", "R")
.Replace("B", "B")
.Replace("I", "II")
.Replace("K", "I")
.Replace("J", "K")
.Replace("II", "J");
我会使用 Dictionary
和 linq 来做到这一点。请注意,不在字典中的任何字符(数字、空格、符号)都不会被转换。当我针对 Dictionary
执行查找时,请注意我如何将输出 char
设置为 foreach 的当前 char
值。此外,由于这是区分大小写的,因此我必须将字符串转换为大写。
public class Program
{
public static void Main(string[] args)
{
string encryptedOutput = "";
var decryptedInput = "this is a test string";
Dictionary<char,char> cipherTable =
new Dictionary<char,char>{
{'A', 'R'},
{'B', 'B'},
{'C', 'T'},
{'D', 'O'},
{'E', 'P'},
{'F', 'M'},
{'G', 'Z'},
{'H', 'S'},
{'I', 'J'},
{'J', 'K'},
{'K', 'I'},
{'L', 'Y'},
{'M', 'P'},
{'N', 'G'},
{'O', 'L'},
{'P', 'V'},
{'Q', 'C'},
{'R', 'X'},
{'S', 'N'},
{'T', 'E'},
{'U', 'H'},
{'V', 'F'},
{'W', 'A'},
{'X', 'U'},
{'Y', 'Q'},
{'Z', 'D'}
};
encryptedOutput = string.Join("",decryptedInput
.ToUpper()
.ToArray()
.Select(c => {char outChar = c; cipherTable.TryGetValue(c, out outChar); return outChar;}));
Console.WriteLine(encryptedOutput);
}
}
就像其他人提到的那样,您替换了一些字符的倍数。这可能不是期望的行为:
eg: A -> R -> X -> U
此外,这些行似乎有错别字:
.Replace("V", "F") .Replace("P", "A") // should this be W->A ? .Replace("X", "U")
所有这些都可能导致了您的问题。
为了防止这种情况,只需要单传替换字符串:
// build up character mappings for decryption
const string EncryptedLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string DecryptedLetters = "RBTOPMZSJKIYPGLVCXNEHFAUQD";
var decryptionMapping = EncryptedLetters.Zip(DecryptedLetters, Tuple.Create)
.ToDictionary(x => x.Item1, x => x.Item2);
// decrypt the message
var encryptedMessage = "CTHC";
var decryptedMessage = encryptedMessage
.Select(x => decryptionMapping[x])
.Aggregate(new StringBuilder(), (sb, x) => sb.Append(x), sb => sb.ToString());