0

I keep getting String index out of bound: 22 exception. Can anyone tell me what am I doing wrong? Here is the code:

class Troll {
    private static final char[] VOWELS = {'a', 'A', 'e', 'E', 'i', 'I', 'o', 'O', 'u', 'U'};

    public static String disemvowel(String str) {
        int lengthStr = str.length();
        int lengthVOWELS = VOWELS.length;

        for (int i = 0; i < lengthStr; ++i)
            for (char vowel : VOWELS)
                if (str.charAt(i) == vowel)
                    str = removeChar(str, i);

        return str;
    }

    private static String removeChar(String str, int index) {
        return str.substring(0, index) + str.substring(index + 1);
    }
}

What I am trying to do here is to write a function that takes a string and return a new string with all vowels removed.

0

3 Answers 3

1

When you make a string shorter, you reduce its length. But you're storing the initial string length, and using it as the loop bound.

Change i < lengthStr to i < str.length().


That fixes part of the problem, which is the IndexOfOfBoundsException. The other problem is that, having removed a character, you need to make sure that you check the next character fully too.

Consider the string aa:

  • You'd find the a at position 0, and remove it.
  • The next a is now at position 0; you'd skip over checking if it's a vowel
  • You'd move onto check position 1 next.

It would work if you string contained vowels in order of checking (e.g. aeiou), but not in general.

Having removed a character, you need to stop looping over other vowels, and then decrement i, in order to make sure that you check the character immediately following the one you removed:

    for (int i = 0; i < lengthStr; ++i) {
        for (char vowel : VOWELS) {
            if (str.charAt(i) == vowel) {
                str = removeChar(str, i);
                // Decrement i, so it gets incremented back to the
                // same value on the next iteration of the outer loop.
                --i;
                break;  // Break out of vowels loop.
            }
        }
    }

However, this is a very inefficient way to approach the problem: every time you remove one vowel, you rebuild the rest of the string, including all the vowels you're going to subsequently remove.

If you want to do this without regex, the best way is to create a StringBuilder, and only add the non-vowels to it:

StringBuilder sb = new StringBuilder(lengthStr);
for (int i = 0; i < lengthStr; ++i) {
  char c = str.charAt(i);
  if (!isVowel(c) {
    sb.append(c);
  }
}
str = sb.toString();

where isVowel is a method which returns whether the given char is a vowel, e.g.

boolean isVowel(char c) {
  return "aAeEiIoOuU".indexOf(c) >= 0;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Before I read the second part of your answer, I reorganised the code as you told here except I used i = 0 instead of --i. But I see now it was unnecessary to loop over the entire string again. Thank you for quick response.
0

Try this.

private static final String VOWELS = "aAeEiIoOuU";

public static String disemvowel(String str) {
    return Stream.of(str.split(""))
        .filter(c -> !VOWELS.contains(c))
        .collect(Collectors.joining());
}

Comments

0
    public static String disemvowel(String str) {
        return str.replaceAll("[aeiou]", "");
    }

is what you need. If you want also the uppercase, use "[aeiouAEIOU]" then. That will make the resulting string in just one pass through the original string.

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.