1

The program allows the user to enter a phrase and converts it to ROT13, where each English letter entered, becomes the letter 13 places after it(A becomes N). My current code works when 1 character is entered, however I need it to run through the code the number of times there are characters. I've tried to put in a while loop at the beginning, but it doesn't seem to be working. Why is this?

import java.io.*;

public class J4_1_EncryptionErasetestCNewTry
{

    public static void main (String [] args) throws IOException
    {
        BufferedReader myInput = new BufferedReader (new InputStreamReader (System.in));// Buffered Reader reads the number inputed 

        String key [] = {"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"};
        String keyA [] = {"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"};

        System.out.println("Enter a phrase: ");
        String phrase = myInput.readLine();

        int length = phrase.length();
        int y = 0, i = 0, num = 0;

        while (y <= length) {
            String letter = Character.toString(phrase.charAt(y));
            y++;
            while(!(letter.equals(key[i]))){
                i++;
            }
            num = i;
            System.out.println(keyA[num]);
            y++;
        }
    }
}
7
  • 1
    Do you mean to y++ twice within the same loop? Indenting would really help, as would explaining what "doesn't work" (including sample input/output). Also, given that A-Z are sequential characters (and have sequential numeric values), can you think of a way to implement ROT-n without using the extra arrays? Commented Sep 13, 2013 at 1:17
  • looks good to me. Where is the error? Is it getting stuck in the inner loop? It looks like you never reset i to 0 Commented Sep 13, 2013 at 1:17
  • 1
    You're also incrementing y twice. Commented Sep 13, 2013 at 1:17
  • 2
    Also, you want y < length, not y <= length. Commented Sep 13, 2013 at 1:18
  • Oops, thanks i did add the y++ twice. I removed the first y++, now it converts 2 characters rather than 1. The program so far will convert the first and letters entered (AB or BC etc) however when you enter more than two characters( ex. DOG) it will only convert the first two character, not the rest. It outputs the error, "java.lang.StringIndexOutOfBoundsException: String index out of range: 2" when I do so Commented Sep 13, 2013 at 1:24

5 Answers 5

1

See comments on code.

public static void main(String[] args) {

        BufferedReader myInput = new BufferedReader (new InputStreamReader (System.in));// Buffered Reader reads the number inputed 

        String key [] = {"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"};
        String keyA [] = {"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"};

        System.out.println("Enter a phrase: ");
        String phrase = "";

        try {
            phrase = myInput.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }

        int length = phrase.length();
        int y = 0, i = 0, num = 0;

        while (y < length) { // This should be y < length. Otherwise, it would throw a StringIndexOutOfBoundsException.
            i=0; // Re-initialize
            String letter = Character.toString(phrase.charAt(y));
//            y++; // Unecessary incremental
            while(!(letter.equalsIgnoreCase(key[i]))){
                i++;
            }
            num = i;
            System.out.print(keyA[num]);
            y++;
        }

    }
Sign up to request clarification or add additional context in comments.

Comments

1

Although this doesn't answer your problem, it answers your intention:

public static String rot13(String s) {
    String r = "";
    for (byte b : s.getBytes())
        r += (char)((b + 13 - 'A') % 26 + 'A');
    return r;
}

Your code is far too complicated for what it's doing. Really, all the work can be done in one line. Use byte arithmetic rather than array lookups etc. Simple/less code is always the best approach.

Please no comments about inefficiencies etc. This is a basic implementation that works (tested). The reader is free to improve on it as an exercise.

Comments

0

You're code will most likely break in your inner while loop as you are not resetting the value of i. By not doing so your gonna hit StringIndexOutOfBounds. I would recommend initialising i in your outer while loop or better yet just move int i = 0; inside the outer while loop.

Comments

0

I have implemented it in a different way, but it works as you expect, only for uppercase as in your example:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

public class WhileLoopIssue {

    public static void main( String[] args ) throws IOException {
        BufferedReader myInput = new BufferedReader( new InputStreamReader(
                System.in ) );// Buffered Reader reads the
                              // number inputed

        final List<String> letterList = Arrays.asList( "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" );

        System.out.println( "Enter a phrase: " );
        String phrase = myInput.readLine();

        final String[] letters = phrase.split( "" );     // Split input phrase
        final StringBuffer buffer = new StringBuffer();  // Variable to save letters. Could be a String as well.
        for ( int i = 0; i < letters.length; i++ ) {
            final int letterIndex = letterList.indexOf( letters[i] );  // Get the numeric value of the letter
            if ( letterIndex < 0 )  // Skip iteration if not found. Maybe a lowercase, or an empty String
                continue;

            final int nextLetterIndex = 13 + letterIndex;   // Actual value of the letter + 13
            if ( nextLetterIndex > letterList.size() ) {
                buffer.append( nextLetterIndex % letterList.size() );  // Actual value greater than the total number of letters in the alphabet, so we get the modulus for the letter
            } else {
                buffer.append( letterList.get( nextLetterIndex ) );  // Letter in the range, get it
            }
        }
        System.out.println( buffer.toString() );
    }
}

Comments

0

You need to reset i in each iteration. It may happen that first letter found toward the end of the array "key". Your code will find next input char there onward, I guess this is not what you want, and will not find that char and will throw SIOBException. I have changed the while loop, removed twice increment in variable y as well. Have a look

    while (y < length) {
        i = 0; //Every Time you want to search from start of the array 
                //so just reset the i.
        String letter = Character.toString(phrase.charAt(y));
        while(!(letter.equals(key[i]))){
            i++;
        }
        num = i;
        System.out.println(keyA[num]);
        y++;
    }

I am assuming what ever you enter as input is a phrase of ONLY upper-case alphabets, else you will come across the SIOBException as you you will not be able to locate that letter in your array.

Just on side note, instead of those arrays you should use some other data structures which are efficient for searching like hashmap. Your linear search across the array is not optimized.

1 Comment

y <= length would throw a StringIndexOutOfBoundsException. It has to be y < length

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.