-1

I ran into an exception "System.IndexOutOfRangeException" on a project and isolated into this example code block here.

using System;

public class Program
{
    public static void Main()
    {
        string testStr = "AB5, BC4, CD8, DC8, DE6, AD5, CE2, EB3, AE7";
        //split testStr into substrings representing each edge
        string [] edges = testStr.Split(", ".ToCharArray());

        foreach(string edge in edges)
        {
            Console.Write(edge + "\n");
            char [] cEdge = edge.ToCharArray();
            char cost = cEdge[cEdge.Length - 1]; // what out of bounds?
            Console.Write(cost);
        }
    }
}

This issue comes from the line "char cost = cEdge[cEdge.Length - 1];". Which makes no sense to me since cEdge by this point should be an array of length 3. So indexing at cEdge.Length - 1 should be index of 2 and be within bounds of the array. I'm quite confused, maybe I've over looked something. Thanks for your time and help.

  • If cEdge is of length zero then `cEdge[cEdge.Length-1]` will generate an out of bounds exception. – dbc Nov 08 '14 at 07:10

5 Answers5

3

By default the Split method includes empty strings in the array. So you're cEdge array is has a size of 17 with around 8 of the elements being empty strings. So when you try iterating through the array, the length of the empty string is 0 and you try to subtract 1 which places you out of bounds on the array.

You've got a couple of options here. You can place an if statement to ensure the length of cEdge is 3 characters or update the Split method to use one of the overloads that will automatically remove these empty elements.

Here's how you would use the overload:

string[] edges = testStr.Split(", ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

Edit

Just realized I didn't really explain why you get the extra empty groups. The empty elements appear because you supplied the split function with an array of delimiters. The function then uses the array to match on ANY one of the delimiters and breaks it into unique elements. There's a perfect example in you're situation where this makes a difference. If your source string testStr was to contain a space in one of the fields it will actually break that field in half because you supplied a space into the delimiter list.

As the MSDN article puts it:

Each element of separator defines a separate delimiter character. If two delimiters are adjacent, or a delimiter is found at the beginning or end of this instance, the corresponding array element contains Empty.

So for instance:

string testStr = "AB5, BC4, CD8 Test, DC8";
string [] edges = testStr.Split(", ".ToCharArray());

In this case most people assume that we would end up with an array that looks something like this:

+----------------------------+
| AB5 | BC4 | CD8 Test | DC8 |
+----------------------------+

However the actual output of this method would be more like this:

+------------------------------+
| AB5 | BC4 | CD8 | Test | DC8 |
+------------------------------+

To get the desired output every time, a more robust solution would look something like this:

String[] edges = Regex.Split(testStr, Regex.Escape(", "), RegexOptions.None);

If the split happens to be within a tight loop you may want to consider compiling the regex before entering the loop, but that's a different problem.

Nathan
  • 1,437
  • 12
  • 15
1

The problem is when the array is empty Length property will equal to 0 and cEdge[0 - 1] will eventually give you IndexOutOfRangeException. Consider checking Length before indexing array:

using System;

public class Program
{
    public static void Main()
    {
        string testStr = "AB5, BC4, CD8, DC8, DE6, AD5, CE2, EB3, AE7";
        //split testStr into substrings representing each edge
        string [] edges = testStr.Split(", ".ToCharArray());

        foreach(string edge in edges)
        {
            Console.Write(edge + "\n");
            char [] cEdge = edge.ToCharArray();
            if (cEdge.Length > 0)
            {
                char cost = cEdge[cEdge.Length - 1]; // what out of bounds?
                Console.Write(cost);
            }
        }
    }
}
Eldar Dordzhiev
  • 5,105
  • 2
  • 22
  • 26
0

Because the 2nd,4th,6th,etc... array value of edges in empty.

static void Main(string[] args)
    {
        string testStr = "AB5, BC4, CD8, DC8, DE6, AD5, CE2, EB3, AE7";
        //split testStr into substrings representing each edge
        string[] edges = testStr.Split(", ".ToCharArray());
        char[] cEdge;
        foreach (string edge in edges)
        {
            Console.Write(edge + "\n");
            cEdge = edge.ToCharArray();
            char cost = new char();
            if(cEdge.Length > 0)
            { 
                cost = cEdge[0]; // what out of bounds?
            }
            Console.Write(cost);
        }
        Console.Read();
    }
Onel Sarmiento
  • 1,608
  • 3
  • 20
  • 46
0

I trace Your code and i found edge value contains "" that causes cEdge.Length is 0 you must fixed you code like this:

public static void Main()
        {
            string testStr = "AB5, BC4, CD8, DC8, DE6, AD5, CE2, EB3, AE7";
            //split testStr into substrings representing each edge
            string[] temp = { ", " };
            string[] edges = testStr.Split(temp, StringSplitOptions.RemoveEmptyEntries);

            foreach (string edge in edges)
            {
                Console.Write(edge + "\n");
                char[] cEdge = edge.ToCharArray();
                char cost = cEdge[cEdge.Length - 1]; // what out of bounds?
                Console.Write(cost);
            }
        }
Asieh hojatoleslami
  • 3,240
  • 7
  • 31
  • 45
0

You splitting a string by char array of ',' and ' '
and you get something like:
["AB5","","BC4","", ....]
look here http://msdn.microsoft.com/en-us/library/b873y76a(v=vs.110).aspx
In this line than edge == ""
char cost = cEdge[cEdge.Length - 1];
cEdge.Length == 0
and you get System.IndexOutOfRangeException You should use following syntax
testStr.Split(", ".ToCharArray(),StringSplitOptions.RemoveEmptyEntries);

Roman Gordon
  • 166
  • 1
  • 2