kusalkw
kusalkw

Reputation: 19

Incorrect String encryption/decryption

I created this program to take a String as user input and swap each character of the word with another specific character to create a different word.

But the output is the same as the input.

import java.util.Scanner;

class Encrypt{

    public static void main(String[] args){

        char[] arrencrypt={'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'};
        char[] arrdecrypt={'Z','Y','X','W','V','U','T','S','R','Q','P','O','N','M','L','K','J','I','H','G','F','E','D','C','B','A'};

        Scanner sc=new Scanner(System.in);
        System.out.println("Enter the encrypted word:");
        String word=sc.nextLine();
        char[] arr=word.toCharArray();
        for(int i=0;i<arr.length;i++){
            for(int j=0;j<arrencrypt.length;j++){
                if(arr[i]==arrencrypt[j]){
                    arr[i]=arrdecrypt[j];
                }
            }
        }
        for(int k=0;k<arr.length;k++){
            System.out.print(arr[k]);
        }
    }
}

Upvotes: 1

Views: 161

Answers (6)

Rafał Sokalski
Rafał Sokalski

Reputation: 2007

Try this solution: First you initialize your map where key is encrypted letter and value is decrypted letter, than you provide your word and program replace letters and print output. Initialize map just convert ASCII number to Char and then to String to put it into map

public class Encrypt {

    public static void main(String[] args) {
       Map<Character, Character> map = initializeMap();
       StringBuilder output = new StringBuilder();
       Scanner sc = new Scanner(System.in);
       System.out.println("Enter the encrypted word:");
       String word = sc.nextLine();

       for (char s : word.toCharArray()) {
          output.append(map.get(s));
       }

       System.out.println(output.toString());
   }

   private static Map<Character, Character> initializeMap() {
      Map<Character, Character> map = new HashMap<>();
      for (int i = 65; i <= 90; i++) {
         map.put((char) i, (char) (155 - i));
      }
      for (int i = 97; i <= 122; i++) {
         map.put((char) i, (char) (219 - i));
      }

    return map;
}

Upvotes: 0

GBlodgett
GBlodgett

Reputation: 12819

Because of that in your arrencrypt and arrdecrypt all the chars are uppercase. This means that only upper case letters will be replaced. So either change

char[] arr=word.toCharArray();

To

char[] arr=word.toUpperCase().toCharArray();

Or make the chars lowercase in your arrays

With this change:

Input: "String"

Output: "HGIRMT"

Upvotes: 0

Chirag
Chirag

Reputation: 565

try this

import java.util.Scanner;

public class A {
    public static void main(String[] args) {
        char[] arrencrypt = { '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' };
        char[] arrdecrypt = { 'Z', 'Y', 'X', 'W', 'V', 'U', 'T', 'S', 'R', 'Q', 'P', 'O', 'N', 'M', 'L', 'K', 'J', 'I',
                'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A' };
        try (Scanner sc = new Scanner(System.in)) {
            System.out.println("Enter the encrypted word:");
            String word = sc.nextLine();
            char[] arr = word.toCharArray();
            for (int i = 0; i < arr.length; i++) {
                char ch = arr[i];
                if (ch >= 'A' && ch <= 'Z') {
                    for (int j = 0; j < arrencrypt.length; j++) {
                        if (arrencrypt[j] == arr[i]) {
                            arr[i] = arrdecrypt[j];
                            break;
                        }
                    }
                } else {
                    char temp = Character.toUpperCase(arr[i]);
                    for (int j = 0; j < arrencrypt.length; j++) {
                        if (arrencrypt[j] == temp) {
                            arr[i] = Character.toLowerCase(arrdecrypt[j]);
                            break;
                        }
                    }
                }
            }
            for (char ch : arr)
                System.out.print(ch);
        }
    }
}

Output

Enter the encrypted word:
Hello
Svool

as you have only upper case letters so it was failing

Upvotes: 0

Lino
Lino

Reputation: 19935

You can make your life a lot easier, if you just use simple character arithmetics. This eliminates the declaration of the two arrays and their iteration completly:

for(int i = 0; i < arr.length; i++){
    char c = arr[i];
    if(Character.isLowerCase(c)){
        arr[i] = (char) ('z' - c + 'a');
    } else if(Character.isUpperCase(c)){
        arr[i] = (char) ('Z' - c + 'A');
    }
}

This code will swap every letter in the alphabet with its "counterpart". E.g. 'Z' will be encrypted to 'A' and so on. I also added the same logic to support lowercase.

The "math" behind it is pretty easy. It works by converting the char to its ASCII-value. This is done implicitly in java. See the example:

int i = 'A';
System.out.println(i);

Will print 65 because the ASCII value of A is 65.

Upvotes: 2

Joop Eggen
Joop Eggen

Reputation: 109603

The gotten array is a duplicate of the internal char array of the String, so changing the array will not change the String. This indeed is a blessing.

    char[] arr = word.toCharArray();
    for (int i = 0; i < arr.length; i++) {
        for (int j = 0; j < arrencrypt.length; j++){
            if (arr[i] == arrencrypt[j]) {
                arr[i] = arrdecrypt[j];
                break;
            } else if (arr[i] == Character.toLowerCase(arrencrypt[j])) {
                arr[i] = Character.toLowerCase(arrdecrypt[j]);
                break;
            }
        }
    }
    String word2 = new String(arr);
    System.out.printf("Word '%s' is decrypted as: '%s'%n", word, word2);
    for(int k=0;k<arr.length;k++){
        System.out.print(arr[k]);
    }

Without break, the condition can become true with the changed char for a later j. And then it is converted again. Unfortunately here twice encrypting yield the original letter.


Alternatively

    String arrencrypt = "ABCDEFG...XYZ";
    String arrdecrypt = "ZYX...GFEDCBA";
    StringBuilder sb = new StringBuilder(word.length());
    for (int i = 0; i < word.length(); i++) {
        char ch = word.charAt(i);
        int j = arrencrypt.indexOf(ch);
        if (j != -1) {
            ch = arrdecrypt.charAt(j);
        }
        sb.append(ch);
    }
    String word2 = sb.toString();

Upvotes: 0

Bill the Lizard
Bill the Lizard

Reputation: 405965

The problem is in the inner loop.

for(int j=0;j<arrencrypt.length;j++){
    if(arr[i]==arrencrypt[j]){
        arr[i]=arrdecrypt[j];
    }
}

This works for inputs that are found in the second half of the alphabet. But when a letter is found in the first half of the alphabet, first it gets replaced, then the loop keeps going and finds the new letter and replaces it with the original letter. (A gets replaced with Z, but then the Z is found in a later iteration of the loop and is replaced with A.)

Add a break to get out of this loop after a single replacement has been done.

for(int j=0;j<arrencrypt.length;j++){
    if(arr[i]==arrencrypt[j]){
        arr[i]=arrdecrypt[j];
        break;
    }
}

Upvotes: 3

Related Questions