WedX - журнал о программировании и компьютерных науках

Сбой программы при вводе в массив двойных указателей, который находится в точке структуры

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

Но каждый раз, когда я пытаюсь ввести результаты тестов для студентов, моя программа падает. Я пробовал studentData->testscores в моей функции enterData(), я пробовал studentData[i].testScores[j], *studentData->testScores, и ничего не работает.

Может ли кто-нибудь указать мне в правильном направлении.

#include <iostream>
#include <string>
#include <iomanip>

using namespace std;

struct StudentInfo
{
    string name;
    string idNum;
    double* testScores;
    double average;
    char grade;
};

StudentInfo enterData(StudentInfo*, int, int);//Add data to the student
//void displayData(StudentInfo*, int);//Display the student info and grade

int main()
{
int numStudents;
int numTests;

cout << "Enter the amount of students to input: ";
cin >> numStudents;
cin.ignore();
cout << "Enter the number of test scores per students: ";
cin >> numTests;
cin.ignore();

StudentInfo* studentData = new StudentInfo[numStudents];

for(int i = 0; i < numStudents; i++);
{
    studentData->testScores = new double[numTests];
    studentData++;
}


//Let the user enter students information
enterData(studentData, numStudents, numTests);

return 0;
}
//*************************
//define enterData function
//*************************
StudentInfo enterData(StudentInfo* studentData, int numStudents, int numTests)
{
int testTotal = 0; //Keep a total of the tests.
double testScore; //Variable to hold user input of test score.
for(int i = 0; i < numStudents; i++)
    {
    cout << "\n\nPlease enter data for Student #" << i + 1;
    cout << "\n-------------------------------------\n";
    cout << "\nName: ";
    getline(cin, studentData[i].name);
    while(studentData[i].name.empty())
    {
        cout << "Oops! You didn't enter the students's name!" << endl;
        cout << "Please enter customer's name: ";
        getline (cin, studentData[i].name);
    }
    //Get Student's Id Number
    cout << "ID Number: ";
    getline(cin, studentData[i].idNum);
    while(studentData[i].idNum.empty())
    {
        cout << "Oops! You didn't enter the students's ID Number!" << endl;
        cout << "Please enter student's ID Number: ";
        getline (cin, studentData[i].idNum);
    }
        //Get Student's Test Scores
        cout << "Enter Test Scores for Student #" << i + 1 << endl;

        for (int j = 0; j < numTests; j++)
        {
            cout << "Test #" << j + 1 << ": ";
            cin >> testScore;
            cin.ignore();
            studentData[i].testScores[j] = testScore;
            testTotal += testScore;
        }
    //Save Students Average
    cout << fixed << setprecision(2);
    cout << "Student's Average: " << testTotal/numTests;

    studentData[i].average = testTotal/numTests;

    //Save Students Grade
    if(studentData[i].average > 90)
        studentData[i].grade = 'A';
    else if(studentData[i].average > 80)
        studentData[i].grade = 'B';
    else if(studentData[i].average > 70)
        studentData[i].grade = 'C';
    else if(studentData[i].average > 60)
        studentData[i].grade = 'D';
    else
            studentData[i].grade = 'F';
        cout << "Student's Grade: " << studentData[i].grade << endl;

    }
    return *studentData;
}
15.02.2014

  • очистите код: удалите части, не относящиеся к вашему вопросу, и проверьте, воспроизводит ли он проблему. 16.02.2014

Ответы:


1

Вы столкнулись с неопределенным поведением, потому что пытаетесь получить доступ к памяти за пределами массива:

// you create an array and keep pointer to first element:
StudentInfo* studentData = new StudentInfo[numStudents];

// try to increment this pointer till it points behind this array:
for(int i = 0; i < numStudents; i++);                        // <-- semicolon !!!
{
    studentData->testScores = new double[numTests];
    studentData++;
}

// and use this pointer that points to incorrect memory:
enterData(studentData, numStudents, numTests);

Кроме того, после вашего for есть точка с запятой, которая приводит к тому, что «тело» вашего цикла (которое из-за точки с запятой является не чем иным, как анонимной вложенной областью) выполняется только один раз, что достаточно для функции enterData для итерации студентов, начиная со 2-го элемента , вызывая UB в конце.


Что вы должны сделать, это:

StudentInfo* studentData = new StudentInfo[numStudents];

for(int i = 0; i < numStudents; i++) {
    studentData[i].testScores = new double[numTests];
}

enterData(studentData, numStudents, numTests);

... и просто чтобы напомнить вам, обратите внимание, что очистка этого должна отражать способ его размещения:

for(int i = 0; i < numStudents; i++) {
    delete[] studentData[i].testScores;
}
delete[] studentData;
15.02.2014
  • Не говоря уже о случайной точке с запятой после for, поэтому цикл даже не выполняется... 16.02.2014
  • Я очень ценю это. Я пытался использовать нотацию указателя с studentData->testScores. И дело с точкой с запятой после цикла for действительно не помогло. :) Точка с запятой смерти. Спасибо, теперь работает! 16.02.2014
  • Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]