2

I am trying to do a project for my computer science class called "Encryption/Decryption"

The code goes as follows

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

public class Tester { 
public static void main(String args[]) { 
    Scanner kbReader = new Scanner(System.in); 
    System.out.print("Enter a sentence that is to be encrypted: "); 
    String sntnc = kbReader.nextLine(); 
    System.out.println("Original Sentence = " + sntnc); 

    Crypto myCryptObj = new Crypto(); 
    String encryptdSntnc = myCryptObj.encrypt(sntnc); 
    System.out.println("Encrypted sentence = " + encryptdSntnc); 

    String decryptdSntnc = myCryptObj.decrypt(encryptdSntnc); 
    System.out.println("Decrypted sentence = " + decryptdSntnc); 
  } 
} 

class Crypto { 
 public String encrypt(String sntnc) { 
    sntnc = sntnc.replace("m", "ssad"); 
    sntnc = sntnc.replace("b", "dug>?/");
    sntnc = sntnc.replace("g", "jeb..w"); 
    sntnc = sntnc.replace("v", "ag',r"); 
    return sntnc; 
} 

public String decrypt(String sntnc) { 
    sntnc = sntnc.replace("ag',r", "v"); 
    sntnc = sntnc.replace("ssad", "m"); 
    sntnc = sntnc.replace("jeb..w", "g");  
    sntnc = sntnc.replace("dug>?/", "b"); 
    return sntnc; 
  } 
}

The problem isn't in the Tester class, it's in the Crypto class.

The input is: This is a very big morning. And the code should output:

Enter a sentence that is to be encrypted: This is a very big morning.
Original Sentence: This is a very big morning.
Encrypted sentence: This is a ag',rery dug>?/ijeb..w ssadorninjeb..w.
Decrypted sentence: This is a very big morning.

But instead the Encrypted sentence line is printing:

This is a ag',rery dujeb..w>?/ijeb..w ssadorninjeb..w.

The sntnc.replace method is replacing the already replaced letters. How do I fix it to where it won't replace things twice?

2
  • replaceAll is for regular expressions. Are you using regular expressions? If not (or if you don't know) you probably want to use replace instead. Commented Feb 8, 2016 at 19:30
  • @tobias_k Oh, I meant to fix that and take off the replaceAll. I was just messing around and seeing if that would fix it. But even with replace it still doesn't work. Commented Feb 8, 2016 at 19:33

3 Answers 3

6

The problem comes from your logic of replacing the strings:

sntnc = sntnc.replaceAll("b", "dug>?/");  // <-- replaces with a "g" here
sntnc = sntnc.replaceAll("g", "jeb..w");  // <-- so that "g" is also getting replaced here

A simple solution is to drop using replaceAll. Making your code works by re-ordering the replaceAll calls is very fragile: you don't know that in the future someone will change what is getting replaced and break everything.

The solution is much simpler when building the String by iterating over the characters. Because we have an distinct temporary container when building the Strings, there are no conflicts when the replacements are happening.

public String encrypt(String sntnc) { 
     StringBuilder sb = new StringBuilder();
     for (char ch : sntnc.toCharArray()) {
         if (ch == 'm') sb.append("ssad");
         else if (ch == 'b') sb.append("dug>?/");
         else if (ch == 'g') sb.append("jeb..w");
         else if (ch == 'v') sb.append("ag',r");
         else sb.append(ch);
     }
     return sb.toString();
} 
Sign up to request clarification or add additional context in comments.

4 Comments

Assuming that the "encryptions" are never substrins of each other; doing the same for decryption with variable length codes, would be tricky.
This works, thank you! So is there no easy way to actually use replace here, since it is always going to replace no matter what?
@Hartja Yes. You can't tell that the character you will replace isn't part of the encrypted String already (this is because there's not intermediate distinct structure, replace works in-place)
@tobias_k True, but there wouldn't be an assignment anymore otherwise ;).
0

Instead of using sntnc = sntnc.replaceAll("m", "ssad"); Try replacing each character with the appropriate encryption code and then save it in another string and return it.

`String s = "xyz";
for(int i = 0; i < sntnc.length(); i++)
{
   char c = sntnc.charAt(i);
   // Do your code here saving it in a new string say sntnc2
}`
   return sntnc2;

May not be the most efficient method but using replaceAll("a","c") as you've done replaces each character a with c from the start to the end of the string.

2 Comments

return from within a loop?
Sorry, my mistake. Edited it out.
0

Your problem is that one replace intersect with other:

sntnc = sntnc.replace("g", "jeb..w"); 
sntnc = sntnc.replace("b", "dug>?/");

The first include a b and the second include a g even reorder the replaces will don't work.

You have to do all your replaces at once, try:

class Crypto { 
 public String encrypt(String sntnc) {    

    Pattern p = Pattern.compile("(m|g|b|v)");
    Matcher m = p.matcher(sntnc);
    StringBuffer sb = new StringBuffer();

    while (m.find()) {
        if(m.group(1).equals("m"))
            m.appendReplacement(sb, "ssad");
        if(m.group(1).equals("g"))
            m.appendReplacement(sb, "jeb..w");
        if(m.group(1).equals("b"))
            m.appendReplacement(sb, "dug>?/");
        if(m.group(1).equals("v"))
            m.appendReplacement(sb, "ag',r");
    }

    m.appendTail(sb);

    return sb.toString(); 
} 

Comments

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.