Emily
Emily

Reputation: 1

String Out of Bounds Exception for For Loop

The code compiles, but in its runner I get an out of bounds exception. Is there a problem with the for loop?

public class CountPairs
{
    public static int pairCounter( String str )
    { 
      //count pairs and aaa counts as 2
      int count = 0;
      int stringLength = str.length();
      String string = str;
      
      for( int i = 1; i <= stringLength; i++ )
      {
         char first = string.charAt( 0 );
         if( first == string.charAt( i ) )
         {
            count++;
         }
         string = string.substring( i );
      }
      return count;
    }
}

Upvotes: 0

Views: 263

Answers (4)

Jan
Jan

Reputation: 2352

This answer is in three parts:

  1. Fixing your original code so that it compiles, but might not get your desired return value (finding all pairs of equal characters that occur side-by-side?)
  2. Changing your original code so that it counts all pairs of equal characters that occur side-by-side
  3. Showing a short sequence of events on how your original code acts so that you can reflect the erroneous places

Fixed for compilation and running without error:

Here is a version of your code that compiles and returns a value. But if that is your intended return value, I don't know. It would be great to accompany your code with the actual task it should achieve (in detail).

What I changed is:

  1. Change lower-equals (<=) to lower-than (<), because the maximum index of a string is equal to its length minus one
  2. Add a recalculation of stringLength because string and thus its length change in each iteration as a cause of string = string.substring( i )
public class CountPairs
{
    public static int pairCounter( String str )
    { 
      //count pairs and aaa counts as 2
      int count = 0;
      int stringLength = str.length();
      String string = str;
      
      // change "<=" to "<" because
      // the index of the last character of a string
      // equals its length MINUS 1
      for( int i = 1; i < stringLength; i++ )
      {
         char first = string.charAt( 0 );
         if( first == string.charAt( i ) )
         {
            count++;
         }
         // Here you reassign "string" to be a substring of itself
         // effectively changing its length and index positions completely
         string = string.substring( i );
         // so you have to recalculate the Length of "string"
         // which changes in each iteration!
         stringLength = string.length();

      }
      return count;
    }
}

Changing for the possibly correct return value

But other than that, I think what you really might want is a sliding window of size two and increment the counter if the characters in this window are equal. And this can be achieved similarly, but without any calls to substring:

public class CountPairs
{
    public static int pairCounter( String str )
    { 
      //count pairs and aaa counts as 2
      int count = 0;
      int stringLength = str.length();
      String string = str;
      
      for( int i = 0; i < stringLength - 1; i++ )
      {
         char first = string.charAt( i );
         if( first == string.charAt( i + 1 ) )
         {
            count++;
         }
      }
      return count;
    }
}

A short example of what your code does in the original version:

Below is some pseudo-syntax that shows how variables and their values change with your originally defined function.

Also there are some aids showing indices and the positions taken for strings involved. relevant indices of string are marked by a ^ underneath accompanied by their index positions another line below

stringLength = 6
string = "aabccd"

// ...
// here the first iteration of the loop starts
i = 1
first = "aabccd".charAt( 0 ) = "a"
         ^
         012345

second = "aabccd".charAt(i = 1) = "a"
           ^
          012345

// first equals second so increment counter
first == second => count++
string = "aabccd".substring( i = 1) = "abccd"
           ^^^^^
          012345
-------------
// second for loop iteration, i is incremented to 2, string is "abccd"
i = 2
first = "abccd".charAt( 0 ) = "a"
         ^
         01234

second = "abccd".charAt(i = 2) = "c"
            ^
          01234

first != second
string = "abccd".substring( i = 2) = "ccd"
            ^^^
          01234
-------------
// third for loop iteration, i is incremented to 3, string is "ccd"
i = 3
first = "ccd".charAt( 0 ) = "a"
         ^
         012

// Here already an index out of bounds exception is thrown!!
// because 3 is larger than the highest possible index position 2
second = "ccd" .charAt(i = 3) = "c"
             ^
          012

Upvotes: 0

SKL
SKL

Reputation: 3

First of all

String is basically a wrapper around char[] array.

Second

The array index in Java starts with zero. Negative indexes are invalid in Java.

Third

Java will throw ArrayIndexOutOfBoundException ,if you try to access an Array with an invalid index which could mean "negative index", "index greater than or equal to the length of the array" in Java.

Your Problematic Code:

public class CountPairs
{
    public static int pairCounter( String str )
    { 
      //count pairs and aaa counts as 2
        int count = 0;
      int stringLength = str.length();
      String string = str;
      
      for( int i = 1; i <= stringLength; i++ )
      {
         char first = string.charAt( 0 );
         if( first == string.charAt( i ) )
         {
            count++;
         }
         string = string.substring( i );
      }
      return count;
    }
}

A Possible Solution:

public class CountPairs
{
    public static int pairCounter( String str )
    { 
      //count pairs and aaa counts as 2
        int count = 0;
      int stringLength = str.length();
      String string = str;
      
      for( int i = 0; i < stringLength; i++ )
      {
         char first = string.charAt( 0 );
         if( first == string.charAt( i ) )
         {
            count++;
         }
         string = string.substring( i );
      }
      return count;
    }
}

Hope this might solve your problem.

Thumb up If Yes.

Keep Learning Java!

Upvotes: 0

Programmer
Programmer

Reputation: 813

Because of the index of the first char in a String is 0, the index of last char is myString.length() - 1, and myString.charAt(myString.length()) throw an StringOutOfBoundsException. To fix your code, change the loop header to for (int i = 0;i < myString. length();i++)

Upvotes: 0

Donato Amasa
Donato Amasa

Reputation: 856

You should replace line below:

for( int i = 1; i <= stringLength; i++ )

With line:

for( int i = 0; i < stringLength; i++ )

You should only loop through your string by starting with index i = 0

Upvotes: 1

Related Questions