Hartja
Hartja

Reputation: 57

Java replace method problems

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?

Upvotes: 2

Views: 475

Answers (3)

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(); 
} 

Upvotes: 0

Rahul
Rahul

Reputation: 106

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.

Upvotes: 0

Tunaki
Tunaki

Reputation: 137209

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();
} 

Upvotes: 6

Related Questions