#java #string #exception #indexoutofboundsexception
Вопрос:
Я продолжаю получать строковый индекс из-за исключения bound: 22. Кто-нибудь может сказать мне, что я делаю не так? Вот код:
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);
}
}
То, что я пытаюсь здесь сделать, — это написать функцию, которая принимает строку и возвращает новую строку со всеми удаленными гласными.
Ответ №1:
Когда вы делаете строку короче, вы уменьшаете ее длину. Но вы сохраняете начальную длину строки и используете ее в качестве привязки цикла.
Измените i < lengthStr
на i < str.length()
.
Это устраняет часть проблемы, которая заключается IndexOfOfBoundsException
в том, что . Другая проблема заключается в том, что, удалив символ, вам нужно убедиться, что вы также полностью проверили следующий символ.
Рассмотрим строку aa
:
- Вы бы нашли
a
в позиции 0 и удалили ее. - Следующий
a
теперь находится в позиции 0; вы бы пропустили проверку, является ли это гласной - Затем вы перейдете на контрольную позицию 1.
Это сработало бы, если бы вы строили гласные в порядке проверки (например aeiou
), но не в целом.
Удалив символ, вам нужно прекратить зацикливание на других гласных, а затем уменьшить i
, чтобы убедиться, что вы проверяете символ сразу после того, который вы удалили:
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.
}
}
}
Однако это очень неэффективный способ решения проблемы: каждый раз, когда вы удаляете одну гласную, вы перестраиваете остальную часть строки, включая все гласные, которые вы собираетесь впоследствии удалить.
Если вы хотите сделать это без регулярных выражений, лучший способ-создать a StringBuilder
и добавлять в него только не гласные:
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();
где isVowel
метод, который возвращает, является ли данное char
гласным, например
boolean isVowel(char c) {
return "aAeEiIoOuU".indexOf(c) >= 0;
}
Комментарии:
1. Прежде чем я прочитал вторую часть вашего ответа, я реорганизовал код, как вы сказали здесь, за исключением того, что я использовал i = 0 вместо —i. Но теперь я вижу, что не было необходимости снова перебирать всю строку. Спасибо вам за быстрый ответ.
Ответ №2:
Попробуй это.
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());
}
Ответ №3:
public static String disemvowel(String str) {
return str.replaceAll("[aeiou]", "");
}
это то, что тебе нужно. Если вам также нужен верхний регистр, используйте "[aeiouAEIOU]"
тогда. Это сделает результирующую строку всего за один проход через исходную строку.