【问题标题】:How can I replace multiple letters at the same time for Caesar cipher?如何为凯撒密码同时替换多个字母?
【发布时间】:2018-12-19 10:55:33
【问题描述】:

我目前正在开发一个程序,该程序通过用自定义预设字母替换特定字母来加密(使用凯撒密码)用户输入字符串。例如 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”。几乎每个字母都会发生这种情况,然后我得到一个加密文本,我永远无法解密。

有什么办法可以同时替换所有的字母,或者你会推荐我使用其他功能吗?

【问题讨论】:

  • 字母之间是否存在循环映射?如果没有,那么您可以按转换顺序绘制所有字母,然后按倒序进行替换。但是看起来整个映射是一个圆圈。
  • 使用StringBuilder.Replace,而不是String.Replace。它在 StringBuilder 的缓冲区中进行替换。 String.Replace 在每个操作上创建一个新字符串(因为字符串是不可变的)。
  • bing.com/… 将为您提供更多版本的代码供您查看...
  • 你在替换的两边都有P而不是W,那不好。

标签: c# encryption replace caesar-cipher


【解决方案1】:

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

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】:

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

    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&lt;string, string&gt; - 可以反向搜索。您可以使用List&lt;T&gt;

     class ED 
     {
         public Char Enc {get; set;}
         public Char Dec {get; set;}
     }
     var list = new List<ED>();
    

    现在您可以更清楚地进行加密/解密。 用于加密list.First(c =&gt; c.Enc.Equals(inputChar)) 和用于解密list.First(c =&gt; c.Dec.Equals(inputChar))

    【讨论】:

    • 不能使用char 作为字符串到字符串字典的键。
    • @Xiaoy312 确定 - 这是伪代码。只是你不为每个 replace 创建新字符串而是构建你的新字符串的想法
    • 这是一种非常有效的方法 - 您只传递一次字符串,每次迭代只需支付字典查找费用。
    【解决方案3】:

    我会在外面帮助你,了解它的工作原理是 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()

    【讨论】:

      【解决方案4】:

      如果您想保留已实施的简单替换策略,而不是进行 @T.S. 的字典混淆。演示,您可以执行以下操作,您的地图有 3 个不同的组需要这种处理,因此需要留白。

      1. 按连接对地图进行排序
      2. 通过将 1 映射到外部值来打破任何循环
      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");
      

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-02-08
          • 1970-01-01
          • 1970-01-01
          • 2011-07-11
          • 1970-01-01
          • 1970-01-01
          • 2014-04-11
          • 1970-01-01
          相关资源
          最近更新 更多