如何同时为Caesar密码替换多个字母?

时间:2018-12-18 22:50:53

标签: c# encryption replace caesar-cipher

我目前正在开发一个程序,该程序通过使用自定义预设字母替换特定字母来加密(使用Caesar密码)用户输入字符串。例如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”被加密/转换为“ R”。当程序到达字母“ R”时,该字母再次被加密/转换并最终变为“ X”,随后在代码中转换为“ U”。几乎每个字母都会发生这种情况,然后我得到的是加密文本,我永远无法解密。

是否可以同时替换所有字母,或者您只是推荐我使用其他功能?

5 个答案:

答案 0 :(得分:2)

您想要做的最简单的表示是这里

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>();

现在,在加密/解密时,您将变得更加清晰。 对于加密,请list.First(c => c.Enc.Equals(inputChar)),对于解密list.First(c => c.Dec.Equals(inputChar))

答案 1 :(得分:2)

就像其他人提到的那样,您替换了一些字符倍数时间。这可能不是预期的行为:

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());

答案 2 :(得分:1)

我将在外部帮助您,找出它的工作方式是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()

答案 3 :(得分:0)

如果要保持已实现的简单替换策略,而不要对@ T.S进行字典混淆。演示,您可以执行以下操作,您的地图上有3个不同的组需要进行此处理,因此需要白色间距。

  1. 通过连接对地图进行排序
  2. 通过将一个映射到一个外部值来中断任何循环
  3. 向后处理地图
  4. 将步骤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");

答案 4 :(得分:0)

我将使用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);

    }
}