Индекс находился вне границ массива? - PullRequest
0 голосов
/ 16 мая 2018

Я продолжаю получать это сообщение «System.IndexOutOfRangeException: индекс был за пределами массива». при попытке запустить созданную мной программу, которая использовала ловушку исключений.

класс StudentS { приватный список theStudentList;

    public bool PopulateStudents(string path)
    {
        theStudentList = new List<Student>();
        bool flag = false;
        try
        {
            List<string[]> strArrayList = new List<string[]>();
            using (StreamReader streamReader = new StreamReader(path))
            {
                string str;
                while ((str = streamReader.ReadLine()) != null)
                {
                    string[] strArray = str.Split(',');
                    strArrayList.Add(strArray);
                }
            }
            for (int index1 = 0; index1 < strArrayList.Count; ++index1)
            {
                string[] strArray = strArrayList[index1];
                Student student = new Student(strArray[0], strArray[1], strArray[2]); **where the error is**
                int index2 = 3;
                while (index2 < strArray.Length)
                {
                    student.EnterGrade(int.Parse(strArray[index2]), int.Parse(strArray[index2 + 1]));
                    index2 += 2;
                }
                student.CalGrade();
                theStudentList.Add(student);
            }
        }
        catch (Exception e)
        {
            flag = true;
            Console.WriteLine(e);
        }
        return flag;
    }

    public int ListLength
    {
        get
        {
            return theStudentList.Count;
        }
    }

    public float StudentAverage(int index)
    {
        return theStudentList.ElementAt(index).Average;
    }

    public string StudentGrade(int index)
    {
        return theStudentList.ElementAt(index).LetterGrade;
    }

    public string StudentID(int index)
    {
        return theStudentList.ElementAt(index).ID;
    }

    public string StudentLastName(int index)
    {
        return theStudentList.ElementAt(index).NameLast;
    }
}

class Student
{
    private float average;
    private ArrayList Earned;
    private string letterGrade;
    private string nameFirst;
    private string nameLast;
    private ArrayList Possible;
    private string studentID;

    public Student(string id)
    {
        studentID = null;
        nameFirst = null;
        nameLast = null;
        Earned = new ArrayList();
        Possible = new ArrayList();
    }

    public Student(string id, string first)
    {
        studentID = id;
        nameFirst = null;
        nameLast = null;
        Earned = new ArrayList();
        Possible = new ArrayList();
    }

    public Student(string id, string first, string last)
    {
        nameFirst = first;
        nameLast = last;
        studentID = id;
        Earned = new ArrayList();
        Possible = new ArrayList();
    }

    public float Average
    {
        get
        {
            return average;
        }
    }

    public string ID
    {
        get
        {
            return studentID;
        }
    }

    public string LetterGrade
    {
        get
        {
            return letterGrade;
        }
    }

    public string NameFirst
    {
        get
        {
            return nameFirst;
        }
        set
        {
            nameFirst = value;
        }
    }

    public string NameLast
    {
        get
        {
            return nameLast;
        }
        set
        {
            nameLast = value;
        }
    }

    public void CalGrade()
    {
        int num1 = 0;
        int num2 = 0;
        foreach (int num3 in Earned)
            num1 += num3;
        foreach (int num3 in Possible)
            num2 += num3;
        average = num1 / (float)num2;
        average = (float)Math.Round(average, 2);
        if (average >= 0.9)
            letterGrade = "A";
        if (average >= 0.8 && average < 0.9)
            letterGrade = "B";
        if (average >= 0.7 && average < 0.8)
            letterGrade = "C";
        if (average >= 0.6 && average < 0.7)
            letterGrade = "D";
        if (average >= 0.6)
            return;
        letterGrade = "U";
    }

    public void EnterGrade(int earnedValue, int possValue)
    {
        Earned.Add(earnedValue);
        Possible.Add(possValue);
    }
}

Я не уверен, что сделал неправильно. Спасибо за любую помощь!

Редактировать: я добавил сюда большую часть кода в надежде, что это лучше ответит на ваши вопросы. Я имею в виду набор данных, состоящий из 4 строк, которые помещаются в массив студентов.

Ответы [ 5 ]

0 голосов
/ 16 мая 2018

Это трудно диагностировать, потому что вы предоставили ограниченную информацию. Если бы я мог увидеть файл, который вы запускаете через свою программу, и указать его как путь, я бы смог сравнить то, что функция пытается сделать, с данными, которые он пытается сделать. Тем не менее, это кажется мне знакомым, поэтому я попытаюсь решить его и, по крайней мере, дам вам инструмент, чтобы примерить его.

У меня возникла похожая проблема с программой, которая требовала чтения файла CSV для графической программы. Проблема заключалась в том, что при создании CSV-файла в конце оставалась пустая строка. Это оставило мне пустой массив для представления последней строки в файле.

Кроме того, вы убедились, что массивы, добавляемые в strArrayList, имеют одинаковый размер?

Если вы проверяете эту пустую строку в конце вашего файла, и она не существует, и если вы проверяете запятые, оставленные в конце строк в вашем файле, переданных как путь, тогда вы можете попробовать правки, которые я сделал выше чтобы понять, какие строки в вашем файле CSV вызывают проблему. Я прокомментировал все изменения, которые я сделал с помощью «РЕДАКТИРОВАТЬ:», чтобы их было легко найти. Без дополнительной информации я не смогу решить проблему, но, возможно, смогу помочь вам взглянуть в правильном направлении.

Ниже приведен отредактированный код с выводом номеров строк в вашем файле, которые связаны с ошибками. Удачи!

    public bool PopulateStudents(string path)
{
    theStudentList = new List<Student>();
    bool flag = false; 

    // EDIT: NEW VARIABLE int lineCounter declared and initialized before try block so it remains in scope when the catch block is called
    int counter = 0;

    try
    {
        List<string[]> strArrayList = new List<string[]>();
        using (StreamReader streamReader = new StreamReader(path))
        {
            string str;
            while ((str = streamReader.ReadLine()) != null)
            {
                string[] strArray = str.Split(',');
                strArrayList.Add(strArray);
            }
        }

        for (int index1 = 0; index1 < strArrayList.Count; ++index1)
        {
            // EDIT: UPDATE lineCounter
            ++lineCounter;

            string[] strArray = strArrayList[index1];
            Student student = new Student(strArray[0], strArray[1], strArray[2]);
            int index2 = 3;
            while (index2 < strArray.Length)
            {
                student.EnterGrade(int.Parse(strArray[index2]), int.Parse(strArray[index2 + 1]));
                index2 += 2;
            }
            student.CalGrade();
            theStudentList.Add(student);
        }
    }
    catch (Exception e)
    {
        flag = true;
        Console.WriteLine(e);

        // EDIT: PRINT CURRENT LINE
        Console.WriteLine(“error at line in file = “ + lineCounter);
    }
    return flag;
}
0 голосов
/ 16 мая 2018

У вас могут быть проблемы, если файл из вашего path содержит пустую строку в качестве последней строки.Вы получаете доступ к strArray[0], strArray[1], strArray[2] независимо от того, является ли он пустым массивом или нет.

0 голосов
/ 16 мая 2018

Возможно, вам не хватает Array.resize (). // Это сработало для меня

Array.Resize<string[]>(ref strArrayList , count+ 1); // Count is the current length of strArrayList
0 голосов
/ 16 мая 2018

Отмечены два места, где вы можете столкнуться с проблемами:

public bool PopulateStudents(string path)
{
    theStudentList = new List<Student>();
    bool flag = false;
    try
    {
        List<string[]> strArrayList = new List<string[]>();
        using (StreamReader streamReader = new StreamReader(path))
        {
            string str;
            while ((str = streamReader.ReadLine()) != null)
            {
                string[] strArray = str.Split(',');
                strArrayList.Add(strArray);
            }
        }
        for (int index1 = 0; index1 < strArrayList.Count; ++index1)
        {
            string[] strArray = strArrayList[index1];
            // below that, what makes you believe strArray's length is >= 3 ?
            Student student = new Student(strArray[0], strArray[1], strArray[2]);
            int index2 = 3;
            while (index2 < strArray.Length)
            {
                // here index2 will be < strArray.Length, but index2+1 might be ==
                student.EnterGrade(int.Parse(strArray[index2]), int.Parse(strArray[index2 + 1]));
                index2 += 2;
            }
            student.CalGrade();
            theStudentList.Add(student);
        }
    }
    catch (Exception e)
    {
        flag = true;
        Console.WriteLine(e);
    }
    return flag;
}

Обратите внимание, что ваш цикл while можно заменить на:

for(int index2 = 3; index2 < strArray.Length - 1; index2 += 2)
{
    student.EnterGrade(...);
}
0 голосов
/ 16 мая 2018

index2 + 1 может быть вне диапазона в выражении strArray[index2 + 1] ниже:

while (index2 < strArray.Length)
{
    student.EnterGrade(int.Parse(strArray[index2]), int.Parse(strArray[index2 + 1]));
    index2 += 2;
}

Чтобы обрабатывать два элемента одновременно, используйте index2 < strArray.Length - 1

...