COMP 1917 Computing 1
Session 2, 2016

Week 4 Lab - Caesar Cipher


In this lab you will implement one of the oldest known coding techniques, called the Caesar Cipher, which encripts a message by rotating the letters of the alphabet in a cyclical fashion. You can read about the Caesar Cipher on this Wikipedia page.

  1. Create a directory called lab4, and cd to this directory. Open an editor and start editing a new file called caesar.c

  2. Write a function
    int rotate_right(int ch)
    
    which rotates a specified alphabetic character one step to the right, and returns the new character. In other words, it should convert 'A' to 'B', 'B' to 'C' ... 'Y' to 'Z', and 'Z' to 'A'.
    Lowercase letters should be rotated in the same fashion. (Note: unlike the examples on the Wikipedia page, which convert lower to upper case, your function should preserve the case of the letter). Non-alphabetic characters should be returned without change.

  3. Write a function
    int rotate_left(int ch)
    
    which performs the inverse of rotate_right() - converting 'a' to 'z', 'b' to 'a', etc. and returns the new value.

  4. Write a function
    int encode(int ch, int shift)
    
    which performs the Caesar encryption for a single character by rotating the specified number of times (shift). The function should repeatedly call rotate_right() or rotate_left() depending on whether shift is positive or negative. (If shift is zero, the original character should be returned unchanged.)

  5. Finally, write the full program caesar.c which performs the Caesar encryption for an entire text. Your program should prompt the user, enter the shift, then enter the original text, and finally output the encoded text.
    $ ./caesar
    Enter shift: 1
    Enter Text:
    HAL
    IBM
    
    $ ./caesar
    Enter shift: -5
    Enter Text:
    Cry "Havoc!", and let slip the Dogs of War.
    Xmt "Cvqjx!", viy gzo ngdk ocz Yjbn ja Rvm.
    
    Feel free to use this skeleton code for your main function. (Note: getchar() reads a single character from standard input, putchar() writes a single character to standard output, EOF stands for "End Of File")
    int main(int argc, char * argv[]){
      int ch;
    
      //your code here
    
      ch = getchar();
      while(ch != EOF) {
        putchar(/*your code here*/);
        ch = getchar();
      }
    
      return EXIT_SUCCESS;
    }
    
  6. We have provided a few sample files for you to decrypt, which you can copy from this directory.

    You should also copy freq.c from the code directory.

  7. Samuel Morse calculated that the letters of the alphabet written in order from most common to least common are
    ETAONISRHLDCUPFMWYBGVKQXJZ
    
    Compile freq.c and use it to measure the frequency of letters in each of the sample encoded files by typing, for example:
    $ ./freq < c1.in
    
    From this (or otherwise) try to guess what shift has been applied to these files. Then decrypt them using your caesar program, by changing the "0" at the top of each file to the negative of the shift you deduced, and typing
    $ ./caesar < c1.in
    
  8. When you have finished, show your work to your tutor and submit it using
    $ give cs1917 lab4 caesar.c
    
  9. Bonus Challenge:
    Combine code from freq.c and caesar.c to produce a program deceasar.c which counts the frequency of each letter in the input, makes a "best guess" of how far the letters have been shifted, and prints the decoded message.

    To do this, you may need to read the input twice. This can be done using files and command-line arguments, like this:

    int main(int argc, char *argv[]) {
      FILE *fp;
      int ch;
    
      // open the file whose name is given as a command-line argument
      fp = fopen(argv[1],"r");
      ch = getc(fp);
      while(ch != EOF) {
        //your code here
        ch = getc(fp);
      }
    
      // close the file and re-open it from the beginning
      fclose(fp);
      fp = fopen(argv[1],"r");
      ch = getc(fp);
      while(ch != EOF) {
        //your code here
        ch = getc(fp);
      }
    
      return EXIT_SUCCESS;
    }