CS 124, Spring 2017
Lab 7: Vigenère Cipher
Once again this week, you will be working with subroutines. In this case, you will work on an implementation of the Vigenère Cipher, the system for encoding and decoding text messages that was discussed and demonstrated in class. This is an exercise in writing subroutines and in using an API that provides some utility functions that can be used in solving the problem.
You will, presumably be working in Eclipse. You will probably want to create a new Java Project in Eclipse for this lab. You will need copies of the files CodeUtil.java and TextIO.java. You can copy-and-paste them from /classes/cs124 into the Eclipse window, putting them in the src folder in your project.
This lab is due by 3:00 PM next Friday, February 9. You should submit the file named Cipher.java using the Submit124 web site as usual.
The Assignment
You should write a program that does encoding and decoding of messages using the Vigenère cipher. The program must be named Cipher. Create a new class in your Eclipse project with that name. Your project should already contain the files CodeUtil.java and TextIO.java. Note that you should not modify CodeUtil.java; your program must work with the original version.
For the main() routine in the program, you should use the following code, which you should copy-and-paste from this web page into the file Cipher.java:
public static void main(String[] args) { String plainText; // The un-encrypted message. String cipherText; // The encrypted message. String key; // The key for the Vigenere cipher. boolean encodeFlag; // Whether to do encoding or decoding. key = readVignereKey(); // returns a string of letters only! encodeFlag = askUserEncodeOrDecode(); if (encodeFlag) { plainText = readInput(); plainText = CodeUtil.lettersOnly(plainText); cipherText = vigenereEncode(plainText,key); writeOutput(cipherText); } else { cipherText = readInput(); cipherText = CodeUtil.lettersOnly(cipherText); plainText = vigenereDecode(cipherText,key); writeOutput(plainText); } } // end main();
You should not modify main(). To finish the assignment, you should write all the methods that are required by this main() routine. All of the methods are static. In addition to writing the method itself, you should add a JavaDoc comment for each method. You should also add a JavaDoc comment for class Cipher. Here are the requirements for the methods:
readVignereKey()
— must let the user enter one line of text. The text will be used as the key in the cipher. The value that the user enters can contain spaces and punctuation, but the string that is returned by the function must contain only letters.askUserEncodeOrDecode()
— must ask the user whether to encode or decode the user's input. A return value of true means to encode; a return value of false means to decode.readInput()
— must let the user enter multiple lines of text, with a blank line to indicate the end of the input. Input ends when the user presses return without typing anything. All the input lines must be combined into one long string, and that string is the return value of the function.writeOutput(string)
— must write all the characters of the string to standard output (System.out), with a line break after every 60-th character and at the end. (In fact, the string will consist entirely of uppercase letters, with no line breaks in the string.)vigenereEncode(plainText,key)
— must encode the plaintext using the specified key, and return the resulting ciphertext. You can assume that every character in the plaintext is a letter and every character in the key is a letter. A character, ch, from the plaintext is to be encoded by callingCodeUtil.encode(ch,offset
), where the offset is computed from one of the letters in the key. To determine which letter from key to use, you need the position of ch in plaintext. Convert that position into a position in key by takingposition % key.length(). vigenereDecode(cipherText,key)
— must decode the ciphertext using the specified key, and return the resulting plaintext. This is almost identical to vigenereEncode(), except that you are decoding instead of encodeing.
You must use functions from CodeUtil.java when appropriate. Read that file to see what functions are available.
Here is an example ciphertext that was encoded using the key carpe diem. This is an encoding of the preamble to the U.S. constitution: "We the people of the United States, in order...". Your program should be able to decode it:
YEKWISMSBNEFUXKMYZKTVSWWIXQUIEDVGMVFQFFGQDUSDGPVGJHKXGPIFCIV BENNIJWNXAXUEEZCWXZIPQMVHXLKXDCNHJMOQXKRRFKMGMJATTYTGRUQAPDV UIQKIBTODDXHBLQIEETVDTAQNFRGIDVHEGCLGIWPINNEJHMQOWAHLZQIUBCF QOLGWHTZQUAESSXZTAUTVGMWGHAQRUPMQIRPGSKPFOQWTVHZHGRVWFKTLIMR VJATTYTYQQXQFSKPXHASRCMVGMFI
Style Rules For Subroutines
Here are a few new style rules, relevant to writing subroutines and using member variables. You are expected to follow these rules, starting with this lab.
- You should always use meaningful names for subroutines.
- The name of a subroutine should begin with a lower case letter.
- A subroutine should always have a single, well-defined task.
- Member variables should be used to save information about "state" that has to be saved between calls to subroutines. They should not be used for simple communication between routines; use parameters and return values for that.
- Every subroutine should have a comment that describes the task performed by the subroutine, the purpose of each of its parameters, and the meaning of the return value, if any. It should also describe any important exceptions that can be thrown by the subroutine. For non-private subroutines, at least, the comment should be in the form of a JavaDoc comment. That is, it should come just before the definition of the subroutine, and it should start with /** and end with */. (It is recommended, but not required, that you use the @param, @return, and @throws tags in the comment. These tags must always come at the end of the comment, after the description of the purpose of the subroutine.) Note that if you type /** on the line before a subroutine and press return, Eclipse will put in an outline of a JavaDoc comment for you.
- Public member variables should be rare. But if you define one, you should provide a JavaDoc-style comment just before the declaration of the variable.
- The main comment on a class should also be in JavaDoc format.
Note that JavaDoc comments are covered in the textbook in Section 4.5.4 Be sure to read that section and make sure that you understand how to write JavaDoc and what it is for.