I get a StringIndexOutOfBoundsException in the terminating condition of my while loop. Could someone explain the reason for this?
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();
}
}
From JavaDoc
You are exceeding the length of the string.
In addition I think you have some errors in your logic (see below).
What you really are trying to do is this:
What you were doing was this:
The If is redundant, since you chech it in the while anyway, and count would be increased by zero.
But more importantly, in the terminating condition of the while, you the check if
s.charAt(j)happens before the checkj < s.length(). Thus, you get the exception at the first case, before you see if j is to largeIn addition, since the expressions is Java are calculated from left to right, you could change your loop like this:
Now you don’t get an Exception, because if the first 2 terms are false (from the left), then the other two term on the right will not be evaluated at all (at least in my JVM)
Output:
Hope that helped.
Ps: I also changed the line
to
So that you parse the newline after the number is given.
Clarifications
1) Why
se.nextLine()You had
Lets say the user enters
23and presses enter, which means that the InputSream whill read from the keyboard23\n.23is the number that the user entered, and\nis newline character. The newline character is used so that the computer can tell when one line ends and the next one begins, and it is automatically inserted when the user presses enter. More info here: How do I get a platform-dependent new line character?When you call
nextInt(), you only read the number that was entered, but you do not read the\ncharacter. Thus, next time you callreadLine(), you will read the\nthat is left over from when you entered the number (and pressed enter). This is the reason you change the above command toNow you read that extra
\ncharacter, and the next call ofnextLine(), that will happen when you read the string that the user entered, will correctly return the string.2) Why did whe change the loop to
((k < s.length()) && (j < s.length()) && (s.charAt(j) == s.charAt(k))You had this
This caused the StringIndexOutOfBoundsException. And here is why:
In Java, the expressions are calculated from left to right. that means, that at each iteration, the JVM will first check
(s.charAt(j)==s.charAt(k)). If the term is true, then it will evaluate the term(k<s.length()), and if that is also true, it will evaluate(j<s.length()). If all these terms are true, the program will enter the loop.On the other hand, if the first term (i.e.
(s.charAt(j)==s.charAt(k))) is false, then the whole expression is false (since we have and AND operator), and there is no need to calculate the rest of terms.Now, why did that cause an Exception? Look at what happens at the last iteration. At this point, the variable
j(orkequivalently) will have a value equal to the length of strings. When the JVM tries to evaluate the termination condition, it will first evaluate the term(s.charAt(j)==s.charAt(k)). Sincejis equal to the length ofs, the callcharAt()will throw a StringIndexOutOfBoundsException, since the call will try to get a character that is outside of the string. Remember that the indexes in the String are from0tolength() - 1. This is where you got your Exception.If however, you change the termination condition to
you will avoid the StringIndexOutOfBoundsException. Here is why. This time, the terms
(k < s.length())and(j < s.length())are evaluated before the call tocharAt(). Thus, when we reach the end of the string, at least one of the two first terms will befalse, and there is no need to evaluate the rest of the Expression. Thus, at the last iteration, the methodcharAtis not called at all, so we don’t get the Exception.I hope this clarified the situation a bit.