解密否定特殊字符,如" !@#$%^&放大器; *()"

时间:2015-11-25 07:04:16

标签: c# encryption

我想知道我怎么能否定这个特殊的角色。 例如,当我为我的解密文本键入aaa并向后移动3个空格时,它显示它^^^而不是www。我的编码有什么问题吗? 这是我在c#

中的所有代码
static void Main(string[] args)
{
    string UserInput = "";
    int shift;
    Shift OBSHIFT = new Shift();
    Console.WriteLine("Welcome to Ceasar Shift Program:");
    Console.WriteLine("********************************");
    Console.WriteLine("type a string to encrypt:");
    UserInput = Console.ReadLine();
    Console.WriteLine("How many chars would you like to shift?: :");
    shift = int.Parse(Console.ReadLine());
    Console.Write("Your encrypted string is: ");
    Console.WriteLine(OBSHIFT.Decrypt(UserInput, -shift));
    Console.Read();
}
class Shift
{
    public string Decrypt(string cipherString, int shift)
    {
        string userOutput = "";
        char[] a = cipherString.ToCharArray();
        for (int i = 0; i < cipherString.Length; i++)
        {
            char c = a[i];
            int temp;
            if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
            {
                temp = (int)(a[i] + shift);
                if ((c >= 'A' && c <= 'Z' && temp > 'Z') || (c >= 'a' && c <= 'z' && temp > 'z'))
                    temp = temp + 26;
                else
                    temp = (int)(a[i] + (shift));
            }
            else
                temp = c;
            userOutput += (char)temp;
        }
        return userOutput;
    }
}

2 个答案:

答案 0 :(得分:0)

问题在于这段代码可以实际转移:

if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
{
    temp = (int)(a[i] + shift);
    if ((c >= 'A' && c <= 'Z' && temp > 'Z') || (c >= 'a' && c <= 'z' && temp > 'z'))
        temp = temp + 26;
    else
        temp = (int)(a[i] + (shift));
}

我建议以几种方式进行重组:

  • 确保您的班次始终是正面的,所以您只需要担心“过去”一组特定字符的结尾
  • 使用两个单独的分支,一个用于a-z,一个用于A-Z
  • 使用StringBuilder构建字符串而不是重复字符串连接

例如:

public string ShiftText(string input, int shift)
{
    // This makes sure the shift is *always* in the range 0-25.
    shift = ((shift % 26) + 26) % 26;

    StringBuilder output = new StringBuilder();
    foreach (char c in input)
    {
        if (c >= 'a' && c <= 'z')
        {
            // We'll sort this later
        }
        else if (c >= 'A' && c <= 'Z')
        {
            // We'll sort this later
        }
        else
        {
            output.Append(c);
        }
    }
    return output.ToString();
}

现在“稍后排序”中的位更容易使用。对于a-z部分,例如:

int shifted = c + shift;
if (shifted > 'z')
{
    shifted -= 26;
}
output.Append((char) shifted);

...然后A-Z也一样,但是对'Z'而不是'z'进行测试。是的,这实际上是重复的代码 - 但它只有两次,我认为复制比提取它更简单。

答案 1 :(得分:0)

我建议改用这种代码:

public class Shift
{
    public string Decrypt(string cipherString, int shift)
    {
        var alphabet =
            Enumerable
            .Concat(
                Enumerable.Range((int)'a', 26),
                Enumerable.Range((int)'A', 26))
            .Select(i => (char)i)
            .ToArray();

        var map =
            alphabet
                .Zip(
                    alphabet.Concat(alphabet).Concat(alphabet).Skip(alphabet.Length + shift),
                    (c0, c1) => new { c0, c1 })
                .ToDictionary(x => x.c0, x => x.c1);

        return String.Join("", cipherString.Select(x => map.ContainsKey(x) ? map[x] : x));
    }
}

这三个部分非常清晰。 (1)构建了alphabet。它可以包含任意数量的字符,只要没有重复。 (1)map只是通过将字母表映射到由shift个字符移位的字母表而构建的字典。 (3)返回由密钥存在的cypherString映射的输入map