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\n
23
\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からまでであることに注意してください。これはあなたがあなたの例外を得たところです。0
length() - 1
ただし、終了条件を次のように変更した場合
((k < s.length()) && (j < s.length()) && (s.charAt(j) == s.charAt(k)))
StringIndexOutOfBoundsExceptionを回避します。これが理由です。今回は、用語(k < s.length())
と を呼び出す前(j < s.length())
に評価されます。したがって、文字列の最後に到達すると、最初の2つの項の少なくとも1つがになり、式の残りの部分を評価する必要はありません。したがって、最後の反復では、メソッドはまったく呼び出されないため、例外は発生しません。charAt()
false
charAt
これで状況が少し明らかになったと思います。