2

I'm trying to make a Caesar cipher program, however I am unable to remove the spaces from the final encrypted output. I used:

if (letter == ' ')
                continue;

However this seems to not be working and I can't identify what is causing the issue. I haven't been working with C# very long so it may potentially be a stupid error.

If I was to input the phrase with a shift of 7: "I need help" the following output would be pAullkAolsw with all spaces becoming uppercase A. The output I wish to have should be in the example: p ullk olsw.

Below is my full code:

using System;

class Program
{

static string Caesar(string value, int shift)
{
    char[] buffer = value.ToCharArray();
    for (int i = 0; i < buffer.Length; i++)
    {

        char letter = buffer[i];

        letter = (char)(letter + shift);


        if (letter == ' ')
            continue;

        if (letter > 'z')
        {
            letter = (char)(letter - 26);
        }
        else if (letter < 'a')
        {
            letter = (char)(letter + 26);
        }


        buffer[i] = letter;
    }
    return new string(buffer);
}

static void Main()
{
   Console.WriteLine("Enter text to encrypt: ");
   string buffer = Console.ReadLine();
   Console.WriteLine("Enter value of shift: ");
   int shift = int.Parse(Console.ReadLine());

   string final = Caesar(buffer, shift);

   Console.WriteLine(final);
   }
}
Ryan Easter
  • 45
  • 1
  • 12
  • You check if the shifted letter is ' '. YOu have to check before the shift. EDIT: If you want to remove the spaces completely you have to write in a new char[] instead of changing the buffer[i]. (Note that you wont have any spaces when decrypting it) – TheSkimek Nov 02 '17 at 13:08
  • yes silly mistake: test for the space before doing the + shift. – Rob Nov 02 '17 at 13:09
  • Yeah it seems obvious now, at least I will remember it for in the future – Ryan Easter Nov 02 '17 at 13:12
  • Be careful, in *general case* you should use *modulo arithmetics*; counter example - `shift = 100` and `shift = -100` – Dmitry Bychenko Nov 02 '17 at 13:43
  • 2
    The lesson to learn here is **variables should have one meaning**. Here you use `letter` to mean both the plaintext and the ciphertext, but those are logically different, so make different variables for them. Programmers at all levels of experience sometimes behave as though variables are expensive, but local variables are the cheapest thing there is; use as many as you like if it makes the program easier to follow. – Eric Lippert Nov 02 '17 at 13:45

2 Answers2

2

If you want to skip spaces you just have to check before you transform the letter variable:

char letter = buffer[i];
if (letter == ' ')
    continue;

letter = (char)(letter + shift);
// ...
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
0

You should encrypt if and only if you know how to do it (i.e. if you have a a..z or A..Z character); in case you have different character (space, minus sign, quotation mark, whatever), just leave it intact:

using System.Linq;

...

static string Caesar(string value, int shift) {
  //DONE: do not forget about validation
  if (null == value)
    return value; // or throw exception (ArgumentNullValue)

  int n = 'z' - 'a' + 1;

  // For each character in the value we have three cases:
  //   a..z letters - encrypt
  //   A..Z letters - encrypt
  //  other letters - leave intact
  //  "n + shift % n) % n" - let's support arbitrary shifts, e.g. 2017, -12345 etc. 
  return string.Concat(value
    .Select(c => 
        c >= 'a' && c <= 'z' ? (char) ('a' + (c - 'a' + n + shift % n) % n) 
      : c >= 'A' && c <= 'Z' ? (char) ('A' + (c - 'A' + n + shift % n) % n) 
      : c));
}

Test:

Console.Write(Caesar("Hello! It's a test for so called 'Caesar cipher'.", -2));

Outcome (please, notice that spaces, apostrophes, exclamation mark are left as they were):

Fcjjm! Gr'q y rcqr dmp qm ayjjcb 'Aycqyp agnfcp'.
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215