2

My goal is to change any form of the word "java" in a sentence to "JAVA".I've got everything done but my code won't read in mixed cases for example:JaVa, JAva,etc. I know I am suppose to use toUpperCase and toLowerCase or equalsIgnoreCase but I am not sure how to use it properly. I am not allowed to use replace or replace all, teacher wants substring method.

    Scanner input=new Scanner(System.in);
    System.out.println("Enter a sentence with words including java");
    String sentence=input.nextLine();

    String find="java";
    String replace="JAVA";
    String result="";
    int n;
    do{
        n=sentence.indexOf(find);
        if(n!=-1){
            result =sentence.substring(0,n);
            result=result +replace;
            result = result + sentence.substring(n+find.length());
            sentence=result;            
        }
    }while(n!=-1);
    System.out.println(sentence);
}

}

ben
  • 97
  • 1
  • 1
  • 10

3 Answers3

4

You can't do that using String.indexOf because it is case sensitive.

The simple solution is to use a regex with a case insensitive pattern; e.g.

Pattern.compile(regex, Pattern.CASE_INSENSITIVE).matcher(str).replaceAll(repl);

That also has the benefit of avoiding the messy string-bashing you are currently using to do the replacement.


In your example, your input string is also valid as a regex ... because it doesn't include any regex meta-characters. If it did, then the simple workaround is to use Pattern.quote(str) which will treat the meta-characters as literal matches.

It is also worth nothing that String.replaceAll(...) is a "convenience method" for doing a regex replace on a string, though you can't use it for your example because it does case sensitive matching.


For the record, here is a partial solution that does the job by string-bashing. @ben - this is presented for you to read and understand ... not to copy. It is deliberately uncommented to encourage you to read it carefully.

// WARNING ... UNTESTED CODE
String input = ...
String target = ...
String replacement = ...
String inputLc = input.lowerCase();
String targetLc = target.lowerCase();
int pos = 0;
int pos2;
while ((pos2 = inputLc.indexOf(targetLc, pos)) != -1) {
    if (pos2 - pos > 0) {
        result += input.substring(pos, pos2);
    }
    result += replacement;
    pos = pos2 + target.length();
}
if (pos < input.length()) {
    result += input.substring(pos);
}

It probably be more efficient to use a StringBuilder instead of a String for result.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Sorry! forgot to mention I can't use replaceAll. Teacher wants me to use substring method only. – ben Dec 02 '14 at 02:21
  • @Stephen C, there is a way to use `String.replaceAll` in a case-insensitive manner by including `"(?i)"`, as I've demonstrated in my answer – nem035 Dec 02 '14 at 03:10
  • @ben - Actually, I expect your teacher wants you work out the whole thing for your self!! – Stephen C Dec 02 '14 at 06:45
0

A quick solution would be to remove your do/while loop entirely and just use a case-insensitive regex with String.replaceAll(), like:

sentence = sentence.replaceAll("(?i)java", "JAVA");
System.out.println(sentence);

Or, more general and according to your variable namings:

sentence = sentence.replaceAll("(?i)" + find, replace);
System.out.println(sentence);

Sample Program

EDIT:

Based on your comments, if you need to use the substring method, here is one way.

First, since String.indexOf does case-sensitive comparisons, you can write your own case-insensitive method, let's call it indexOfIgnoreCase(). This method would look something like:

// Find the index of the first occurrence of the String find within the String str, starting from start index
// Return -1 if no match is found
int indexOfIgnoreCase(String str, String find, int start) {
    for(int i = start; i < str.length(); i++) {
        if(str.substring(i, i + find.length()).equalsIgnoreCase(find)) {
            return i;
        }
    }
    return -1;
}

Then, you can use this method in the following manner.

You find the index of the word you need, then you add the portion of the String before this word (up to the found index) to the result, then you add the replaced version of the word you found, then you add the rest of the String after the found word.

Finally, you update the starting search index by the length of the found word.

String find = "java";
String replace = "JAVA";
int index = 0;
while(index + find.length() <= sentence.length()) {
    index = indexOfIgnoreCase(sentence, find, index);       // use the custom indexOf method here
    if(index == -1) {
        break;
    }
    sentence = sentence.substring(0, index) +               // copy the string up to the found word
               replace +                                    // replace the found word
               sentence.substring(index + find.length());   // copy the remaining part of the string
    index += find.length();
}
System.out.println(sentence);

Sample Program

You could use a StringBuilder to make this more efficient since the + operator creates a new String on each concatenation. Read more here

Furthermore, you could combine the logic in the indexOfIgnoreCase and the rest of the code in a single method like:

String find = "java";
String replace = "JAVA";
StringBuilder sb = new StringBuilder();
int i = 0;
while(i + find.length() <= sentence.length()) {
    // if found a match, add the replacement and update the index accordingly
    if(sentence.substring(i, i + find.length()).equalsIgnoreCase(find)) {
        sb.append(replace);
        i += find.length();
    } 
    // otherwise add the current character and update the index accordingly
    else {
        sb.append(sentence.charAt(i));
        i++;
    }
}
sb.append(sentence.substring(i)); // append the rest of the string
sentence = sb.toString();
System.out.println(sentence);
Community
  • 1
  • 1
nem035
  • 34,790
  • 6
  • 87
  • 99
  • The problem with this is that you are "normalizing" the inter-word spacing as a side effect. Also, it won't work if there is a punctuation character immediately before or after the `find` word. – Stephen C Dec 02 '14 at 02:12
  • yes you are correct, i figured out a much better solution – nem035 Dec 02 '14 at 02:14
  • Sorry! forgot to mention I can't use replaceAll. Teacher wants me to use substring method only. – ben Dec 02 '14 at 02:21
  • @ben, check out my edit. I believe it is what you are looking for. – nem035 Dec 02 '14 at 02:56
  • @nem thank you for all your help! Unfortunately, I haven't learned indexOfIgnoreCase and I'm not allowed to use stringbuilder either(my fault for not stating more clearly on my directions, running out of time atm)so I couldn't use any of your suggestions. Really appreciate the help! – ben Dec 02 '14 at 04:36
0

you are allowed to use toUpperCase() ? try this one

 Scanner input=new Scanner(System.in);
    System.out.println("Enter a sentence with words including java");
    String sentence=input.nextLine();

    String find="java";
    String replace="JAVA";
    String result="";

    result = sentence.toLowerCase();
    result = result.replace(find,replace);
    System.out.println(result);
}

reply with the result :))

Update : Based on

I've got everything done but my code won't read in mixed cases for example:JaVa, JAva,etc.

you can use your code

   Scanner input=new Scanner(System.in);
    System.out.println("Enter a sentence with words including java");
    String sentence=input.nextLine();

    String find="java";
    String replace="JAVA";
    String result="";
    int n;
    do{
        //for you to ignore(converts the sentence to lowercase) either lower or upper case in your sentence then do the nxt process
        sentence = sentence.toLowerCase();

        n=sentence.indexOf(find);
        if(n!=-1){
            result =sentence.substring(0,n);
            result=result +replace;
            result = result + sentence.substring(n+find.length());
            sentence=result;            
        }
    }while(n!=-1);
    System.out.println(sentence);
}

Update 2 : I put toLowerCase Convertion outside the loop.

public static void main(String[] args){

            String sentence = "Hello my name is JAva im a jaVa Man with a jAvA java Ice cream";
            String find="java";
            String replace="JAVA";
            String result="";
            int n;
            //for you to ignore(converts the sentence to lowercase) either lower or upper case in your sentence then do the nxt process
            sentence = sentence.toLowerCase();
            System.out.println(sentence);

            do{


                n=sentence.indexOf(find);
                if(n!=-1){
                    result =sentence.substring(0,n);
                    result=result +replace;
                    result = result + sentence.substring(n+find.length());
                    sentence=result;            
                }
            }while(n!=-1);

            System.out.println(sentence);
    }

RESULT

hello my name is java im a java man with a java java ice cream

hello my name is JAVA im a JAVA man with a JAVA JAVA ice cream

Secondo
  • 451
  • 4
  • 9
  • sorry! can't use replace, am only allowed to use substring method. – ben Dec 02 '14 at 02:53
  • the updated part will not work because it will convert the whole sentence to lower case thus altering more than just string matching variations of "java" – nem035 Dec 02 '14 at 03:08
  • what do you want to do with the sentence? i thought that you want to convert all (java, JavA, jaVa etc.. ) inside of your sentence to JAVA(uppercase). – Secondo Dec 02 '14 at 03:14
  • I convert the sentence to lowercase to ignore the case sensitivity – Secondo Dec 02 '14 at 03:17
  • @Secondo thank you so much! something as simple as that... Im still new to programming so I really appreciate the help! – ben Dec 02 '14 at 04:41
  • Im Glad that i was able to help you :)) it would be great if i got my First Accepted Answer :) :P Happy Coding :) – Secondo Dec 02 '14 at 04:43
  • 2
    Interesting. The final answer is wrong of course, but we'll leave it for Ben's teacher / marker to point out the flaw. :-) – Stephen C Dec 02 '14 at 06:47
  • @StephenC Hi sir im open for correction :) can you state why is it wrong ? so that if ever i can fix this TIA – Secondo Dec 02 '14 at 06:55
  • @Secondo - See my updated answer. You should be able to figure out your mistake from there. – Stephen C Dec 02 '14 at 07:10
  • @StephenC thanks bro +1 for explanation indeed you're right. im sorry i wasnt able to explain it to Ben – Secondo Dec 02 '14 at 07:21