Главная страница
Навигация по странице:

  • Завершение сеанса работы программы

  • Ядро работы программы: входные параметры: массив/вектор аккаунтов,массив/вектор данных, размеры массивовВывод главного меню

  • Вход в систему: входные параметры: массив/вектор аккаунтов, массив/вектор данных, размеры массивовАвторизация

  • Модуль пользователя: входные параметры: массив/вектор данных,размер массива данных itemБесконечный цикл 1Бесконечный цикл 1showUserMenuВывод

  • 6 Рекомендации по программированию курсовой работы 6.1 Типичные ошибки начинающих при написании кода. Способы отслеживания и устранения ошибок.

  • Для отслеживания и устранения ошибок

  • 6.2 Структуры. Запись и чтение из файла

  • Первый пример: работа с файлом выполняется в текстовом режиме.

  • Второй пример: работа с файлом выполняется в бинарном режиме.

  • Методические указания к выполнению курсовой работы по дисциплине «Основы конструирования программ». 1_Меженная_ОКП_Курсовое_проектирование_Пособие. Курсовое проектирование


    Скачать 2.04 Mb.
    НазваниеКурсовое проектирование
    АнкорМетодические указания к выполнению курсовой работы по дисциплине «Основы конструирования программ
    Дата10.05.2023
    Размер2.04 Mb.
    Формат файлаpdf
    Имя файла1_Меженная_ОКП_Курсовое_проектирование_Пособие.pdf
    ТипРеферат
    #1118858
    страница4 из 6
    1   2   3   4   5   6
    Предварительные настройки:
    подключение русскоязычной локали;
    вывод информации о программе:
    название, ФИО разработчика
    Начало сеанса работы программы:
    объявление и резервирование памяти под массивы/векторы; чтение информации из файлов в массивы/векторы
    Ядро работы программы:
    авторизация; регистрация (если предусмотрена); реализация функционала пользователя или администратора
    Завершение сеанса работы программы:
    запись информации из массивов/векторов в файлы; очистка памяти (для динамически созданных массивов)
    Рисунок 5.4 – Пример алгоритма главной функции main

    40 core mainMenu choiceMenuItem
    Конец
    Ядро работы программы:
    входные параметры: массив/вектор аккаунтов,
    массив/вектор данных, размеры массивов
    Вывод главного меню:
    1-авторизация
    2-регистрация (если предусмотрена)
    0-завершение работы программы
    Ввод пункта меню
    возвращает item - целое положительное число из диапазона возможных пунктов меню
    Бесконечный цикл 1
    item logIn
    Бесконечный цикл 1
    registration
    = 0
    = 1
    = 2
    Рисунок 5.5 – Пример алгоритма функции core: основная логика программы

    41 logIn authorization
    Конец
    Вход в систему:
    входные параметры: массив/вектор аккаунтов, массив/вектор данных, размеры массивов
    Авторизация:
    входные параметры: массив/вектор аккаунтов,
    размер массива аккаунтов; возвращает role (роль)
    Бесконечный цикл 1
    role
    Бесконечный цикл 1
    adminModule
    = 0
    иное
    = 1
    userModule
    Такой пользователь не найден repeatRequest
    Повторить авторизацию?
    Запрос
    на повтор действия;
    возвращает ответ
    Нет
    Да
    Рисунок 5.6 – Пример алгоритма функции logIn: вход в систему

    42 authorization
    Возврат current_role
    Авторизация:
    входные параметры: массив/вектор аккаунтов,
    размер массива аккаунтов;
    возвращает role (роль)
    Обнаружено совпадение?
    Нет
    Да
    Сравниваем current_login и current_password с соответствующими полями i-го элемента массива/вектора int current_login;
    int current_password;
    int current_role =
    -
    1;
    int i = 0
    Цикл 1
    Пока i < размера массива/вектора и current_role = =
    -
    1
    current_role присваиваем значение роли i-го элемента массива/вектора i = i + 1
    Цикл 1
    Ввод current_login current_password
    Рисунок 5.7 – Пример алгоритма функции authorization: авторизация

    43 userModule
    Конец
    Модуль пользователя:
    входные параметры: массив/вектор данных,
    размер массива данных item
    Бесконечный цикл 1
    Бесконечный цикл 1
    showUserMenu
    Вывод
    меню пользователя choiceMenuItem
    Ввод пункта меню
    возвращает item - целое положительное число из диапазона возможных пунктов меню searchData sortData individualTask showData
    = 0
    = 1
    = 2
    = 3
    = 4
    Рисунок 5.8 – Пример алгоритма функции userModule: функционал пользователя

    44 showData
    Конец
    Вывод данных на экран:
    входные параметры: массив/вектор данных,
    размер массива данных showTableTitle i = 0; i < размера массива/вектора;
    i = i + 1
    Вывод i-го элемента массива/вектора
    Вывод
    названий столбцов таблицы данных
    Рисунок 5.9 – Пример алгоритма функции showData: вывод данных на экран

    45
    6 Рекомендации по программированию курсовой работы
    6.1 Типичные ошибки начинающих при написании кода. Способы
    отслеживания и устранения ошибок.
    Создание exe-файла проекта
    Типичные ошибки начинающих при написани кода:
    1. Пропуск «;» в конце инструкции или размещение «;» там, где это не нужно.
    2. Путаница в количестве открывающихся «{» и закрывающихся «}» скобок
    (пишите обе скобки одновременно!).
    3. Использование в условных конструкциях знака присвоения «=» вместо «=
    =».
    4. Ни о чем не говорящие имена переменных и функций.
    5. Объявление служебных переменных и попытка их использования без инициализации (без присвоения начального значения).
    6. «Магические» числа и строки в коде.
    7. Отсутствие освобождения памяти (с помощью оператора delete) после ее ручного выделения (с помощью оператора new).
    8. Использование слишком длинных функций, которые в реальности следо- вало бы разбить на несколько функций.
    9. Сложная (неочевидная, неоптимальная) логика решения задачи.
    10. Аргументация «Но программа же работает!» в ответ на замечания по ло- гике работы программы, «недружественному» интерфейсу и оформлению кода.
    Для отслеживания и устранения ошибок рекомендуется использовать сле- дующие подходы в том порядке, в котором они перечислены далее:
    1. Построение (сборка) проекта в среде разработки.
    2. Отладка в пошаговом режиме.
    3. Рефакторинг.
    Частая сборка проекта, выполняемая в процессе работы над кодом, позволяет быстро выявлять ошибки компиляции и компоновки, например неверный синтак- сис, несоответствия типов и другое (рисунок 6.1) и своевременно их устранять.
    Успешная сборка – это подтверждение правильности синтаксиса кода прило- жения и корректного разрешения всех статических ссылок на библиотеки. Однако успешная сборка не исключает наличие логических ошибок, о которых будут сви- детельстовать неверные результаты работы программы. Логические ошибки мо- гуть быть эффективно локализованы посредством отладки программы, позволяю- щей узнать текущие значения переменных; выяснить, по какому пути выполня- лась программа. Существуют две взаимодополняющие технологии отладки:
    1. Пошаговое выполнение программы с остановками на строчках исходного кода (рисунок 6.2).
    2. Логирование – вывод текущего состояния программы с помощью располо- женных в критических точках программы операторов вывода.

    46
    Рисунок 6.1 – Пример обнаружения ошибки сборки проекта
    1 – устанавливаем точку остановки, 2 – после запуска программы переходим от точки остановки к следующей инструкции посредством панели инструментов для пошаговой отладки;
    3 – отслеживаем значения переменных в процессе отладки
    Рисунок 6.2 – Пример отладки программы в пошаговом режиме

    47
    Помимо синтаксических и логических ошибок собственно качество кода про- граммы зачастую нуждается в улучшении – рефакторинге. Рефакторинг – процесс изменения внутренней структуры программы, не затрагивающий ее внешнего по- ведения и имеющий целью облегчить понимание ее работы. Ни о чем не говоря- щие имена переменных и функций, «магические» числа и строки в коде, исполь- зование слишком длинных функций, сложная (неочевидная, неоптимальная) логи- ка – вот примеры проблем, которые необходимо решить на стадии рефакторинга.
    После полного тестирования приложения и рефакторинга целесообразно скомпилировать итоговую release-версию проекта (помимо отладочной debug- версии) – рисунки 6.3, 6.4.
    Рисунок 6.3 – Выбор версии проекта для сборки: debug или release
    Рисунок 6.4 – Изменение динамического связывания библиотек времени выполнения на статическое связывание

    48
    Следует отметить, что приложения, созданные с помощью Microsoft Visual
    Studio, зависят от Visual С++ Redistibutable и динамически связаны с библиотека- ми MSVCR**.dll (Microsoft C Runtime Library). Для последующих запусков exe- файла на других компьютерах, которые потенциально могут не содержать требуе- мых библиотек (не установлена Microsoft Visual Studio или версия установленной
    Microsoft Visual Studio ниже требуемой) перед сборкой итоговой версии необхо- димо изменить динамическое связывание библиотек времени выполнения на ста- тическое связывание. Для этого требуется перейти к свойствам проекта (щелкнув правой кнопкой мыши на имени проекта в Обозревателе решений), а в разделе
    C/С++ → Создание кода найти параметр Библиотека времени выполнения. Его необходимо изменить с Многопоточная DLL (/MD) на Многопоточная (/MT) – см. рисунок 6.4.
    6.2 Структуры. Запись и чтение из файла
    В языке C++ потоки, которые позволяют читать и записывать информацию в файл, являются объектами классов ifstream, ofstream. Они находятся в библиотеке с заголовочным файлом :

    ifstream: класс, функции которого используются для чтения файлов;

    ofstream: класс, функции которого используются для записи файлов.
    Название класса эквивалентно типу переменной, поэтому после названия класса объявляется объект, тип которого будет соответствовать классу. Для ини- циализации объектов в конструктор класса необходимо передать параметры: пер- вый параметр – путь к файлу, второй параметр – режим работы с файлом. Кон- станты режима файлов:

    ios::in – открыть файл для чтения;

    ios::out – открыть файл для записи;

    ios::ate – перейти к концу файла после открытия;

    ios::app – добавлять к концу файла;

    ios::binary – бинарный файл.
    Далее приведены два примера записи и чтения в файл.
    Первый пример: работа с файлом выполняется в текстовом режиме. В качестве строковых полей структуры используем класс string, структуры объеди- няем в статически создаваемые локальные массивы, запись и чтение выполняем посредством указания всех полей структуры.

    49
    Приведенный ниже пример ориентирован на статически создаваемые масси- вы, а именно включает целый ряд проверок выхода за пределы зарезервированной под статический массив памяти.
    С точки зрения скорости данный вариант работы с файлом уступает второму варианту, однако сам файл содержит информацию в текстовом виде (также при ручной записи в файл информации требуемого формата она впоследствии может быть корректно считана программно).
    #include

    #include

    #include

    using namespace std; struct
    Student
    { string name; string surname; int age;
    };
    // Запись в файл (если что-то было в файле, то исходные данные будут удалены):
    void writeFileStudents(
    Student
    *
    arr_of_students
    , int number_of_students
    );
    // Добавление в конец файла одной строки:
    void writeEndFileStudents(
    Student new_student
    );
    // Чтение из файла в массив:
    void readFileStudents(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    );
    // Заполнение массива студентов void generateStudentArray(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    );
    // Добавление студента в массив void addStudentInArray(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    );
    // Удаление студента из массива void delStudentFromArray(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    );
    // Вывод содержимого массива на экран void showStudentArray(
    Student
    *
    arr_of_students
    , int number_of_students
    ); const string
    FILE_OF_DATA =
    "MyFile.txt"
    ;
    //Путь к файлу const int
    RESERVE_SIZE = 100;
    //Максимальное количество элементов массива

    50 void main()
    { setlocale(
    LC_ALL
    ,
    "rus"
    );
    Student arr_of_students[RESERVE_SIZE]; int number_of_students = 0; generateStudentArray(arr_of_students, number_of_students); writeFileStudents(arr_of_students, number_of_students); addStudentInArray(arr_of_students, number_of_students); showStudentArray(arr_of_students, number_of_students); delStudentFromArray(arr_of_students, number_of_students); showStudentArray(arr_of_students, number_of_students);
    Student arr_new_of_students[RESERVE_SIZE];
    /* Создаем новый массив исключительно для того, чтобы продемонстрировать корректность чтения данных из файла */
    int new_number_of_students = 0; readFileStudents(arr_new_of_students, new_number_of_students); showStudentArray(arr_new_of_students, new_number_of_students); system(
    "pause"
    );
    } void generateStudentArray(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    )
    { number_of_students
    = 2; arr_of_students
    [0].name
    =
    "Alex"
    ; arr_of_students
    [0].surname
    =
    "Black"
    ; arr_of_students
    [0].age = 20; arr_of_students
    [1].name
    =
    "Ivan"
    ; arr_of_students
    [1].surname
    =
    "Ivanov"
    ; arr_of_students
    [1].age = 25;
    } void addStudentInArray(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    )
    {

    51
    //добавление студента, если не происходит выход за пределы массива if
    (
    number_of_students
    + 1 <= RESERVE_SIZE)
    { number_of_students
    ++; cout
    <<
    "Введите имя студента: "
    ; cin
    >>
    arr_of_students
    [
    number_of_students
    - 1].name; cout
    <<
    "Введите фамилию студента: "
    ; cin
    >>
    arr_of_students
    [
    number_of_students
    - 1].surname; cout
    <<
    "Введите возраст студента: "
    ; cin
    >>
    arr_of_students
    [
    number_of_students
    - 1].age; writeEndFileStudents(
    arr_of_students
    [
    number_of_students
    - 1]);
    } else cout
    <<
    "Недостаточно памяти для добавления нового элемента!"
    <<
    endl;
    } void delStudentFromArray(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    )
    { int number_of_deleted_item; cout
    <<
    "Введите номер удаляемой записи: "
    ; cin
    >>
    number_of_deleted_item;
    // пользователь мыслит с 1, но индексы нумеруются с 0
    : number_of_deleted_item--; if
    (number_of_deleted_item >= 0 && number_of_deleted_item < number_of_students
    )
    { for
    (
    int i = number_of_deleted_item; i < number_of_students
    - 1; i++) arr_of_students
    [i]
    =
    arr_of_students
    [i + 1]; number_of_students
    --; writeFileStudents(
    arr_of_students
    , number_of_students
    );
    } else cout
    <<
    "Введен некорректный номер удалемой записи!"
    <<
    endl;
    } void showStudentArray(
    Student
    *
    arr_of_students
    , int number_of_students
    )
    { for
    (
    int i = 0; i<
    number_of_students
    ; i++) cout
    <<
    arr_of_students
    [i].name
    <<
    " "

    52
    <<
    arr_of_students
    [i].surname
    <<
    " "
    <<
    arr_of_students
    [i].age
    <<
    endl;
    } void writeFileStudents(
    Student
    *
    arr_of_students
    , int number_of_students
    )
    { ofstream fout(FILE_OF_DATA, ios
    ::out);
    // Открыли файл для записи for
    (
    int i = 0; i<
    number_of_students
    ; i++)
    { fout
    <<
    arr_of_students
    [i].name
    <<
    " "
    <<
    arr_of_students
    [i].surname
    <<
    " "
    <<
    arr_of_students
    [i].age; if
    (i<
    number_of_students
    - 1)
    { fout
    <<
    endl;
    }
    } fout.close();
    } void writeEndFileStudents(
    Student new_student
    )
    { ofstream fadd(FILE_OF_DATA, ios
    ::app);
    // Открыли файл для дозаписи fadd
    <<
    endl; fadd
    <<
    new_student
    .name
    <<
    " "
    <<
    new_student
    .surname
    <<
    " "
    <<
    new_student
    .age; fadd.close();
    } void readFileStudents(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    )
    { ifstream fin(FILE_OF_DATA, ios
    ::in);
    // Открыли файл для чтения if
    (!fin.is_open()) cout
    <<
    "Указанный файл не существует!"
    <<
    endl; else
    { int i = 0; while
    (!fin.eof())
    { if
    (i < RESERVE_SIZE)

    53
    { fin
    >>
    arr_of_students
    [i].name
    >>
    arr_of_students
    [i].surname
    >>
    arr_of_students
    [i].age; i++;
    } else
    { cout
    <<
    "Недостаточно памяти для чтения всех данных!"
    <<
    endl; break
    ;
    }
    } number_of_students
    = i;
    } fin.close();
    //Закрыли файл
    }
    При работе с динамически создаваемыми массивами целесообразно запраши- вать память в процессе выполнения программы, соответствующую количеству структур, записанных в файле. Для этого ниже приведена функция определения количества структур, записанных в текстовый файл (что соответствует количеству строчек в файле) – getCountOfStucturesInFile(
    string file_path
    ).
    // Определение количества структур в файле (при необходимости)
    int getCountOfStucturesInFile(
    string file_path
    )
    { ifstream file(
    file_path
    , ios
    ::in);
    // Открыли текстовый файл для чтения int number_of_strings = 0; if
    (file.is_open())
    { string buffer; while
    (getline(file, buffer)) number_of_strings++;
    } file.close(); return number_of_strings;
    }
    Второй пример: работа с файлом выполняется в бинарном режиме. Сна- чала приведем ряд пояснений по особенностям чтения и записи в файл в бинарном режиме.

    54
    При записи единичной структуры в бинарный файл записываем всю структу- ру целиком и сразу: ofstream fadd(FILE_OF_DATA, ios
    ::binary | ios
    ::app); fadd.write((
    char
    *)&
    new_student
    , sizeof
    (
    new_student
    ));
    /* Записываем структуру new_student в открытый нами файл; для этого узнаем адрес структуры new_student и приводим указатель на new_student к однобайтовому типу; указываем, что в структуре new_student находится sizeof(
    new_student)
    байт */ fadd.close();
    Из файла можно прочитать всю структуру целиком и сразу: ifstream fin(FILE_OF_DATA, ios
    ::binary | ios
    ::in); if
    (!fin.is_open()) cout
    <<
    "Указанный файл не существует!"
    <<
    endl; else
    { fin.read((
    char
    *)
    &
    temp_student
    , sizeof
    (
    temp_student
    ));
    } fin.close();
    При записи массива структур в бинарный файл записываем весь массив цели- ком и сразу: ofstream fout(FILE_OF_DATA, ios
    ::binary | ios
    ::out); fout.write((
    char
    *)&
    arr_of_students
    [0], sizeof
    (
    Student
    )*
    number_of_students
    ); fout.close();
    Из файла целесообразно читать весь массив структур целиком и сразу, однако для этого необходимо знать количество структур в бинарном файле: int getCountOfStucturesInFile(
    string file_path
    )
    {
    //Открываем файл и перемещаем указатель в конец файла ifstream file(FILE_OF_DATA, ios
    ::ate | ios
    ::binary);
    /* file.tellg() возвращает значение типа int, которое показывает, сколько ука- зателем пройдено в байтах от начала файла до текущей позиции */
    int number_of_strings = file.tellg() / sizeof
    (
    Student
    ); file.close();

    55 return number_of_strings;
    }
    Тогда собственно чтение в массив структур из файла программно реализуется следующим образом: ifstream fin(FILE_OF_DATA, ios
    ::binary | ios
    ::in); if
    (!fin.is_open()) cout
    <<
    "Указанный файл не существует!"
    <<
    endl; else
    { fin.read((
    char
    *)&
    arr_of_students
    [0], sizeof
    (
    Student
    )* getCountOfStucturesInFile(FILE_OF_DATA));
    } fin.close();
    Когда приходится записывать структуру или объект в файл, то внутри струк- туры может быть очень много информационных полей и при записи структуры в файл в текстовом режиме придется записывать каждый элемент структуры, а это отнимет много времени. В этом отношении данный вариант работы с файлом име- ет преимущество по скорости. Но заполненный таким способом файл при откры- тии в текстовом режиме нечитабельный, а попытка вручную записать информа- цию, чтобы считать ее программно, не приведет к желаемому результату.
    Далее приведен пример работы с файлом в бинарном режиме. В качестве строковых полей структуры используем строковые массивы, структуры объединя- ем в статически создаваемые локальные массивы.
    Приведенный ниже пример ориентирован на статически создаваемые масси- вы, а именно, включает целый ряд проверок выхода за пределы зарезервированной под статический массив памяти.
    #include

    #include

    #include

    using namespace std; const int
    SIZE_CHAR = 20; const int
    RESERVE_SIZE = 100; const string
    FILE_OF_DATA =
    "MyFile.txt"
    ;
    //Путь к файлу

    56 struct
    Student
    { char name[SIZE_CHAR]; char surname[SIZE_CHAR]; int age;
    };
    // Запись в файл (если что-то было в файле, то исходные данные будут удалены):
    void writeFileStudents(
    Student
    *
    arr_of_students
    , int number_of_students
    );
    // Добавление в конец файла одной строки:
    void writeEndFileStudents(
    Student new_student
    );
    // Чтение из файла в массив:
    void readFileStudents(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    );
    // Определение количества структур в файле (при необходимости)
    int getCountOfStucturesInFile(
    string file_path
    );
    //0 Заполнение массива студентов void generateStudentArray(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    );
    // Добавление студента в массив void addStudentInArray(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    );
    // Удаление студента из массива void delStudentFromArray(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    );
    // Вывод содержимого массива на экран void showStudentArray(
    Student
    *
    arr_of_students
    , int number_of_students
    ); void main()
    { setlocale(
    LC_ALL
    ,
    "rus"
    );
    Student arr_of_students[RESERVE_SIZE]; int number_of_students = 0; generateStudentArray(arr_of_students, number_of_students); writeFileStudents(arr_of_students, number_of_students); addStudentInArray(arr_of_students, number_of_students); showStudentArray(arr_of_students, number_of_students); delStudentFromArray(arr_of_students, number_of_students); showStudentArray(arr_of_students, number_of_students);

    57
    Student arr_new_of_students[RESERVE_SIZE];
    /* Создаем новый массив ис- ключительно для того, чтобы продемонстрировать корректность чтения данных из файла */
    int new_number_of_students = 0; readFileStudents(arr_new_of_students, new_number_of_students); showStudentArray(arr_new_of_students, new_number_of_students); system(
    "pause"
    );
    } void generateStudentArray(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    )
    { number_of_students
    = 2; strcpy_s(
    arr_of_students
    [0].name,
    "Alex"
    ); strcpy_s(
    arr_of_students
    [0].surname,
    "Black"
    ); arr_of_students
    [0].age = 20; strcpy_s(
    arr_of_students
    [1].name,
    "Alex1"
    ); strcpy_s(
    arr_of_students
    [1].surname,
    "Black1"
    ); arr_of_students
    [1].age = 27;
    } void addStudentInArray(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    )
    {
    //добавление студента, если не происходит выход за пределы массива if
    (
    number_of_students
    + 1 <= RESERVE_SIZE)
    { number_of_students
    ++; cout
    <<
    "Введите имя студента: "
    ; cin
    >>
    arr_of_students
    [
    number_of_students
    - 1].name; cout
    <<
    "Введите фамилию студента: "
    ; cin
    >>
    arr_of_students
    [
    number_of_students
    - 1].surname; cout
    <<
    "Введите возраст студента: "
    ; cin
    >>
    arr_of_students
    [
    number_of_students
    - 1].age; writeEndFileStudents(
    arr_of_students
    [
    number_of_students
    - 1]);
    }

    58 else cout
    <<
    "Недостаточно памяти для добавления нового элемента!"
    <<
    endl;
    } void delStudentFromArray(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    )
    { int number_of_deleted_item; cout
    <<
    "Введите номер удаляемой записи: "
    ; cin
    >>
    number_of_deleted_item;
    // пользователь мыслит с 1, но индексы нумеруются с 0:
    number_of_deleted_item--; if
    (number_of_deleted_item >= 0 && number_of_deleted_item < number_of_students
    )
    { for
    (
    int i = number_of_deleted_item; i < number_of_students
    - 1; i++) arr_of_students
    [i]
    =
    arr_of_students
    [i + 1]; number_of_students
    --; writeFileStudents(
    arr_of_students
    , number_of_students
    );
    } else cout
    <<
    "Введен некорректный номер удалемой записи!"
    <<
    endl;
    } void showStudentArray(
    Student
    *
    arr_of_students
    , int number_of_students
    )
    { for
    (
    int i = 0; i < number_of_students
    ; i++) cout
    <<
    arr_of_students
    [i].name
    <<
    " "
    <<
    arr_of_students
    [i].surname
    <<
    " "
    <<
    arr_of_students
    [i].age
    <<
    endl;
    } void writeFileStudents(
    Student
    *
    arr_of_students
    , int number_of_students
    )
    {
    //Открываем файл для записи:
    ofstream fout(FILE_OF_DATA, ios
    ::binary | ios
    ::out); fout.write((
    char
    *)&
    arr_of_students
    [0], sizeof
    (
    Student
    )*
    number_of_students
    ); fout.close();
    } void writeEndFileStudents(
    Student new_student
    )

    59
    {
    //Открываем файл для дозаписи:
    ofstream fadd(FILE_OF_DATA, ios
    ::binary | ios
    ::app); fadd.write((
    char
    *)&
    new_student
    , sizeof
    (
    new_student
    ));
    //Записали структуру fadd.close();
    } void readFileStudents(
    Student
    *
    arr_of_students
    , int
    &
    number_of_students
    )
    { ifstream fin(FILE_OF_DATA, ios
    ::binary | ios
    ::in); if
    (!fin.is_open()) cout
    <<
    "Указанный файл не существует!"
    <<
    endl; else
    {
    // определяем количество строк в файле int sizeOfFileWithStudents = getCountOfStucturesInFile(FILE_OF_DATA);
    /* если выделенная память под статический массив вмещает все строч- ки в файле */
    if
    (sizeOfFileWithStudents <= RESERVE_SIZE)
    {
    // будем считывать все строчки number_of_students
    = sizeOfFileWithStudents;
    } else
    {
    // иначе считаем ровно столько, насколько хватает места в массиве number_of_students
    = RESERVE_SIZE; cout
    <<
    "There is not enough memory for read all data!"
    <<
    endl;
    }
    /* читаем сразу number_of_students-строчек из файла и сохраняем их в массиве */
    fin.read((
    char
    *)&
    arr_of_students
    [0], sizeof
    (
    Student
    )*
    number_of_students
    );
    } fin.close();
    } int getCountOfStucturesInFile(
    string file_path
    )
    {
    //Открываем файл и перемещаем указатель в конец файла ifstream file(FILE_OF_DATA, ios
    ::ate | ios
    ::binary);

    60
    /*file.tellg() возвращает значение типа int, которое показывает, сколько ука- зателем пройдено в байтах от начала файла до текущей позиции */
    int number_of_strings = file.tellg() / sizeof
    (
    Student
    ); file.close(); return number_of_strings;
    }
    1   2   3   4   5   6


    написать администратору сайта