2014-09-16 5 views
1

Для моего класса CompSci мы делаем . Вы бы скорее? функция для нашего проекта chatbot. Метод String.split() хорошо работает для этого, но мы получаем бонусные баллы, если мы сможем это сделать без него. Я решил это сделать, просто создав метод, который реплицировал String.split.Репликация String.split: OutOfBoundsException

private String[] separate (String phrase, String omit1, String omit2) 
{ 
    int c = 0; 

    //gets rid of leading and trailing whitespace, replaces target characters 
    //with the # character 
    phrase = phrase.trim(); 
    phrase = phrase.replace(omit1, "#"); 
    phrase = phrase.replace(omit2, "#"); 

    //detects the number of phrases to be included in the array 
    for (int i = 0; i < phrase.length(); i++) 
     if (phrase.charAt(i) == '#') 
      c++; 

    //creates array list based on number of phrases 
    String[] phraseList = new String[c]; 
    c = 0; 

    //builds phrases from characters found between occurrences 
    //of the # character 
    for (int i = 0; i < phrase.length(); i++) 
    { 
     if (phrase.charAt(i) == '#') 
      c++; 
     else if (phrase.charAt(i) != '#') 
      phraseList[c] += phrase.charAt(i); 
    } 

    return phraseList; 

} 

Всякий раз, когда я использую этот метод с фразой «Вы предпочитаете есть чай, кушать печенье или толкать?» (Omit1 быть «» и omit2 быть „или“) он бросает это исключение:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 
    at Magpie.separate(Magpie.java:306) 
    at Magpie.getResponse(Magpie.java:44) 
    at MagpieRunner.main(MagpieRunner.java:24) 

Я понимаю, что это что-то делать со счетчиком для phraseList массива, но мои попытки исправить до сих пор это не помогло.

Любая помощь?

+0

Последний 'if-else-if' должен быть просто' if-else', потому что вы просто проверяете одно и то же условие дважды, второй раз отрицая его. Кроме того, это классика [Off by one error] (http://en.wikipedia.org/wiki/Off-by-one_error). Посмотри ответы. – bcsb1001

ответ

1

, потому что если у вас есть еще 1 # вы будете иметь 2 строки, так что вам нужно сделать с + 1, создавая новый массив

Как

//creates array list based on number of phrases 
String[] phraseList = new String[c+1]; 
c = 0; 

вы должны использовать replaceAll(omit1,"#") и не replace(omit1,"#") & replace(omit2,"#")

Можете ли вы дать больше информации о том, где находится нуль?

Редактировать:

Вы пробовали что-то вроде?

phraseList[0]=""; 
for(int i = 0; i < phrase.length(); i++) 
    { 
    if(phrase.charAt(i) == '#') 
    { 
     c++; 
     phraseList[c]=""; 
    }else if(phrase.charAt(i) != '#') 
    { 
     phraseList[c] += phrase.charAt(i); 
    } 
    } 
+0

Это работало красиво, но когда ответ возвращается, перед ним есть «нуль». Любые указатели? – Ziggy

+0

Когда я использую фразу «Хочешь ли ты есть чай, кушать печенье или подталкивать?» значениями массива являются nullhave tea, null eat cookie и null push up. – Ziggy

+0

Предполагая, что вы раскалываетесь, правильно? и ожидаемый результат. Предпочитаете ли вы чай, как первый кусок печенья, как второй и или отжимать? как третий? – StackFlowed

1

Думай о нем, как запятые, разделяющие список:

1 , 2 , 3 , 4 , 5 , 6 

Если посчитать запятые, вы найдете там пять; но в списке есть шесть записей. Это потому, что запятые разделяют записи, но у вас все еще есть один на каждом конце.

Или подумайте с точки зрения столбов и панелей забора: пять столбов, четыре панели.

Когда вы создаете свой массив для хранения фраз, вам нужна еще одна запись, чем у вас были точки разделения, чтобы убедиться, что у вас есть место для всех фраз.

Но было бы проще избежать этого полностью и вернуть List<String>, а не String[]. Таким образом, вам не нужно знать размер заранее.

1

Поскольку другие ответы показали, что не так с вашим кодом, здесь уборщик способ разделения строки, которые вы могли бы и что ведет себя больше как фактический split() метод:

private String[] separate(String phrase, String delim) { 
    List<String> tokens = new ArrayList<String>(); 

    // add delimiter to the end of the string 
    // so last token will be included properly 
    phrase += delim; 

    // start from index of first deliminator 
    // i is the index for the deliminator 
    // j is the index for the first char of the expression before deliminator 
    int i, j = 0; 

    // while there are deliminators 
    while((i = phrase.indexOf(delim, j)) != -1) { 
     // obtain the current token from j to deliminator location 
     String token = phrase.substring(j, i); 
     // trim leading/trailing spaces of the token and make sure it has any chars 
     // if it does, add the token to list 
     if(token.trim().length() != 0) { 
      tokens.add(token); 
     } 
     // update j to the first character after the deliminator 
     j = i + delim.length(); 
    } 

    return tokens.toArray(new String[0]); 
} 
+0

Существует причина 'toArray()' без каких-либо параметров; чтобы избежать необходимости писать 'toArray (новый SomeType [0])' все время. – bcsb1001

0

почему бы не использовать StringTokenizer? (Ниже приведен пример из документа Java)

Ниже приведен пример использования токенизатора.Код:

StringTokenizer st = new StringTokenizer("this is a test"); 
while (st.hasMoreTokens()) { 
    System.out.println(st.nextToken()); 
} 

печатает следующий вывод:

this 
is 
a 
test 
0

Массивы индексируются, начиная с 0, но длина массива определяется с начальным значением 1.

Таким образом, даже хотя c дает вам количество фраз, на самом деле количество индексов в массиве (начиная с c начинается с 0), а не с фактической длины. Фактическая длина будет с + 1 (так как длина рассчитывается исходя из 1)

Index  0 | 1 | 2 | 3 | 4 
Length 1 | 2 | 3 | 4 | 5 

Например, если с = 4 (индекс = 4), ваш String [] будет иметь длину 4, когда он должен быть 5. Это то, что выбрасывает ArrayIndexOutOfBounds. Надеюсь, это поможет :)