Caeasar Cipher with java's acm

1.3k views Asked by At

The code below encrypts a word or sentence in the way Caesar did. You put the shift value and the program takes each letter of the word/sentence and "moves" in the alphabet acoording to the shift (key) value. But this is not the problem. I found the code on the internet and i cannot explain some of it's lines. I know how it works but i need some specific answer about some of it's lines. Here is the code:

import acm.program.*;

public class CaesarCipher extends ConsoleProgram {

public void run() {
    println("This program implements a Caesar cipher.");
    int key = readInt("Character positions to shift: ");
    String plaintext = readLine("Enter a message: ");
    String ciphertext = encodeCaesarCipher(plaintext, key);
    println("Encoded message: " + ciphertext);
}


private String encodeCaesarCipher(String str, int key) {
    if (key < 0) key = 26 - (-key % 26);
    String result = "";
    for (int i = 0; i < str.length(); i++) {
        char ch = str.charAt(i);
        if (Character.isLetter(ch)) {
            if (Character.isUpperCase(ch)) {
                ch = (char) ('A' + (ch - 'A' + key) % 26);
            }
            else {
                ch = (char) ('a' + (ch - 'a' + key) % 26);
            }
        }
        result += ch;
    }
    return result;
}
}

What exactly do those lines mean, and how do they do what they do?

ch = (char) ('A' + (ch - 'A' + key) % 26);

and

ch = (char) ('a' + (ch - 'a' + key) % 26);
2

There are 2 answers

1
Trojan On BEST ANSWER

Those two lines behave identically, except for the fact that one applies to uppercase, and one to lowercase. I'll explain the uppercase operations here. Keep in mind that these char values are treated as ints until step 6 below.

ch = (char) ('A' + (ch - 'A' + key) % 26);
  1. ch - 'A' gives the initial character's int offset from capital-A.
  2. ch - 'A' + key increases the offset by key, creating the ciphered character's offset from capital-A.
  3. (ch - 'A' + key) % 26: the modulo here ensures that the numeric value of the ciphered character is 0-25 (for the 26 letters in the alphabet), preventing alphabet "overflow." The value of that expression is now the normalized offset of the ciphered character from capital-A.
  4. 'A' + (ch - 'A' + key) % 26 adds the ciphered character's offset from capital-A to capital-A itself, resulting in the ciphered character's int value.
  5. (char) ('A' + (ch - 'A' + key) % 26) casts that int to char type, resulting in the ciphered character as a char.

This code treats the beginning of the alphabet (capital-A) as the "starting point," from which each letter's offset is measured. The offset is the character's number of letters from 'A'.

Example: To cipher "E" with a key of 6:

  1. Find the number of letters between "E" and capital-A. The ASCII code of A is 65, and the code of E is 69. To find E's offset from A, subtract 69 - 65 = 4.
  2. Add the offset and the key: 4 + 6 = 10. This is the number of letters from A the ciphered character will be.
  3. 10 % 26 = 10 (no effect because of the small starting letter + small key)
  4. 'A' + 10 = 65 + 10 = 75 results in the ASCII code of the ciphered character, 75 ('K')
  5. Casting 75 to char allows it to be treated as a character, rather than an int.
0
AudioBubble On

It is converting the character to the ASCII equivalent, as denoted by the + operator (you cannot add characters, only numbers), then changing the character by a certain number of values. The (char) is casting (converting) the result back to a character so you can assign it to ch.

'A's ASCII value is 65, and ch is the character currently being evaluated at position i in the string. ch = (char) ('A' + (ch - 'A' + key) % 26); evaluates as '65 + (character's ASCII number - 65 + key) % 26'. This result is then cast back to a character and assigned to ch. The modulo (%) operator takes a number, divides it by a second number, in this case 26, and returns the remainder (5 % 6 is 5, while 7 % 3 is 1). The second statement works the same way, but uses lowercase 'a' (97) instead of capital 'A'.

See this page for ASCII keys: http://www.asciitable.com/