我目前正在C#中编写一个Caesar Cipher程序来完成我的任务,我遇到了问题。
我正在使用一个数组来接近这个任务,我存储了整个字母表,并且我声明了一个移位变量,它由数组中的字符索引定义 - 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);
}
}
我看了看你的代码并进行了一些调整。首先,我将它转换为一个方法,让你传入字符串和你想要移动的数量,这样你就可以在从0
到25
的循环中调用它来查看所有的排列,或者你可以得到一个单一的价值。我还检查每个字符是否实际上在数组中,如果不是,则不要更改它(在您的代码中,您只检查'\'
和' '
字符:
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。