0

I'm relatively new to java (and programming in general), and I'm trying to improve. There's this project I'm trying to work on (not school related) that calls for the creation of a Caesar Cipher based on a string they entered, the direction they wish to shift, and by the number of positions in the alphabet they wish to shift by. AN example is below:

NORMAL ALPHABET: A B C D E F G H

SHIFT RIGHT BY 2: Y Z A B C D E F

SHIFT LEFT BY 3: D E F G H I J K

The thing is though, it is simple to do it if it's just a single character, but I've got no idea on how to proceed without using an array, which I'm not keen on. Any advice?

Update

I've managed to compile some code (through hours and hours of help) into the following below, however I'm encountering two errors with my main. Here is my methods file:

import java.util.Scanner;

public class HW4Methods
{
   public static String readString(Scanner kb)
   {

      Scanner kbTwo = new Scanner(System.in);

      System.out.print("Please Enter A String: ");
      String userString = kbTwo.nextLine();

      while(userString.equals(null) || (userString.isEmpty()))
      {
         System.out.print("Field Cannot Be Empty. Please Re-Enter: ");
         userString = kbTwo.nextLine();
      }
      return userString;
   }

   public static int readAmountToShift(Scanner kb)
   {
      int amountToShift;

      Scanner kbThree = new Scanner(System.in);

      System.out.print("Please Enter the Amount You Wish To Shift: ");
      amountToShift = kb.nextInt();

      while((amountToShift < 0) || (amountToShift > 2000000000))
      {
         System.out.print("Number Not Within Specified Parameters. Please Re-Enter: ");
         amountToShift = kb.nextInt();
      }

      return amountToShift;
   }

   public static String readDirection(Scanner kb)
   {

      Scanner kbFour = new Scanner(System.in);

      System.out.print("Enter the Direction You Wish to Shift (Left or Right): ");
      String shiftD = kb.next();

      while(!shiftD.equalsIgnoreCase("left") && (!shiftD.equalsIgnoreCase("right")))
      {
        System.out.print("Invalid Direction. Enter the Direction You Wish to Shift (Left or Right):  ");
        shiftD = kbFour.next();
      }

      return shiftD;
   }

   public static int menu(Scanner kb)
   {
      int userChoice;
      Scanner kbFive = new Scanner(System.in);

      System.out.println("Please Choose From the Following:");
      System.out.println("1. Enter New String.");
      System.out.println("2. Encrypt String.");
      System.out.println("3. Decrypt String.");
      System.out.println("4. Quit.");
      System.out.println("Please Enter Your Choice: ");
      userChoice = kbFive.nextInt();

      while((userChoice < 1)||(userChoice > 4))
      {
        System.out.print("Invalid Menu Choice. Please Try Again.");
        userChoice = kbFive.nextInt();
      }
      return userChoice;
   }        
   public static String encryptString(String origString, int amount, String direction)
   {
     origString = "";
     for(int i=0;i < origString.length();i++)
     {
      char a = origString.charAt(i);
      if(direction.equalsIgnoreCase("right"))
      {
         if(a + amount > 122)
         {
            origString += 97 +(a + amount - 123);
         }
         else if(a + amount > 90)
         {
            origString += 65+(a + amount - 91);
         }
         else if(a + amount > 97 && a + amount <= 122)
         {
            origString += (char)(a + amount);
         }
         else if(a + amount > 65 && a + amount <= 90)
         {
            origString += (char)(a + amount);
         }
     }
     if(direction.equalsIgnoreCase("left"))
     {
         if(a+ amount < 65)
         {
            origString += (char)(90);
         }
         else if(a - amount < 91)
         {
            origString += 113 +(a - amount + 91);
         }
         else if(a + amount >= 97 && a + amount <= 122)
         {
            origString += (char)(a - amount);
         }
         else if(a + amount <= 65 && a + amount >= 91)
         {
            origString += (char)(a - amount);
         }   
     }
    }
    return origString; 

   }  

   public static String decryptString(String encryptedString, int amount, String direction)
   {
     String decrypt = "";
     for(int i=0;i < encryptedString.length();i++)
     {
      char a = encryptedString.charAt(i);
      if(direction.equals("right"))
      {
         if(a - amount < 97)
         {
            decrypt += (char)(122) - (a - amount - 123);
         }
         else if(a - amount < 65)
         {
            decrypt += 90 - ((char)(a + amount) - 91);
         }
         else if(a - amount >= 97 && a - amount <= 122)
         {   
            decrypt += (char)(a - amount);
         }   
         else if(a - amount >= 65 && a - amount <= 90)
         {   
            decrypt += (char)(a - amount);
         }    

     }
         if(direction.equals("left"))
         {
            if(a + amount > 90)
            {   
               decrypt += 65 +((char)(a - amount) - 64);
            }
            else if(a + amount > 122)
            {   
               decrypt += 97 + ((char)(a + amount) - 97);
            }
            else if(a + amount >= 65 && a + amount <= 91)
            {   
               decrypt += (char)(a + amount);
            }
            else if(a + amount >= 97 && a + amount <= 122)
            {   
               decrypt += (char)(a + amount);
            }
         }    
      }
    return decrypt; 

   }  
   public static void display(String stringOne, String stringTwo)
   {
      System.out.println(stringOne + stringTwo);
   }



}

And here is my main (in a different folder):

import java.util.Scanner;

public class CSCD210HW4
{
   public static void main(String [] args)
   {
      int choice, amount;
      Scanner kb = new Scanner(System.in);
      String direction, origString, encryptedString, decryptedString;      

      origString = HW4Methods.readString(kb);
      amount = HW4Methods.readAmountToShift(kb);
      direction = HW4Methods.readDirection(kb);
      encryptedString = HW4Methods.encryptString(origString, amount, direction);
      HW4Methods.display("Your encrypted string is ", encryptedString);

      do
      {
         choice = HW4Methods.menu(kb);

         switch(choice)
         {
            case 1:  origString = HW4Methods.readString(kb);
                     break;

            case 2:  amount = HW4Methods.readAmountToShift(kb);
                     direction = HW4Methods.readDirection(kb);
                     encryptedString = HW4Methods.encryptString(origString, amount, direction);
                     HW4Methods.display("Your encrypted string is ", encryptedString);
                     break;

            case 3:  direction = HW4Methods.readDirection(encryptedString);
                     amount = HW4Methods.readAmountToShift(encryptedString);
                     decryptedString = HW4Methods.decryptString(encryptedString, amount, direction);
                     HW4Methods.display("Your decrypted string is ", decryptedString);
                     break;

            case 4:  System.out.println("Thanks for playing");

         }// end switch

      }while(choice != 4);

   }// end main
}// end class

I am encountering two errors in main, listed below:

CSCD210HW4.java:33: error: incompatible types: String cannot be converted to Scanner
                     amount = HW4Methods.readAmountToShift(encryptedString);
                                                           ^
CSCD210HW4.java:32: error: incompatible types: String cannot be converted to Scanner
            case 3:  direction = HW4Methods.readDirection(encryptedString);
                                                          ^

I don't know why I'm getting these errors, and it's driving me crazy.

  • "it is simple to do it if it's just a single character, but..." If _what_ is just a single character? Is _it_ a character that you read from a file? Is _it_ a character from the command line? Is _it_ in a Swing text box? – Solomon Slow Oct 27 '14 at 21:44
  • "...(not school related)...I've got no idea on how to proceed without using an array, which I'm not keen on." Yeah, only the thing is, it's very common for a teacher to say, "you may not use an array," but what is unusual is for somebody to be "not keen on" using an array to hold a fixed-length sequence of anything. – Solomon Slow Oct 27 '14 at 21:49

1 Answers1

2

Each character is associated with a number. Check this to see how to convert char to a java string. Idea is that you can get a range in number form without making an array.

If you know their bounds, you can use mod (%) to wrap around. For example:

If we have B = 66. Index(B) - 64 = 2. (That is order in the list of numbers from 1 - 26).

Shift = -5. So the answer is supposed to be: W (23rd)

(Index(B)-64-5)%26 = 23.

Just make sure to start either at 1 or 0 for A. If you start A at 1, you need to add 1.

UPDATE

Since you spend a lot of time on this, let me give you a simple example of what it could look like. this doesn't have all the exceptions checks and validations that good code should have:

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    System.out.println("Enter the string to encrypt: ");
    String string = scanner.nextLine().toUpperCase();
    System.out.println("Enter offset");
    int offset = Integer.parseInt(scanner.nextLine());

    System.out.println("Encrypting " + string + " with offset: " + offset);
    StringBuilder sb = new StringBuilder();

    for (char c : string.toCharArray())
    {
        //broken down for clarity
        int order = ((int)c) - 65 + offset;
        //that strange addition is to force negative modulo to the answer that we want.
        int newOrder = (order % 26) + ((order < 0) ? 26 : 0); 
        int backToAscii = newOrder + 65;

        sb.append(Character.toString((char)backToAscii));
    }
    System.out.println(sb.toString());
}

An example usage:

Enter the string to encrypt: 
Bulka
Enter offset
-5
Encrypting BULKA with offset: -5
WPGFV

OR

Enter the string to encrypt: 
Bulka
Enter offset
5
Encrypting BULKA with offset: 5
GZQPF
Community
  • 1
  • 1
lupus137
  • 383
  • 3
  • 10
  • Would I wrap around by using %26 since there are 26 letters each for the capital and lowercase ascii characters? – HockeyFlakey Oct 27 '14 at 21:34
  • Sorry for taking a bit. Yes, as long as you understand that you are starting at 65 with only capital. If you are doing both, then you would need to accommodate for intermediate characters that are not part of the rotation. If you are doing only capital or only lowercase it is easier. Also, remember that using %26 you are assuming that A starts at 0, so that Z = 25 and next time you reach around to 26, it would be 26%26 --> 0. – lupus137 Oct 27 '14 at 21:56