Hello, I'm trying to program a Caesar Cipher, but I keep getting weird errors. My input is not being handled correctly. I have no idea, i've tried different variations, but it does not work, here is my code.

import java.io.*;
import java.util.Scanner;


public class CaesarCipher
{
    public static final int SIZE = 52;

    public static final char[] alphabet = {'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', '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'};

    protected char[] coded = new char[SIZE];

    protected char[] decoded = new char[SIZE];  

    public int CaesarCipher()
    {
        for (int i = 0; i < SIZE; i++)
        {
            coded[i] = alphabet[(i + 3) % SIZE];
        }

        for(int i = 0; i < SIZE; i++)
        {
            decoded[coded[i] - 'A'] = alphabet[i];
        }

        return 0;
    }

    public String encode(String secret)
    {
        char[] message = secret.toCharArray();

        for (int i = 0; i < message.length; i++)
        {
            if(Character.isUpperCase(message[i]))
            {
                message[i] = coded[message[i] - 'A'];
            }
        }

        return new String(message);

    }


    public String decode(String secret)
    {
            char[] message = secret.toCharArray();

            for (int i = 0; i < message.length; i++)
            {
                if(Character.isUpperCase(message[i]))
                {
                    message[i] = decoded[message[i] - 'A'];
                }
            }

            return new String(message);
    }



    public static void main(String[] args)
    {



        CaesarCipher cipher = new CaesarCipher();

        System.out.printf("Caesar Cipher! \n");

        System.out.println("\nPlease enter message:  ");

        Scanner input = new Scanner(System.in);

        String phrase = " ";

        while(input.hasNextLine())
        {
            phrase = input.next();
        }

        phrase = cipher.encode(phrase);

        System.out.println(phrase);

        phrase = cipher.decode(phrase);

        System.out.println(phrase);

    }

}

It will print out the first 2 phrases like Caesar Cipher and please enter text, I have it when I enter text, but i'm assuming the while loop won't break, but when I hit enter to continue the program it just goes to a new line. If I remove the while loop I get the no such element error. How can I handle my input, should an exception be thrown? Thanks in advance for your help.

Recommended Answers

All 8 Replies

I figured out to work it only with uppercase, I changed the while loop to an if statement, my problem is my CaesarCipher() method, it creates an ArrayOutofBounds Exception

I don't get your code to work at all. why do you even need that while or if statement? there's no need for it. just replace it with
String phrase = input.nextLine();

actually, with this:

public static final char[] alphabet = {'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', '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'};

you've made a good start. after all: a ceasar shift (the default shifting step = 1) ony takes the next element of the array.

so: whether your input is Upper or Lower case, that shouldn't matter.
there are, however, two things to consider. Two actions (one at encoding, one at decoding) where an ArrayIndexOutOfBoundsException might be thrown)

  1. at the encoding step => if the original char = 'z'
  2. at the decoding step => if the decoded char = 'A'

so.. my suggestion: keep the idea of the information there, but keep it in a String, not an array, it'll simplify the searching for the index:

private static final String aplhabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

now ... on encoding, you need to find the index of the original char in that String.

char charToEncode = 'a';
int ind = alphabet.getIndexOf(charToEncode);

now, there are three possible situations:
1. the char you entered is not in the 'alphabet' String (it might be a question mark, ...)
if so, you add that exact char to the encoded value, since you don't have another to encode it with.
2. the char you entered is not z (ind < (alphabet.length()-1)) ->
in this case, you add the char value of alphabet.charAt(ind+1);
3. it is z (the last char of your String), then you take alphabet.charAt(0)

and vice versa for the decoding

I just finished a ceasar cipher not too long ago. I'll give you my code for reference.

package com.github.geodox.ceasarcipher;

public class CeasarCipher
{
    private static StringBuilder sb = new StringBuilder();

    public static void main(String[] args)
    {
        String key = args[1];
        String text;

        for(int i = 2; i < args.length; i++)
        {
            sb.append(args[i]);
            sb.append(" ");
        }
        sb.deleteCharAt(sb.length()-1);
        text = sb.toString();

        if(args.length < 3)
        {
            System.out.println("Not Enough Arguments");
            System.out.println("Example Expected Arguments: encrypt, decrypt 795043 google");
        }
        if(args.length == 3)
        {
            if(args[0].equals("encrypt"))
            {
                System.out.println("Uncrypted Text: " + text);
                System.out.println("Key: " + key);
                String EncryptedText = Encrypt(key, text);
                System.out.println("Crypted Text: " + EncryptedText);
            }
            else if(args[0].equals("decrypt"))
            {
                System.out.println("Encrypted Text: " + text);
                System.out.println("Key: " + key);
                String DecryptedText = Decrypt(key, text);
                System.out.println("Decrypted Text: " + DecryptedText);
            }
            else
                System.out.println("Invalid Argument; 'encrypt' or 'decrypt' Expected.");
        }
        if(args.length > 3)
            System.out.println("Too Many Arguments");
    }

    private static String Encrypt(String key, String text)
    {
        char[] cryptedText = new char[text.length()];
        char[] textArray = new char[text.length()];
        int[] keyArray = new int[key.length()];

        for(int i = 0; i < text.length(); i++)
        {
            textArray[i] = text.charAt(i);
        }

        for(int i = 0; i < key.length(); i++)
        {
            keyArray[i] = key.charAt(i);

            char c = textArray[i];
            int s = keyArray[i];
            if (c >= 32 && c <= 127)
            {
                int x = c - 32;
                x = (x + s) % 96;
                if (x < 0) 
                    x += 96;
                cryptedText[i] = (char) (x + 32);
            }
        }

        return new String(cryptedText);
    }

    private static String Decrypt(String key, String text)
    {
        char[] decryptedText = new char[text.length()];
        char[] textArray = new char[text.length()];
        int[] keyArray = new int[key.length()];

        for(int i = 0; i < text.length(); i++)
        {
            textArray[i] = text.charAt(i);
        }

        for(int i = 0; i < key.length(); i++)
        {
            keyArray[i] = key.charAt(i);

            char c = textArray[i];
            int s = keyArray[i];
            if (c >= 32 && c <= 127)
            {
                int x = c - 32;
                x = (x - s) % 96;
                if (x < 0) 
                    x += 96;
                decryptedText[i] = (char) (x + 32);
            }
        }

        return new String(decryptedText);
    }

}

Feel free to change it to support multiple words. I attempted to do that so there is code that compliments it. However I moved on from this. I do ask that you post back with the code if you do change it.

... I don't really see a Caesar Cypher in that code ...
the arguments I would expect would be:
1. en or decrypt
2. the shift (which should logically never as high as the number you've provided). in the example the op created the max should be the nr of elements of his alphabet array
3. a text to en/decrypt..

since I didn't see a caesar shift in your code, I ran it here.
encryption of "hallo", second param (logically, the nr of shifts) = 1, result = '9'..
the length of the decrypted version can not be different from the length of the encrypted text in a caesar shift, so .. not sure what that is, but it's not a Caesar shift.

You enter a number from 0 - 9 per character. There also is Encrypt and Decrypt methods that each can be called from arguments. And the text is there as well.
I do not see what the problem is. The result gives the same number of characters encrypted as it is decrypted.

I dont see how you couldnt read the code to figure out how "the number provided" "should logically" never be that high. Its quite easy to figure out that Im parsing each number individually.

encrypt 32847 hallo = ;3D@F
decrypt 32847 ;3D@F = hallo

ah, ok..
that's rather an alternative encryption method.
the problem with that is, what are you going to pass as key when you enter:
"please, encrypt this sentence for me, I would be most grateful if I could get it secured."
if you miss one int in the key, you'll have an incorrect encoded value.

your solution does remind me of an other encryption type, don't recall the name immediately, though.
that uses a 'key' of chars (of which the chars aren't shifts, rather begin-chars of the corresponding encoded array), and the key is 'repeated' if the key is shorter than the text to-encode.

Oh well, that may help in some way. Good luck with it!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.