-1

I'm making a letter counter in c#, it compiles ok, but whenever I run it, I have this error "System.IndexOutOfRangeException" on line "if(chars[num]==knizka[num1])". What should I do please? idk why i need to add more text

            int num = 0;
            int num1 = 0;
            string knihaRef = System.IO.File.ReadAllText("Osnova.txt");
            knihaRef = knihaRef.ToLower();
            string abcd ="abcdefghijklmnopqrstuvwxyz";
            abcd = abcd.ToLower();
            char[] chars =abcd.ToArray();
            char[] knizka = knihaRef.ToArray();
            int[] numOfLet =new int[26];

            for (int i=0; i<chars.Length;i++)
            {
                numOfLet[i] = 0;
            }

            while(num1<knizka.Length)
            {
                if (chars[num]==knizka[num1])
                {
                    numOfLet[num]++;
                    num1++;
                    num++;

                    if (num>=numOfLet.Length)
                    {
                        num = 0;
                    }   
                }
                else
                {
                    num++;
                }
            }
  • [This will help](http://stackoverflow.com/questions/20940979/what-is-an-indexoutofrangeexception-argumentoutofrangeexception-and-how-do-i-f) – Dec Mar 17 '17 at 17:05
  • Possible duplicate of [What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?](http://stackoverflow.com/questions/20940979/what-is-an-indexoutofrangeexception-argumentoutofrangeexception-and-how-do-i-f) – Kyle Mar 17 '17 at 17:06
  • The `else` statements looks like it's the cause of your problem. It can cause `num` to increase to a value larger than `chars.Length`. – Sean Mar 17 '17 at 17:09
  • Your code is at too low of a level. That makes it hard to compare with the requirements and for you to give feedback about the imprecision of the requirements. You need another approach. First, you seem to be mapping all letters of interest (see [Char.IsLetter](https://msdn.microsoft.com/en-us/library/system.char.isletter(v=vs.110).aspx)) to the lowercase Basic Latin letters. However, `ToLower` uses the user's culture so the mapping could vary. Clearly, A-Z and a-z map to a-z. But, İ maps to İ or to i and K maps to K or to k. You also aren't counting thousands of other letters such as ấåăäá…ą. – Tom Blodget Mar 18 '17 at 20:33

3 Answers3

0

Firstly, use string.ToCharArray() rather than string.ToArray() - it makes it clearer for future reference.

Use a debugging tool to find the value of knihaRef to see if there's any value assigned to it.
Also go through your while loop and the nested for loop to check that you're not going out of the array's bounds.

Nathangrad
  • 1,426
  • 10
  • 25
0

As Juharr noted in comments, you are not checking if num grows to the size of chars.Length. This could happen if a character is in knizka that is not in chars. e.g. if there is a punctuation mark in knizka, it will not match anything in chars and the while loop will walk off the end of chars looking for a match.

PhilC
  • 767
  • 3
  • 8
0

The main issue is that in your else you increment num, but then don't make sure it isn't outside the range of chars, which can happen if you have any characters that are not standard English letters. When it is you'd want to set it to zero and increment num1 since you've already tested knizka[num1] against all the lower case letters.

while(num1<knizka.Length)
{
    if (chars[num]==knizka[num1])
    {
        numOfLet[num]++;
        num1++;
        num++;

        if (num>=numOfLet.Length)
        {
            num = 0;
        }   
    }
    else
    {
        num++;

        if (num>=numOfLet.Length)
        {
            num = 0;
            num1++;
        }   
    }
}

Though it's easier if you just iterate over the characters in knihaRef check if the character is a lower case letter and if it is then you can get the index to increment by subtracting the ASCII value of 'a' from it. Also you don't have to do the loop where you set all the values in numOfLet to zero since the array will be initialized with all zeros when you create it.

string knihaRef = System.IO.File.ReadAllText("Osnova.txt").ToLower();
int[] numOfLet =new int[26];

foreach(char c in knizka)
{
    // Only count letters.
    if ('a' < c && c < 'z')
    {
        numOfLet[c-'a']++;
    }
}
juharr
  • 31,741
  • 4
  • 58
  • 93