凯撒密码移位(使用字母数组)

本文关键字:数组 密码 凯撒 | 更新日期: 2023-09-27 18:21:44

我目前正在用C#为我的作业编写一个Caesar密码程序,遇到了一个问题。

我使用一个数组来处理这个任务,在这个数组中我存储了整个字母表,并声明了一个由数组中的字符索引定义的移位变量——for循环的迭代。移位计算是在foreach循环中完成的,该循环从从文本文件中读取的字符串中获取一个字符。Foreach循环包含在for循环中,该循环迭代以输出每个可能的移位。

然而,问题是,当我试图通过移位变量的值访问数组中的字符时,程序似乎没有访问我想要的字符,它只是输出与原始字符串中相同的字符。

这是程序的代码:

using System; 
using System.IO;
public class caesar_shift
{
    public static void Main()
    {
        string file = @"C:'Users'terasss2'Desktop'Programming and Data Structures'caesarShiftEncodedText.txt";      //String variable that stores a file location
        string encrypted_text = File.ReadAllText(file);     //String variable that contains the text from a file. To get the text, the method in a class SystemIO is ran to read the text. It expects a parameter, which is a file directory.
        string decoded_text = " ";
        int shift = 0;
        char character = '0';
        char[] alphabet = new char[26]{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
        Console.WriteLine("The encrypted text is 'n{0}", encrypted_text);       //Display the encrypted text
        for(int i = 0; i < alphabet.Length; i++)        //Start a loop which will display 25 different candidates of decipher
        {
            foreach(char c in encrypted_text)
            {
                character = c;
                if(character == '''' || character == ' ')
                    continue;
                shift = Array.IndexOf(alphabet, character) - i;     //Define a shift which is the index of a character in an alphabet array, take away the itteration of this loop. Store the result in a variable
                if(shift <= 0)
                    shift = shift + 26;
                if(shift >= 26)
                    shift = shift - 26;
                character = alphabet[shift];    //Set the character to a shifted letter by accessing the array element of a value shift
                Console.WriteLine(character);
                decoded_text = decoded_text + character; 
             }  
            Console.WriteLine("'nShift {0} 'n {1}",i + 1, decoded_text);
         }
       }
}

凯撒密码移位(使用字母数组)

我对您的代码进行了一些处理。下面给出了解决方案,但你必须小心:你只能使用大写字母,因为上下图表有区别。我使用了ToUpper()方法。对我来说很好。我想这就是你的问题所在。

public static void Main()
    {
        string encrypted_text = "BCD";     //String variable that contains the text from a file. To get the text, the method in a class SystemIO is ran to read the text. It expects a parameter, which is a file directory.
        string decoded_text = " ";
        int shift = 0;
        char character = '0';
        encrypted_text = encrypted_text.ToUpper();
        char[] alphabet = new char[26] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
        Console.WriteLine("The encrypted text is 'n{0}", encrypted_text);       //Display the encrypted text
        for (int i = 0; i < alphabet.Length; i++)        //Start a loop which will display 25 different candidates of decipher
        {
            decoded_text = "";
            foreach (char c in encrypted_text)
            {
                character = c;
                if (character == '''' || character == ' ')
                    continue;
                shift = Array.IndexOf(alphabet, character) - i;     //Define a shift which is the index of a character in an alphabet array, take away the itteration of this loop. Store the result in a variable
                if (shift <= 0)
                    shift = shift + 26;
                if (shift >= 26)
                    shift = shift - 26;

                decoded_text += alphabet[shift];
            }
            Console.WriteLine("'nShift {0} 'n {1}", i + 1, decoded_text);
        }
    }

我查看了您的代码,并进行了轻微调整。首先,我将其转换为一个方法,允许您传入字符串和要偏移的量,这样您就可以在从025的循环中调用它来查看所有排列,也可以只获得一个值。我还检查每个字符是否真的在数组中,如果不是,那么不要更改它(在代码中,您只检查'''' '字符:

public static string ShiftText(string input, int shiftAmount)
{
    if (input == null) return null;
    char[] alphabet =
    {
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
        'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
    };
    shiftAmount %= 26; // Ensure shift is between 0 and 25
    var shiftedText = string.Empty;
    foreach (var character in input)
    {
        var index = Array.IndexOf(alphabet, character);
        if (index < 0)
        {
            // This character isn't in the array, so don't change it
            shiftedText += character;
        }
        else
        {
            var newIndex = index - shiftAmount;
            // If it's negative, wrap around to end of array
            if (newIndex < 0) newIndex += 26;
            shiftedText += alphabet[newIndex];
        }
    }
    return shiftedText;
}

但是,另一种适用于大写和小写并且代码较少的方法是简单地测试是否为char.IsLetter(character),然后在相同的0-25范围内移动字符的ASCII值。

例如,这与上面的代码相同,只是它也适用于小写字母。这里的区别在于,在我们将该字符与我们的最低值字符('a''A')进行比较之前,我们首先测试是否为char.IsLower()。这样,我们就可以保持在这个字符集的ASCII范围内:

/// <summary>
/// This method takes the input string and shifts all letter characters 
/// to the left (subtracts) by the amount specified in shiftAmount, so 
/// if shiftAmount = 1, then 'M' becomes 'L', and 'a' becomes 'z'.
/// </summary>
/// <param name="input">The input string to apply changes to</param>
/// <param name="shiftAmount">A value from 0 to 25, used to shift the characters</param>
/// <returns>The modified (shifted) string</returns>
public static string ShiftText(string input, int shiftAmount)
{
    if (input == null) return null;
    // Ensure shift is between 0 and 25
    shiftAmount %= 26; 
    var result = string.Empty;
    // Loop through input and update result with shifted letters
    foreach (var character in input)
    {
        if (!char.IsLetter(character))
        {
            // If the character isn't a letter, don't change it
            result += character;
        }
        else
        {
            var newChar = (char) (character - shiftAmount);
            // Adjust newChar to stay within this character range
            if (newChar < (char.IsLower(character) ? 'a' : 'A')) newChar += (char) 26;
            result += newChar;
        }
    }
    return result;
}

为什么不直接使用字符的ASCII值呢。我会先把密文转换成小写。例如,a的asci值为97。我会写一个方法来提取97个每个字符,所以a=0,b=1……z=25。然后,对于密文中的每个字符,得到该字符的-3偏移值。例如,输入字符d应返回值0,该值对应于a。