0

I'm trying to search and reveal unknown characters in a string. Both strings are of length 12.

Example:

     String s1 = "1x11222xx333";
     String s2 = "111122223333"

The program should check for all unknowns in s1 represented by x|X and get the relevant chars in s2 and replace the x|X by the relevant char.

So far my code has replaced only the first x|X with the relevant char from s2 but printed duplicates for the rest of the unknowns with the char for the first x|X.

Here is my code:

    String VoucherNumber = "1111x22xx333";
    String VoucherRecord = "111122223333";
    String testVoucher = null;
    char x = 'x'|'X';

    System.out.println(VoucherNumber); // including unknowns


            //find x|X in the string VoucherNumber
            for(int i = 0; i < VoucherNumber.length(); i++){

                   if (VoucherNumber.charAt(i) == x){

                       testVoucher = VoucherNumber.replace(VoucherNumber.charAt(i), VoucherRecord.charAt(i));

                   }


            }

                     System.out.println(testVoucher); //after replacing unknowns
        }


    }
6
  • Strings are immutable in Java. You cannot replace characters in a String, you have to build a new string, or use a StringBuilder, which is mutable. Commented Feb 8, 2017 at 6:32
  • 2
    char x = 'x'|'X'; what are you trying to do here? Commented Feb 8, 2017 at 6:32
  • char x = 'x'|'X' // To handle user input if either x|X is entered. Commented Feb 8, 2017 at 6:37
  • 3
    @Latz Unfortunately you can only store one char inside a char. 'x' | 'X' evaluates to the bitwise-OR of the two char values 'x' and 'X', which equals 120 (or in char form, simply 'x'). If you want to compare to two chars, you're gonna have to do two comparisons in your if condition. Commented Feb 8, 2017 at 6:52
  • 1
    Also, String.replace(char, char) doesn't do what you think it does; take a look at the docs. (It replaces all occurrences of that char, not just one) Commented Feb 8, 2017 at 6:54

3 Answers 3

1

I am always a fan of using StringBuilders, so here's a solution using that:

private static String replaceUnknownChars(String strWithUnknownChars, String fullStr) {
    StringBuilder sb = new StringBuilder(strWithUnknownChars);
    while ((int index = Math.max(sb.toString().indexOf('x'), sb.toString().indexOf('X'))) != -1) {
        sb.setCharAt(index, fullStr.charAt(index));
    }

    return sb.toString();
}

It's quite straightforward. You create a new string builder. While a x or X can still be found in the string builder (indexOf('X') != -1), get the index and setCharAt.

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

2 Comments

toUpperCase() on the string is dangerous in corner cases. For example, in most locales, if the string contains the German letter ß, it will become SS, two chars, and will therefore shift the indices of the following chars, so you may be setting a char at the wrong index. Rather only change the case of the char you are looking at. Or just search for both (small) x and (capital) X.
@Sweeper bad timing ^^ I have just removed the comment since I didn't like the idea to search both everytime, your twin loop will check only the good amout of time. Save the value into an integer ;) while( (int index = Math.max ... ) != 1)
0

Your are using String.replace(char, char) the wrong way, the doc says

Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.

So you if you have more than one character, this will replace every one with the same value.

You need to "change" only the character at a specific spot, for this, the easiest is to use the char array that you can get with String.toCharArray, from this, this is you can use the same logic.

Of course, you can use String.indexOf to find the index of a specific character

Note : char c = 'x'|'X'; will not give you the expected result. This will do a binary operation giving a value that is not the one you want.

The OR will return 1 if one of the bit is 1.

0111 1000 (x)
0101 1000 (X)
OR
0111 1000 (x)

But the result will be an integer (every numeric operation return at minimum an integer, you can find more information about that)

You have two solution here, you either use two variable (or an array) or if you can, you use String.toLowerCase an use only char c = 'x'

4 Comments

Funnily, char c = 'x'|'X'; can be compiled as a statement. I agree with you that it does not make sense.
@OleV.V. Damn, off course... this is a simple operator, so indeed this compile (but return an int) but not give the expected result. Well, luckily: 0111 1000 | 0101 1000 still give 0111 1000 (x) so it works with lowercase test. Add this information in the question (but a bit vague)
— which can be good or bad: it might deceive someone into thinking that this works (I’d personally have preferred it didn’t compile).
@OleV.V. Well, it doesn't because of the result being an integer. But character are just numeric value, so I understand the JVM on this, of course, using a character value instead of the numerical value could be used to prevent this.
0

With the level of details from the description the solution is less complex than imagine.

String voucherRecord = "111122223333";
String voucherNumber = "1111x22xx333";
String testVoucher = voucherNumber.replace(voucherNumber, voucherRecord);

Additional details on what prevents replacing voucherNumber with voucherRecord definitely increase complexity.

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.