-3

while ループの終了条件でStringIndexOutOfBoundsExceptionを取得します。誰かがこの理由を説明できますか?

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(); 
    }
}
4

2 に答える 2

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;
}

とにかくしばらくの間それをチェックするので、Ifは冗長であり、カウントはゼロだけ増加します。

しかし、もっと重要なのは、しばらくの終了条件で、チェックs.charAt(j)の前にチェックが行われるかどうかをチェックすることj < s.length()です。したがって、jが大きすぎるかどうかを確認する前に、最初のケースで例外が発生します。


さらに、式はJavaであるため、左から右に計算されるため、ループを次のように変更できます。

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

最初の2つの用語が(左から)偽の場合、右側の他の2つの用語は(少なくとも私のJVMでは)まったく評価されないため、例外は発生しません。

出力:

run:
2
ababaa
aa
11
3

お役に立てば幸いです。

追伸:私も行を変更しました

int t = se.nextInt();

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

番号が与えられた後に改行を解析するように。


明確化

1)なぜse.nextLine()

持っていた

int t = se.nextInt();

ユーザーが入力23してを押したとしましょう。これは、 InputSreamがキーボードから読み取られる enterことを意味します。ユーザーが入力した番号であり、改行文字です。改行文字は、1つの行が終了し、次の行が開始することをコンピューターが認識できるようにするために使用され、ユーザーがEnterキーを押すと自動的に挿入されます。詳細はこちら:プラットフォームに依存する改行文字を取得するにはどうすればよいですか?23\n23\n

を呼び出すときはnextInt()、入力された番号だけを読みますが、\n文字は読みません。したがって、次に電話をかけるときは、番号を入力したとき(およびEnterキーを押したとき)から残っている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))ます。項が真の場合、それは項を評価し、それ(k<s.length())真の場合、それはを評価し(j<s.length())ます。これらの条件がすべて当てはまる場合、プログラムはループに入ります。

一方、最初の項(つまり(s.charAt(j)==s.charAt(k)))がfalseの場合、式全体がfalseになり(AND演算子があるため)、残りの項を計算する必要はありません。

さて、なぜそれが例外を引き起こしたのですか?最後の反復で何が起こるかを見てください。この時点で、変数j(またはk同等のもの)は文字列の長さに等しい値になりますs。JVMが終了条件を評価しようとすると、最初に用語を評価し(s.charAt(j)==s.charAt(k))ます。jはの長さに等しいため、s呼び出しはStringIndexOutOfBoundsExceptioncharAt()をスローします。これは、呼び出しが文字列の外側にある文字を取得しようとするためです。文字列のインデックスはfromからまでであることに注意してください。これはあなたがあなたの例外を得たところです。0length() - 1

ただし、終了条件を次のように変更した場合

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

StringIndexOutOfBoundsExceptionを回避します。これが理由です。今回は、用語(k < s.length())と を呼び出す(j < s.length())に評価されます。したがって、文字列の最後に到達すると、最初の2つの項の少なくとも1つがになり、式の残りの部分を評価する必要はありません。したがって、最後の反復では、メソッドはまったく呼び出されないため、例外は発生しません。charAt()falsecharAt

これで状況が少し明らかになったと思います。

于 2013-02-09T13:13:09.470 に答える
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
于 2013-02-09T13:12:16.723 に答える