Caesar Cipher C#

Hello,

I’ve been trying to learn how to code with C# for only about 3 weeks now, and this website has been very helpful. However I have been running into an error when trying to run this code and I do not know how to fix it.

using System;

namespace CaesarCipher
{
  class Program
  {
    static void Main(string[] args)
    {
      char[] alphabet = new char[] {'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("type a message to encrypt it.");
      string message = Console.ReadLine();
      char[] secretMessage = message.ToCharArray();
      
      char[] encryptedMessage = new char[secretMessage.Length];
      
      int i;
      for(i = 0; i < secretMessage.Length; i++)
      {
        char secretItem = secretMessage[i];
        int index = Array.IndexOf(alphabet, secretItem);
        int letterPosition = (index += 3) % 26;
        int encryptedCharacter = alphabet[letterPosition];
        encryptedMessage[i] = alphabet[encryptedCharacter];        
      }
      
      string superSecretMessage = String.Join("", encryptedMessage);
      Console.Write(superSecretMessage);
    }
  }
}

When I run this code and type “hello” into the console it gives me an unhandled exception error. Same with any other word or character.

If anyone would be willing to point out me what exactly I am doing wrong. It would be very appreciated.

2 Likes

Your problem is this line:
int encryptedCharacter = alphabet[letterPosition];

Let’s say your plain-text is “hello”.

On the first iteration of your loop - i = 0 - your variables will be as follows:

i = 0
secretItem = "h"
index = 7
letterPosition = 10

We then arrive at the line int encryptedCharacter = alphabet[letterPosition];.

Here, we’re assigning the value of alphabet[letterPosition], which at this stage of the code is k, to the variable encryptedCharacter.

Unfortunately for you, you’ve declared encryptedCharacter as an int - so this variable gets the value 107, which is the decimal representation of the ASCII code for k.

We then try and do encryptedMessage[i] = alphabet[encryptedCharacter], which is the same as encryptedMessage[0] = alphabet[107].

alphabet doesn’t have a 107th item, so you get an IndexOutOfRangeException thrown and your code bails out.

I’ll leave it to you to figure out how to fix this, though. :slight_smile:

3 Likes

Thank you very much!, I did not know it worked liked that and would never have guessed it in a million years. I just fixed it by subtracting 97 from the encryptedCharacter variable within the loop. and it works perfectly now!

That’s one way of fixing it, but would it not be better to change the code like so?

using System;

namespace CaesarCipher
{
  class Program
  {
    static void Main(string[] args)
    {
      char[] alphabet = new char[] {'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("type a message to encrypt it.");
      string message = Console.ReadLine();
      char[] secretMessage = message.ToCharArray();
      
      char[] encryptedMessage = new char[secretMessage.Length];
      
      int i;
      for(i = 0; i < secretMessage.Length; i++)
      {
        char secretItem = secretMessage[i];
        int index = Array.IndexOf(alphabet, secretItem);
        int letterPosition = (index += 3) % 26;
        char encryptedCharacter = alphabet[letterPosition]; // this line now gets the encrypted character as a CHAR
        encryptedMessage[i] = encryptedCharacter; // so we can just pop it directly into the encrypted message!
      }
      
      string superSecretMessage = String.Join("", encryptedMessage);
      Console.Write(superSecretMessage);
    }
  }
}

This way, you’re not making another unnecessary lookup by index of your alphabet variable.

Edit: Incidentally, this isn’t the first time I’ve responded to a thread about the Caesar Cipher in C#. After the last one, I decided to throw together a “quick and dirty” C# Caesar Cipher of my own…

I came up with this...
using System;
using static System.Array;
using static System.Char;

class MainClass {
  public static void Main (string[] args) {
    // alphabet for shifting
    char[] alpha = "abcdefghijklmnopqrstuvwxyz".ToCharArray();

    // caesar shifter
    int shift_by = 3; // +ve: shift right, -ve: shift left

    // message to be enciphered:
    string encipher_me = "placeholder text though caesar ciphers are cryptographically weak";
    Console.Write("Please enter your message for encryption: ");
    encipher_me = Console.ReadLine();
    // placeholder for encrypted message
    string encrypted = "";

    // encrypt the message
    for (int i = 0; i < encipher_me.Length; i++)
    {
      char space = '\u0020';
      if (encipher_me[i] != space) {
        char el;
        if (IsUpper(encipher_me[i])) {
          el = ToLower(encipher_me[i]);
        }
        else {
          el = encipher_me[i];
        }
        int ai = IndexOf(alpha, el);
        int ni = (((ai + shift_by) % 26) + 26) % 26;
        encrypted = encrypted + alpha[ni];
      }
      else {
        encrypted = encrypted + space;
      }
    }

    Console.Write(encrypted);
  }
}

Emphasis on “quick and dirty”… It’s not meant to be perfect. Just wanted to see what I could do. :slight_smile:

Could also use Linq’s select or Select to obtain each individual character, the result of that would be an iterable of characters which is exactly what string.Join takes as input.

using System.Linq;

...

string input = Console.ReadLine();
Console.WriteLine(
  string.Join("", input.Select(encodeChar))
);

...

static char encodeChar(char ch) {
  // subtract 'a', add 3, mod 26, add 'a'
}
1 Like

I think Linq is a bit beyond the scope of the C# course here.

I’ve worked with devs who find that stuff confusing, so might be a bit much for newbies.

(It is pretty good, though!)

yeah I am a bit of a newbie, thanks for the help tho, and yeah your way is the correct way to do it. if you have any tips or extra resources for me to learn, could you let me know? again thank you for the help :slight_smile: