Caesar Cipher C# - 如何处理大写和小写字母

Caesar Cipher C# - How to work with uppercase and lowercase letters

我正在创建一个 Caesar Cipher,我正在尝试弄清楚如何让它同时处理大写和小写字母。例如,如果我输入 "Hello World",我希望它以相同的格式加密,“Ifmmp Xpsme。

using System;

namespace CaesarCipher1
{
    class Program
    {
        static string Encrypt(string value, int shift)
        {
            shift %= 26;
            char[] alphabet = value.ToCharArray();
            for (int i = 0; i < alphabet.Length; i++)
            {
                char letter = alphabet[i];
                if (letter == ' ')
                    continue;

                letter = (char)(letter + shift);
                if (letter > 'z')
                {
                    letter = (char)(letter - 26);
                }
                else if (letter < 'a')
                {
                    letter = (char)(letter + 26);
                }

                // Store.
                alphabet[i] = letter;
            }
            return new string(alphabet);
        }
        static string Decrypt(string value, int shift)
        {
            return Encrypt(value, 26 - shift);
        }

        static void Main(string[] args)
        {
            bool Continue = true;

            Console.WriteLine("      Ceasar Cipher");
            Console.WriteLine("-------------------------\n");

            while (Continue)
            {
                try
                {
                    Console.WriteLine("\nType a string to encrypt:");
                    string UserString = Console.ReadLine();

                    Console.Write("\nShift: ");
                    int key = Convert.ToInt32(Console.ReadLine());

                    Console.WriteLine("\nEncrypted Data: ");

                    string cipherText = Encrypt(UserString, key);
                    Console.WriteLine(cipherText);
                    Console.Write("\n");

                    Console.WriteLine("Decrypted Data:");

                    string t = Decrypt(cipherText, key);
                    Console.WriteLine(t);

                    Console.WriteLine("\nDo you want to continue?");
                    Console.WriteLine("Type in Yes to continue or press any other key and then press enter to quit:");
                    string response = Console.ReadLine();
                    Continue = (response == "Yes");

                }
                catch (FormatException)
                {
                    Console.WriteLine("You entered a bad operation, try another one");
                }
            }

        }
    }
}

这是我得到的,但它是不正确的。

凯撒密码

Type a string to encrypt:
Hello World

Shift: 1

Encrypted Data:
cfmmp rpsme

Decrypted Data:
bello qorld

Do you want to continue?
Type in Yes to continue or press any other key and then press enter to quit:

难点在于加密大写letter时,说'Z'可以得到小写一个,例如'd':

  'Z' + 10 == 'd'     

让我们提取大小写并使用模运算:

  for (int i = 0; i < alphabet.Length; i++) {
    char letter = alphabet[i];

    if (letter == ' ')
      continue;

    letter = (char)(char.IsLower(letter)
      ? (letter - 'a' + shift) % 26 + 26 + 'a'
      : (letter - 'A' + shift) % 26 + 26 + 'A');

    // Store.
    alphabet[i] = letter;
  }

或提取三种情况:

  1. 小写字母'a'..'z'
  2. 大写字母'A'..'Z'
  3. 其他角色(保持原样)

代码:

static string Encrypt(string value, int shift) {
  if (string.IsNullOrEmpty(value))
    return value; // Nothing to encrypt

  // ensure, that shift is in [0..25] range
  shift = ((shift % 26) + 26) % 26; 

  StringBuilder sb = new StringBuilder(value.Length);

  foreach(char letter in value)
    if (letter >= 'a' && letter <= 'z')
      sb.Append((char) ((letter - 'a' + shift) % 26 + 'a'));
    else if (letter >= 'A' && letter <= 'Z')
      sb.Append((char) ((letter - 'A' + shift) % 26 + 'A')); 
    else
      sb.Append(letter);

  return sb.ToString();
} 

// shift % 26 - in order to avoid integer overflow when shift == int.MinValue
static string Decrypt(string value, int shift) => 
  Encrypt(value, 26 - shift % 26);

演示:

  string initial = "Hello World!";
  int shift = 10;

  string encrypted = Encrypt(initial, shift);
  string decrypted = Decrypt(encrypted, shift);

  Concole.Write($"{initial} -> {encrypted} -> {decrypted}");

结果:

  Hello World! -> Rovvy Gybvn! -> Hello World! 

是的,你的加密被破解了。 'H' 不等于 'h'。这行

else if (letter < 'a')
            {
                letter = (char)(letter + 26);
            }

大写字母总是 运行,因为所有大写字母 < 'a'。 'H' = 72,所以上面的代码计算结果为 letter = (char)(72 + 26),右移一位是 99 或 'c'。

使用char.IsUpper拆分逻辑。如果 char.IsUpper == true,那么您需要以不同的方式处理。像

if(letter.IsUpper()){
    if (letter < 'A') DoStuff
} else {
    if (letter < 'a') DoStuff
}