Cтруктура на С++

Здравствуйте, помогите решить проблему. После запуска и ввода данных, программа перестаёт работать, то есть не выводит результат на экран. Что здесь сделано не так? Заранее спасибо за ответ.
Само задание:

Успеваемость студентов. Записать в структуру следующие данные о
студентах: Ф.И.О., № группы, оценки по 4 предметам. Организовать выбор
отличников. Выбранных упорядочить по алфавиту

#include <iostream>
    #include <string.h>
    using namespace std;
    int main()
    {
        struct students
        {
            char* name;
            int number;
            int mark1;
            int mark2;
            int mark3;
            int mark4;
        };
        students *student = new students();
        int k = 0;
        cout << "Vvedite kol-vo studentov: ";
        cin >> k;
        for (int i = 0; i < k; i++)
        {
            cout << "\nVvedite imya studenta: ";
            cin>>student[i].name;

            cout << "\nVvedite nomer gruppi: ";
            cin >> student[i].number;

            cout << "\nVvedite ocenky po algebre: ";
            cin >> student[i].mark1;
            cout << "\nVvedite ocenky po fizike: ";
            cin >> student[i].mark2;
            cout << "\nVvedite ocenky po himii: ";
            cin >> student[i].mark3;
            cout << "\nVvedite ocenke po geografii: ";
            cin >> student[i].mark4;
        }
        students *excellentStudent = new students();
        int i = 0, n=0;
        while (i < k)
        {
            if ((student[i].mark1 == 5) && (student[i].mark2 == 5) &&
                (student[i].mark3 == 5) && (student[i].mark4 == 5))
            {
                excellentStudent[i] = student[i];
                n++;
            }
            i++;
        }
        int choice = 0;
        cout << "\nVvedite '0', esli hotite otsortirovat po alfavity,\n"
            "ili '1', esli sortirovka ne trebyetsya.";
        cin >> choice;
        do
        {
            switch (choice)
            {
            case 0:
                students b;
                for (int m = 0; m < (n - 1); m++)
                {
                    for (int a = (m + 1); a < n; a++)
                    {
                        if (excellentStudent[m].name[0]>excellentStudent[a].name[0])
                        {
                            b = excellentStudent[m];
                            excellentStudent[m] = excellentStudent[a];
                            excellentStudent[a] = b;
                        }
                    }
                }
                for (int j = 0; j < n; j++)
                {
                    cout << "\n\n[" << j << "]";
                    cout << "\nImya studenta: " << excellentStudent[j].name;

                    cout << "\nNoper gruppi: " << excellentStudent[j].number;

                    cout << "\nOcenka po algebre: " << excellentStudent[j].mark1;
                    cout << "\nOcenka po fizike: " << excellentStudent[j].mark2;
                    cout << "\nOcenka po himii: " << excellentStudent[j].mark3;
                    cout << "\nOcenka po geometrii: " << excellentStudent[j].mark4;
                }
                break;
            case 1:
                for (int j = 0; j < n; j++)
                {
                    cout << "\n\n[" << j << "]";
                    cout << "\nImya studenta: " << excellentStudent[j].name;

                    cout << "\nNomer gruppi: " << excellentStudent[j].number;

                    cout << "\nOcenka po algebre: " << excellentStudent[j].mark1;
                    cout << "\nOcenka po fizike: " << excellentStudent[j].mark2;
                    cout << "\nOcenka po himii: " << excellentStudent[j].mark3;
                    cout << "\nOcenka po geometrii: " << excellentStudent[j].mark4;
                }
                break;
            default:
                cout << "Vvedeno nevernoe znachenie ["
                    << choice << "]. Poprobuite snova.";
                break;
            }
        } while ((choice == 0) || (choice == 1));

        return 0;
    }

В программе целый букет ляпов. Настоятельно советую разобраться с темой «Массивы и указатели».

(1) В структуре есть поле char *name. Это указатель на данные типа char. Сам указатель никаким значением не инициализирован. Это раз. Место под данные не отведено. Это два. Т.е. в операторе cin>>student[i].name; вводится строка по случайному (или нулевому, если добрый компилятор инициализировал поле структуры нулём) адресу — раз, и строка размещается в неотведённой для неё памяти — два. Крэш практически неизбежен.

(2) Оператор students *student = new students(); выделяет память под одну структуру, а не под массив структур. Множественное число в названии структуры ни к чему не обязывает. Поэтому оператор cin>>student[i].name; (и далее аналогичные) сработает только для первого студента. При i отличном от 0 будет обращение к «чужой» памяти, что опять-таки будет приводить к падению программы.

Вышесказанное относится и к students *excellentStudent = new students();.

Совет. Объявление структуры вынести из main в глобальную область. Структуру переименовать в единственное число: student, поскольку она содержит данные об одном студенте. А массивы лучше именовать идентификаторами во множественном числе. На работоспособность программы это не влияет, но читать/отлаживать программу будет проще.

(3) Конструкция

    int i = 0, n = 0;
    while (i < k) {
        if ((student[i].mark1 == 5) && (student[i].mark2 == 5) &&
            (student[i].mark3 == 5) && (student[i].mark4 == 5)) {
            excellentStudent[i] = student[i];
            n++;
        }
        i++;
    }

не будет работать так, как ты предполагаешь. Соответственно не будет правильно работать и сортировка, и вывод отличников на консоль. Надо исправить на excellentStudent[n] = student[i];.

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

(4) Сортировка по именам не будет работать правильно, если среди отличников будут студенты с фамилией, начинающейся на одну и ту же букву. Надо использовать сравнение строк.

(5) Неправильно написано условие продолжения цикла в последнем цикле (do). Должно быть

    do {
        cout << "\nVvedite '0', esli hotite otsortirovat po alfavity,\n"
            "ili '1', esli sortirovka ne trebyetsya.";
        cin >> choice;
        switch (choice) {
        // ......
        }
     } while ((choice != 0) && (choice != 1));

(6) Отсутствует освобождение памяти для переменных student и excellentStudent.

Немножко «размял мозги»:

/*
Успеваемость студентов. Записать в структуру следующие данные о
студентах: Ф.И.О., № группы, оценки по 4 предметам. Организовать выбор
отличников. Выбранных упорядочить по алфавиту
*/

#include <iostream>
#include <string.h>

const size_t NAME_LEN = 16;
const size_t MARK_ARRAY_LEN = 4;

struct Student {
    char name[NAME_LEN];
    int group;
    int mark[MARK_ARRAY_LEN];
};

char *subjects[MARK_ARRAY_LEN] = {
    "algebra", "fizika", "himiya", "geografiya"
};

using namespace std;
int main() {
    size_t k = 0;
    cout << "Vvedite kol-vo studentov: ";
    cin >> k;
    Student *students = new Student[k];

    for (size_t i = 0; i < k; ++i) {
        cout << "\nVvedite imya studenta: ";
        cin >> students[i].name;

        cout << "\nVvedite nomer gruppi: ";
        cin >> students[i].group;

        for (size_t s = 0; s < MARK_ARRAY_LEN; ++s) {
            cout << "\nVvedite ocenky dlya predmeta '" << subjects[s] << "': ";
            cin >> students[i].mark[s];
        }
    }
    Student **excellentStudents = new Student*[k];
    size_t i = 0, n = 0;
    int sum;
    while (i < k) {
        sum = 0;
        for (size_t s = 0; s < MARK_ARRAY_LEN; ++s) {
            sum += students[i].mark[s];
        }
        if (sum == 5 * MARK_ARRAY_LEN) {
            excellentStudents[n] = &students[i];
            ++n;
        }
        i++;
    }
    int choice = 0;
    do {
        cout << "\nVvedite '0', esli hotite otsortirovat po alfavity,\n"
            "ili '1', esli sortirovka ne trebyetsya.";
        cin >> choice;
        switch (choice) {
            case 0:
                Student *b;
                if (n > 0) {
                    for (size_t m = 0; m < (n - 1); m++) {
                        for (size_t a = (m + 1); a < n; a++) {
                            if (strcmp(excellentStudents[m]->name, excellentStudents[a]->name) > 0) {
                                b = excellentStudents[m];
                                excellentStudents[m] = excellentStudents[a];
                                excellentStudents[a] = b;
                            }
                        }
                    }
                }
            case 1:
                for (size_t j = 0; j < n; j++) {
                    cout << "\n\n[" << j << "]";
                    cout << "\nImya studenta: " << excellentStudents[j]->name;

                    cout << "\nNomer gruppi: " << excellentStudents[j]->group;

                    for (size_t s = 0; s < MARK_ARRAY_LEN; ++s) {
                        cout << "\nOcenka po predmetu '" << subjects[s] << "': " << excellentStudents[j]->mark[s];
                    }
                }
                break;
            default:
                cout << "Vvedeno nevernoe znachenie [" << choice << "]. Poprobuite snova.";
                break;
        }
    } while ((choice != 0) && (choice != 1));

    delete[] excellentStudents;
    delete[] students;

    return 0;
}

Неплохо получилось. Порадовал массив ссылок на структуры и финт с определением отличников.

Не понравился проскок без break из case 0 в case 1 в операторе switch. Такая конструкция работает правильно, но потенциально чревата ошибками. Здесь лучше просто спросить «Отсортировать отличников по алфавиту? [1/0]»; ввод проверить if'ом на равенство 1 (если равно, то сортируем), а дальше в любом случае вывод отличников на консоль. При этом избавляемся от switch и последнего цикла.

Не понравился проскок без break из case 0 в case 1 в операторе switch ....

Мой моск был отравлен вливаниями C++ 11-го стандарта ))

А если серьезно, то если по нормальному переделывать эту программу, то от исходного варианта только ключевые слова останутся. Кроме того, судя по заданию, уровень решения ожидается где-то на уровне конца 1-го семестра. Тут даже массив ссылок выглядит чужеродным ))

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.