2013-02-09 84 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