2013-02-09 61 views
-3

我得到一个StringIndexOutOfBoundsException终止条件中我的while循环。有人可以解释这个原因吗?StringIndexOutOfBoundsException在一个while循环的终止条件中

import java.util.Scanner; 
class Solution { 

    public static int fun(String s) { 
     int count=0; 
     int k,j;     

     for(int i=0;i<s.length();i++) { 

      k=i; 
      j=0; 
      if (s.charAt(j) == s.charAt(k)) { 
       while((s.charAt(j)==s.charAt(k))&&(k<s.length())&&(j<s.length())) { 
        j++; 
        k++; 
       } 
       count+=j; 
      } 
     } 
     return count; 
    } 

    public static void main(String[] args) { 
     Scanner se=new Scanner(System.in); 
     int t=se.nextInt(); 
     String s; 
     int a[]=new int[t]; 
     for(int i=0;i<t;i++) { 
      s=se.nextLine(); 
      a[i]=fun(s); 
     } 
     for(int i=0;i<t;i++) 
      System.out.println(a[i]); 
     se.close(); 
    } 
} 
+1

什么问题?这个计划的工作是什么?什么是投入,产出和预期产出? – leemes 2013-02-09 13:08:19

+0

其实这是来自面试街道的问题https://www.hackerrank.com/challenges/string-similarity – saimadan 2013-02-09 13:13:26

+0

@saimadan检查我的答案。如果你的逻辑其余部分是正确的,那么你完成了例外.. – Arpit 2013-02-09 13:14:54

回答

2

JavaDoc

的java.lang 类的StringIndexOutOfBoundsException

按字符串方法抛出以指示索引为负数 或大于字符串的大小。对于某些方法(如 charAt方法),当索引等于 到字符串的大小时,也会抛出此异常。

您超出了字符串的长度。

此外,我认为你的逻辑有一些错误(见下文)。

你真正正在尝试做的是这样的:

while ((k < s.length()) && (j < s.length())) { // While no String goes out of Bounds 
    if (s.charAt(j) != s.charAt(k)) { // If we get a different character 
     break; // Get out of the loop 
    } else { 
     j++; // Advance one position 
     k++; 
    } 
} 

什么,你这样做是这样的:

if (s.charAt(j) == s.charAt(k)) { // If the characters are equal 
    while ((s.charAt(j) == s.charAt(k)) // While the characters are equal 
       && (k < s.length()) && (j < s.length())) { // And the position is smaller than the length 
     j++; 
     k++; 
    } 
    count += j; 
} 

的如果是多余的,因为你的同时再检查一下也无妨,和计数将增加零。

但更重要的是,在终止条件下,您检查s.charAt(j)是否发生在检查j < s.length()之前。因此,你在第一种情况下例外,你看如果j是大


另外之前,因为表达式是Java的计算由左到右,你可以改变你的循环是这样的:

while ((k < s.length()) && (j < s.length()) && (s.charAt(j) == s.charAt(k))) { 
    j++; 
    k++; 
} 

现在你不会得到一个异常,因为如果前两项是错误的(从左边),那么右边的另两项将不会被评估(至少在我的JVM中)

输出:

run: 
2 
ababaa 
aa 
11 
3 

希望有所帮助。

PS:我也改了行

int t = se.nextInt(); 

int t = se.nextInt();se.nextLine(); 

所以你解析换行给出的数字后。


澄清

1)为什么se.nextLine()

你有

int t = se.nextInt(); 

比方说,用户输入23并按下输入,这意味着InputSream whill从键盘23\n读取。 23是用户输入的号码,\n换行字符。使用换行符字符,以便计算机可以知道一行结束并且下一行开始,并且当用户按下输入时它会自动插入。更多的信息在这里:How do I get a platform-dependent new line character?

当你打电话给nextInt(),你只能读取输入的号码,但你没有阅读\n字符。因此,下次您拨打readLine()时,您会看到从您输入号码(并按下回车)后遗留下来的\n。这是什么原因你改变了上面的命令

int t = se.nextInt();se.nextLine(); 

现在你看的额外\n性格,和nextLine()下一个电话,当你读取用户输入的字符串会发生,将正确返回字符串。

2)为什么磨片循环改为((k < s.length()) && (j < s.length()) && (s.charAt(j) == s.charAt(k))

你有这个

((s.charAt(j)==s.charAt(k)) && (k<s.length()) && (j<s.length())) 

这引起了的StringIndexOutOfBoundsException。这是为什么:

在Java中,表达式是从左到右计算的。这意味着,在每次迭代时,JVM将首先检查(s.charAt(j)==s.charAt(k))。如果术语是true,那么它将评估术语(k<s.length()),如果这也是true,它将评估(j<s.length())。如果所有这些条款都是true,程序将进入循环。另一方面,如果第一项(即,第一项)(即,第一项(即,第一项))小于或等于第一项(即,(s.charAt(j)==s.charAt(k)))是false,那么整个表达式是false(因为我们有和算子),并且没有必要计算其余的项。

现在,为什么会造成异常?看看最后一次迭代会发生什么。此时,变量j(或等效为k)的值将等于字符串s的长度。当JVM尝试评估终止条件时,它将首先评估术语(s.charAt(j)==s.charAt(k))。由于j等于s的长度,因此调用charAt()将抛出StringIndexOutOfBoundsException,因为调用将尝试获取以外的字符的字符串。请记住,字符串中的索引是从0length() - 1。这是你的例外。

但是,如果你改变了终止条件,以

((k < s.length()) && (j < s.length()) && (s.charAt(j) == s.charAt(k))) 

你将避免的StringIndexOutOfBoundsException。这是为什么。这次,条款(k < s.length())(j < s.length())在之前被评估为,调用charAt()。因此,当我们到达字符串的末尾时,两个第一项中至少有一个是false,并且不需要评估表达式的其余部分。因此,在最后一次迭代中,根本不调用方法charAt,所以我们没有得到异常。

我希望这可以澄清一些情况。

+0

的作用,即使我改变while((s.charAt(j)== s.charAt(k) )&&(k saimadan 2013-02-09 13:33:45

+0

嘿,你能解释我不明白你在说什么吗等待回复 – saimadan 2013-02-09 16:06:08

+0

@saimadan你希望我澄清什么部分? – user000001 2013-02-09 17:00:37

1

试试这个

for(int i=0;i<t;i++) 
    { 
     s=se.nextLine(); 
     se.next(); //add this to discard the newline char of nextLine(). because of newline your next string input is empty string. which leads to IOB exception. 
     a[i]=fun(s); 
    } 

输出:

2 
asdf 
asdf 
0 
0 
+0

你能不能详细说明我的注释行我不明白se.next() – saimadan 2013-02-09 13:29:18