1

对于我的CompSci班级,我们正在制作你愿意吗?我们的聊天机器人项目的功能。该String.split()方法对此很有效,但如果我们没有它也能做到这一点,我们将获得奖励积分。我决定通过创建一个复制的方法来解决这个问题String.split

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数组的计数器有关,但到目前为止我修复它的尝试无济于事。

有什么帮助吗?

4

5 回答 5

1

因为如果您甚至有 1 # 您将有 2 个字符串,因此您需要在创建新数组时执行 c+1

喜欢

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

你应该使用replaceAll(omit1,"#")而不是replace(omit1,"#")&replace(omit2,"#")

您能否提供有关 null 将在何处出现的更多信息?

编辑:

你试过类似的东西吗?

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);
     }
  }
于 2014-09-16T16:32:29.887 回答
1

把它想象成用逗号分隔一个列表:

1 , 2 , 3 , 4 , 5 , 6

如果你数一下逗号,你会发现有五个;但列表中有六个条目。那是因为逗号分隔条目,但每一端仍然有一个。

或者考虑栅栏柱和面板:五个柱子,四个面板。

当您创建数组来存储短语时,您需要比分割点多一个条目,以确保您有空间容纳所有短语。

但是完全避免这种情况并返回 aList<String>而不是 a会更容易String[]。这样,您无需提前知道尺寸。

于 2014-09-16T16:36:37.367 回答
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]);
}
于 2014-09-16T16:40:17.293 回答
0

为什么不使用 StringTokenizer?(以下是 Java 文档中的示例)

以下是使用分词器的一个示例。编码:

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

打印以下输出:

 this
 is
 a
 test
于 2014-09-16T16:48:14.293 回答
0

数组从 0 开始索引,但数组的长度由初始值 1 确定。

所以即使c给你短语的数量,它实际上是数组中的索引数量(因为c从 0 开始)而不是实际长度。实际长度为 c + 1(因为长度是从 1 开始计算的)

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

例如,如果 c = 4 (Index = 4),你的 String[] 的长度应该是 5,而它应该是 5。这就是抛出 ArrayIndexOutOfBounds 的原因。希望这可以帮助 :)

于 2014-09-16T16:50:52.707 回答