The_Cthulhu_Kid
The_Cthulhu_Kid

Reputation: 1859

Caesar Cipher in C#

If I want to write a Caesar cipher C# do I have to go through every case? It doesn't make sense to me to convert to ASCII or UTF (probably because I don't understand how it would work). I just need a point in the right direction.

Should I assign each letter the numbers 1-26?

Upvotes: 5

Views: 8850

Answers (5)

Pigamer37
Pigamer37

Reputation: 1

I made a simple class that handles lowercase, uppercase and numbers. It uses the StringBuilder class to make the output. To decode a string, you would use the opposite shift (if you encrypt with shift = 2, decrypt with shift = -2). I'm also kind of new to C# and come from a C++ background, but I hope this approach works for you or makes it clear how to approach it. I tried commenting so the functionality is clear:

class Cypher
{
    static public String CaesarCipher(String input, int shift = 1) {
        if(shift==0) return input;

        StringBuilder builder = new StringBuilder(); //stringbuilder class for ease of use

        for (int i = 0; i < input.Length; i++) 
        {
            char c = input[i];
            char c2 = c;
            if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')))  {
                c2 = (char)(c + shift); //make the shift

                if ((c >= 'a') && (c <= 'z'))  //original char is in this range
                {
                    c2 = CharBindToRange(c2, 'a', 'z'); //clamp the shifted char to range
                }
                else if ((c >= 'A') && (c <= 'Z'))
                {
                    c2 = CharBindToRange(c2, 'A', 'Z');
                }
                else if ((c >= '0') && (c <= '9'))
                {
                    c2 = CharBindToRange(c2, '0', '9');
                }
            }
            builder.Append(c2); //add the processed character to output
        }
        return builder.ToString(); //return the processed string
    }
    static protected char CharBindToRange(char cinp, char low, char high) //clamps char to specified range
    {
        if (low >= high) { return '?'; }
        if(cinp>high)
        {
            cinp = (char)(low + (cinp - high) - 1);
        }
        else if (cinp < low)
        {
            cinp = (char)(high - (low - cinp) + 1);
        }
        return cinp;
    }
}

Upvotes: 0

Rezo Megrelidze
Rezo Megrelidze

Reputation: 3060

This is my approach.

    public static string Encrypt(string str, int n)
    {
        return string.Join("", str.Select(x => Encrypt(x, n)));
    }

    public static string Decrypt(string str, int n)
    {
        return string.Join("", str.Select(x => Decrypt(x, n)));
    }

    public static char Encrypt(char chr, int n)
    {
        int x = chr - 65;

        return (char)((65) + ((x + n) % 26));
    }

    public static char Decrypt(char chr, int n)
    {
        int x = chr - 65;

        return (char)((65) + ((x - n) % 26));
    }

P.S.

Works only for uppercase letters.

Read the Wikipedia article: Caesar cipher

Upvotes: 1

Tom W
Tom W

Reputation: 5423

Perhaps dropping hints would be helpful - you say you don't want to copy or be told the answer:

  • Consider that C# features the modulus operator, in the form a = b % c - that is, remainder of b divided by c. When c = n and b = n, a = 0. When c = n and b = n+1, a = 1. Experiment with the behaviour of this operator.
  • You can declare arrays statically in C# with initialisers: char[] chars = new char[]{'a', 'b',...};

Upvotes: 1

eFloh
eFloh

Reputation: 2158

You could put each letter into an array and use the array index (wrapping at the end) or you could simply use the asccii value of the letter and wrap to the first when reaching the last. The trick here is that all the characters are coninuously sorted, starting at A=0x41

Upvotes: 2

Jon Hanna
Jon Hanna

Reputation: 113392

For a traditional Caesar Cypher, you'd check a char was in the range [a-z] or [A-Z], and just pass it plain otherwise.

An alternative is to treat all characters in the same way, so not only does a become b, but µ becomes ¶ and you wrap around at U+10FFFF (the highest codepoint in Unicode) becomes U+0000 (the former is a non-character and the latter a null character, but there's no reason why a string can't hold them to transmit to another place.

In between those two, is to act on the UTF-16. That is, you just add 1 to the value of each char, and wrap U+FFFF through to U+0000. The output could become an invalid UTF-16 string (because it could have mis-matched surrogates, but that wouldn't prevent you from passing it around in a string, and then decyphering it again. After all, modern encryption doesn't result in valid strings either.

Upvotes: 1

Related Questions