Автоматизация процесса начисления стипендий

Тип работы:
Курсовая
Предмет:
Программирование


Узнать стоимость

Детальная информация о работе

Выдержка из работы

[Введите текст]

МИНИСТЕРСТВО ОБРАЗОВАНИЯ РЕСПУБЛИКИ БЕЛАРУСЬ

УЧРЕЖДЕНИЕ ОБРАЗОВАНИЯ «БЕЛОРУССКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ИНФОРМАТИКИ И РАДИОЭЛЕКТРОНИКИ»

КАФЕДРА: Экономической информатики

ФАКУЛЬТЕТ: Инженерно-экономический

ПОЯСНИТЕЛЬНАЯ ЗАПИСКА

к курсовому проекту по курсу: «Основы конструирования программ»

НА ТЕМУ: «Автоматизация процесса начисления стипендий»

МИНСК 2014

ЗАДАНИЕ К КУРСОВОМУ ПРОЕКТУ

Создать файл, содержащий сведения о результатах сдачи студентами сессии. Структура записи: номер группы, ФИО, оценки по 3 предметам, признак участия в общественной работе: 1 -активное участие, 0 — неучастие. Программа должна начислять студентам группы Х стипендию. При этом: отличники и общественники получают 50% надбавки, а просто отличники получают 25%. Студент-общественник с одной тройкой также получает стипендию.

ВВЕДЕНИЕ

Язык Си, созданный Денисом Ритчи в начале 70-х годов в Bell Laboratory американской корпорации AT& T, является одним из универсальных языков программирования. Язык Си считается языком системного программирования, хотя он удобен и для написания прикладных программ.

Среди преимуществ языка Си следует отметить переносимость программ на компьютеры различной архитектуры и из одной операционной системы в другую, лаконичность записи алгоритмов, логическую стройность программ, а также возможность получить программный код, сравнимый по скорости выполнения с программами, написанными на языке ассемблера. Последнее связано с тем, что хотя Си является языком высокого уровня, имеющим полный набор конструкций структурного программирования, он также обладает набором низкоуровневых средств, обеспечивающих доступ к аппаратным средствам компьютера. Си предлагает следующие важные особенности:

простую языковую базу, из которой вынесены в библиотеки многие существенные возможности, вроде математических функций или функций управления файлами;

ориентацию на процедурное программирование, обеспечивающую удобство применения структурного стиля программирования;

систему типов, предохраняющую от бессмысленных операций;

использование препроцессора для, например, определения макросов и включения файлов с исходным кодом;

непосредственный доступ к памяти компьютера через использование указателей;

минимальное число ключевых слов;

передачу параметров в функцию по значению, а не по ссылке (при этом передача по ссылке эмулируется с помощью указателей);

указатели на функции и статические переменные;

области действия имён;

структуры и объединения -- определяемые пользователем собирательные типы данных, которыми можно манипулировать как одним целым;

С 1989 года язык Си регламентируется стандартом Американского института национальных стандартов ANSI С. В настоящее время, кроме стандарта ANSI C разработан международный стандарт ISO C (International Standard Organization C).

Каждое высшее учебное заведение стремится простимулировать учёбу и активную общественную деятельность своих студентов. Одним из способов стимулирования в таком случае является начисление стипендий. Сам процесс начисления стипендий довольно трудоёмкий: необходимо определить критерии, по которым будут отбираться студенты для получения стипендии, определить минимальную ставку начисления стипендии, определить таблицу коэффициентов, согласно которым стипендия может индексироваться в зависимости от величины достижений студенты и прочих факторов, влияющих на начисление денежной выплаты. Безусловно, автоматизация данного процесса является замечательным решением, упрощающим этот трудоёмкий процесс.

Изначально, стипендия-- регулярная финансовая помощь, оказываемая оплатой обучения, а иногда и выдачей ежемесячного пособия, учащимся, как правило, средних специальных и высших учебных заведений, а также аспирантами докторантам. В данном курсовом проекте рассматривается такой вид стипендии, как академическая стипендия. Она выдаётся в течение семестра по итогам предыдущей сессии (с коэффициентами, учитывающими разность в успехах). Студентам-первокурсникам, зачисленным на бюджет, в первом семестре выдаётся всем одинаковая (например, минимальная, предусмотренная законом).

Целью данного курсового проекта является создание программы на языке программирования С для автоматизации подсчёта и начисления стипендии студентам учебного заведения. Для выполнения этой цели необходимо выделить следующие задачи: изучить особенности и ошибки при начислении стипендии, определить критерии начисления стипендии, выявить необходимость и актуальность данного программного продукта, составить вспомогательные алгоритмы и схемы для описания работы программы.

Для реализации данной идеи необходимо определить структуру, описывающую студента, и содержащую такие поля, как: номер группы, ФИО, оценки по 3 предметам, признак участия в общественной работе. Для организации списка студентов должен использоваться двусвязный список.

Данная программа предполагает поддержку работы с двумя видами пользователей: администратор и обычный пользователь. При этом их права различаются. Вход в систему выполняется при помощи ввода логина и пароля.

1. ТЕОРИТИЧЕСКИЕ СВЕДЕНИЯ ОБ ИСПОЛЬЗУЕМЫХ АЛГОРИТМАХ

1.1 Библиотеки

«stdafx. h» — одна из главных библиотек, определяющая функции ввода-вывода, такие как: fflush (), fclose (), fopen (), fgets (), fputs (), printf (), scanf () и многие другие.

< stdlib. h> - заголовочный файл стандартной библиотеки языка Си, который содержит в себе функции, занимающиеся выделением памяти, контроль процесса выполнения программы, преобразования типов и другие. В данной программе использовалась функция system («cls») — очистка экрана консоли.

< stdio. h> - заголовочный файл стандартной библиотеки языка Си, содержащий определения макросов, константы и объявления функций и типов, используемых для различных операций стандартного ввода и вывода.

< string. h> - заголовочный файл стандартной библиотеки языка Си, содержащий функции для работы с нуль-терминированными (строка представляется в виде массива символов, а концом строки считается первый встретившийся специальный нуль-символ) строками и различными функциями работы с памятью. В программе использовался оператор strcmp () из данной библиотеки.

< conio. h> - библиотека, содержащая функции для работы с консолью. В данной программе использовался оператор getch () из этой библиотеки.

1.2 Операторы

Для организации условных и безусловных переходов в программе используются операторы: if — else, switch

Оператор -- наименьшая автономная часть языка программирования; команда.

Операторыif-else используются для выбора одного из двух направлений дальнейшего хода программы в зависимости от истинности/ложности условия.

Оператор switch предназначен для организации выбора из множества различных вариантов.

1.3 Прочее

Структура — это объединение одного или нескольких объектов (переменных, массивов, указателей, других структур и т. д.), наборы данных которых могут быть как одного, так и разного типов.

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

Массив располагается в оперативной памяти, а не на внешнем устройстве, как файлы. Элементы массива занимают подряд идущие ячейки, в отличие, например, от списков.

Функция — это совокупность объявлений и операторов, обычно предназначенная для решения конкретной задачи.

Файл — это набор данных, размещенный на внешнем носителе и рассматриваемый в процессе обработки и пересылке как единое целое.

Используемые функции и операторы:

if, switch — условные операторы.

break -оператор перехода, предназначенный для прерывания цикла.

printf () — форматный вывод данных на экран.

scanf () — считывание данных с клавиатуры.

while- операторы выполнения тела цикла, пока условие истинно.

for — оператор, выполняющий тело цикла, пока переменная не достигнет конечного значения.

system («cls») — очистка экрана консоли.

fflush (stdin) — очистка буфера ввода.

fopen (), fclose () — операторы открытия — закрытия файла.

fprintf () — запись данных в файл.

fscanf () — считывание данных из файла.

2. ОПИСАНИЕ ОРГАНИЗАЦИИ СТРУКТУР ХРАНИМЫХ ДАННЫХ

2.1 Простые структуры для работы с пользователями и студентами

В данной программе реализованы две структуры для хранения данных о студентах и пользователях: структуры studentи user_data соответственно. Рассмотрим каждую из них.

Структура user_data служит для хранения данных о пользователях и содержит поля: char login[15] для хранения логина пользователя, char password[15] для пароля, char rights[6] для определения прав пользователя, bool active для характеристики активности (забанен или нет).

Структура studentхранит информацию о студентах и характеризуется следующими полями: char group[7] для номера группы, char name[35] для Ф.И.О. студента, int mark[3] для трёх оценок, bool social для описания общественной активности.

2.2 Двусвязные списки для работы с пользователями и студентами

Для реализации хранения набора данных о пользователях и студентах реализовано два двусвязных списка.

Для работы со студентами сперва создаётся структура node, которая описывает узел списка и содержит такие поля: studentdata для хранения данных о студенте, node *prev — указатель на предыдущий узел, node *next — указатель на следующий узел. Также описана структура student_list для создания непосредственно списка, она описывается следующими полями: node *first — указатель на первый элемент списка, node *last — указатель на последний элемент списка, intsize — размерность списка, а также совокупностью функций, описанных в пункте 3.2.

Для работы с пользователями создаётся структура node_user_data, содержащая поля: user_data data — хранение информации о пользователе, node_user_data *prev — указатель на предыдущий узел списка, node_user_data *next — указатель на следующий узел списка. Также имеется структура user_data_list для формирования двусвязного списка пользователей, включающая поля: node_user_data *first — указатель на первый элемент списка, node_user_data *last — указатель на последний элемент, int size — размерность списка. Помимо этого имеется ряд функций, описанных в пункте 3. 4

3. ОПИСАНИЕ ПОЛЬЗОВАТЕЛЬСКИХ ФУНКЦИЙ ПРИЛОЖЕНИЯ

3. 1 Функции обработки данных о студенте

Функция void change () предназначена для изменения информации о текущем студенте, содержит в себе вывод на экран текущих имеющихся данных о студентах и включает в себя меню, которое даёт возможность выбрать конкретное поле структуры Студент для изменения или выйти в меню верхнего уровня. Для реализации выбора поля для изменения используется конструкция switch-case, где в зависимости от выбора пользователя вызывается та или иная «подзависимая» функция: void enter_name (), void enter_group (), void enter_mark (), void enter_social ().

Рассмотрим подробнее каждую из зависимых функций.

Функция void enter_name () необходима для редактирования имени студента, выводит на экран предложение ввести Ф.И.О. и считывает введённую строку.

Функция void enter_group () также предлагает пользователю ввести номер группы, считывает строку и проверяет её длину на размерность не более шести символов.

Функция void enter_mark () работает аналогично предыдущим и проверяет, лежит ли введённая отметка в диапазоне от четырёх до 10 включительно.

Функция void enter_social () содержит подменю, в котором пользователю предлагает ввести единицу, если студент является активистом, и ноль -- в противном случае. Программа автоматически проставляет в поле соответствующее значение true или false, меню реализовано при помощи конструкции switch-case.

3. 2 Функции для работы с двусвязным списком студентов

Перво-наперво определена функция void init (), предназначенная для начальной инициализации полей списка, она проставляет в них нулевые и NULL-значения для числовых полей и указателей соответственно.

Далее идёт функция void add_front (student pdata) для добавления данных в начало списка. В качестве параметра приходят данные о студенте. В функции рассматриваются два случая: список пуст и необходимо создать первый и единственный пока элемент; первый или более элемент уже существует и необходимо добавить к нему ещё один. Если мы создаём первый элемент, то сперва выделяем память под новый узел, записываем в него данные о студенте, обнуляем указатели на предыдущий и следующий узел, указатель на последний элемент инициализируем первым, т.к. они совпадают в случае одного элемента, инкрементируем счётчик количества элементов. Если в списке уже имеется хотя бы один элемент, то необходимо выделить память для нового узла, записать в него данные о студенте, указатель на следующий узел проинициализировать указателем на первый узел, указатель на предыдущий узел --NULL. Для первого узла указатель на предыдущий узел инициализируется текущим узлом, который мы собираемся добавлять, сам он занимает место первого узла в списке, размер списка инкрементируется на единицу.

Функция voidadd_back (studentpdata) необходима для добавления данных в конец списка. Реализована аналогично добавлению в конец, только с работой с последним узлом. Также рассматривается два случая: список пуст и в списке имеется хотя бы один элемент.

Функция voidrem (intindex) для удаления элемента. В качестве параметра принимается индекс элемента, который необходимо удалить. Рассматриваются следующие ситуации: список пуст, тогда удалять нечего; удаляется первый элемент; удаляется последний элемент; удаляется единственный элемент списка; удаляется элемент из середины списка.

Функция studentget (intindex) возвращает информацию о студенте по заданному индексу. Поиск нужного элемента в списке осуществляется при помощи цикла.

Функция int get_size () возвращает текущее значение размера списка.

Функция voidchange (intindex) нужна для замены данных о студенте по указанному индексу в списке. Предусматривает ввод неверного индекса (лежит за пределами диапазона от нуля до количества элементов списка); список пуст и нельзя ничего изменять; изменяется первый элемент списка; изменяется последний элемент списка; изменяется элемент в середине списка (не первый и не последний).

Функция вывода содержимого списка на экран void print (). Если список пуст, то выводится предупреждение, иначе выводится таблица с имеющимися данными.

Функция void clear () для очистки всего списка. Если размер списка не равен нулю, то в цикле вызывается функция удаления элемента по индексу, описанная выше.

Функции voidfilter_soc (), voidfilter_soc_group (), voidfilter_soc_excellent (), voidfilter_name (), voidfilter_group (), voidfilter_name_group () предназначены для поиска данных о студентах по конкретному полю (критерию) или комбинации полей. Если список пуст, то выводится предупреждение, в противном случае строится таблица с данными, удовлетворяющими критериям фильтрации.

Функция void complete_target () проверяет, пустой ли список. Если список пуст, то выводится сообщение, иначе пользователю предлагается ввести номер группы. Для данной группы формируется таблица с данными о студентах, стипендии, среднем балле (предварительно высчитывается из трёх имеющихся оценок). Средний балл сравнивается с четвёркой и восьмёркой, в зависимости от результатов сравнения начисляется стипендия в том или ином размере.

3. 3 Функции для работы с пользователями

Сперва идёт функция voidinit (char *prights), необходимая для начальной инициализации данных о пользователе. В качестве параметра выступает информация о правах. Значение параметра копируется в значение прав пользователя, а он активируется.

Функция void enter_login () необходима для ввода логина пользователя, при этом введённая строка не должна превышать 15 символов.

Функция void enter_password () для введения пароля пользователя. Сперва на экран выводится приглашение ввести пароль. Пароль считывается посимвольно, каждый символ сверяется на нажатие клавиши ввода или удаления. В случае нажатия клавиши «Enter» в конец пароля дописывается символ конца строки, в случае клавиши удаления и при ненулевой строке последний символ стирается. Если же символ не совпадает ни с одним из этих двух вариантов, то он выводится на экран в виде символа звёздочки с целью безопасности пароля. Длина пароля не должна превышать 15 символ. В конце данной функции вызывается другая функция по шифровке пароля.

Функция void encrypt () нужна для шифровки пароля. Для этого высчитывается длина пароля, умножается на 11, далее прибавляется код каждого символа, умноженный на 11. Полученное числовое значение приводим к символьному типу и получаемый готовый зашифрованный пароль.

3.4 Функции для работы с двусвязным списком пользователей

Функция void init () для начальной инициализации. Ставит значение длины списка равным нулю и значения указателей на первый и последний элемент списка равными NULL.

Функция voidadd_front (user_datapdata) необходима для добавления информации о пользователях в начало списка. Рассматриваются два случая: список пуст и будет добавлен первый элемент; список уже содержит хотя бы один элемент. Принцип действия аналогичен принципу работы функции void add_front (student pdata) для работы со списком студентов, описанной в пункте 3.2.

Функция voidadd_back (user_datapdata) предназначена для добавления информации о пользователях в конец двусвязного списка. Рассматриваются случаи пустого списка и списка с уже имеющимися записями. Принцип действия аналогичен функции voidadd_back (studentpdata) для работы со списком студентов, описанной в пункте 3. 2

Функция voidrem (intindex) для удаления элемента из списка по заданному индексу. Если список пуст, то выводится предупреждение. Также рассматриваются ситуации: удаление первого элемента списка; удаление последнего элемента списка; удаление единственного элемента в списке; удаление элемента из середины списка (не первый и не последний). Принцип действия аналогичен одноимённой функции по работе со списком студентов, описанной в пункте 3.2.

Функция user_data& get (intindex) возвращает информацию о пользователе по заданному индексу в списке. Для поиска нужного элемента используется цикл.

Функция int get_size () возвращает значение размера списка.

Функция void print () выводит на экран данные об имеющихся в списке пользователях в виде таблицы. Если список пуст, то на экран выводится предупреждение.

Функция void clear () полностью очищает список, если он не пустой. Для этого в цикле, не превосходящем размерность списка, вызывается метод rem (i), который удаляет элемент по индексу. Таким образом в цикле удаляются последовательно все имеющиеся записи в списке.

3.5 Функции для организации работы программы

Функция boolauthorize (char *rights) необходима для авторизации пользователей в системе. В качестве параметра принимает информацию о правах пользователя. Для работы создаёт структуру, описывающую пользователя, производит начальную инициализацию, вызывает методы введения логина и пароля пользователя, описанные в пункте 3.3. Далее открывается файл для чтения данных о пользователях, ищется необходимая запись. Если она имеется и права активированы, то файл закрывается, а функция возвращает true, что означает, что пользователь может авторизоваться. Если записи с такими данными нет либо права заблокированы, то файл закрывается, а функция возвращает false, что означает, что пользователь не может авторизоваться.

Функция voidmenu_rule_users () позволяет работать с имеющимся списком пользователей. Для этого открывается файл с данными, которые сохраняются в список пользователей. На экран выводится меню для выбора действия над имеющимся списком. Если пользователь выбирает «Добавить пользователя», то ему предлагает определить, будет ли новый пользователь администратором или обычным пользователем, а также ввести логин и пароль. Далее можно выбрать «Удалить пользователя», в таком случае необходимо ввести индекс пользователя для удаления. Пункт меню «Забанить пользователя» позволяет менять его права, зная индекс пользователя в списке. Также можно просмотреть всех имеющихся пользователей или выйти из меню.

Функция void menu_admin () представляет собой меню для администратора. Оно предполагает следующие возможности: выбрать файл для работы с данными, добавить запись, отредактировать запись, удалить запись, посмотреть все записи, поиск и фильтрация данных, управление пользователями, выход из учётной записи.

Функция void menu_user () является меню для обычного пользователя и предоставляет следующие возможности: выбрать файл для работы с данными, просмотреть все записи, выполнить задачу, поиск и фильтрация данных, выход из учётной записи. Как видно, меню пользователя сродни меню администратора, однако предполагает меньший спектр функциональных возможностей.

Функция char* choose_file () даёт пользователю возможность выбрать файл для работы. Для этого пользователь вводит имя файл (не более 25 символов). Если файла с таким именем не существует на данный момент, то он создаётся.

Функция voidread_file (char *filename) необходима для чтения данных из файла, имя которого приходит в качестве параметра функции. При этом данные из файла заносятся в список.

Функция voidwrite_file (char *filename) предназначена для записи данных в файл. При этом записи последовательно извлекаются из списка и переносятся в файл.

Функция void add_student () добавляет информация о студенте, предварительно введённую пользователем, в конец списка студентов.

Функция void change_student () редактирует информация о студентах. Делается это следующим образом: сперва на экран выводятся все записи о студентах, а затем пользователю предлагается ввести индекс студента, информацию о котором надо отредактировать. При этом вызывает функция редактирования для списка студентов.

Функция void delete_student () позволяет удалять студентов из списка по введённому пользователем индексу. Принцип аналогичен предыдущей функции.

Функция void print_student () выводит информацию о всех имеющихся с списке студентах.

4. СХЕМЫ АЛГОРИТМОВ РАБОТЫ ПРИЛОЖЕНИЯ

4. 1Алгоритм добавления информации о студентах в начало двусвязного списка

код листинг информация приложение

Данный алгоритм реализуется в виде функции void add_front (student pdata).

void add_front (student pdata) {

if (size == 0) {

first = new node ();

first-> data = pdata;

first-> next = NULL;

first-> prev = NULL;

last = first;

size++;

}

else {

node *temp = new node ();

temp-> data = pdata;

temp-> next = first;

temp-> prev = NULL;

first-> prev=temp;

first = temp;

size++;

};

}

Рассмотрим данный алгоритм подробней.

Сперва идёт проверка на размерность списка: в зависимости от того, пуст список или нет, необходимо по-разному действовать. Если список пуст, то выполняются следующие действия:

выделяется память под первый узел списка;

в данные этого узла заносятся данные, введённые пользователем;

для первого узла указатель на следующий узел приравнивается NULL;

для первого узла указатель на предыдущий узел приравнивается NULL;

указатель на последний узел приравнивается указателю на первый узел;

размер списка инкрементируется на единицу.

Если же список имеет хотя бы один элемент, то необходима следующая последовательность действий:

выделяется память для нового узла;

в его данные заносится введённая пользователем информация о студенте;

указатель на следующий узел для созданного нового узла приравнивается указателю на первый узел;

указатель на предыдущий узел для созданного нового узла приравнивается NULL;

указатель на предыдущий узел для первого элемента приравнивается указателю на новый узел;

указатель на первый узел приравнивается указателю на новый узел;

размер списка инкрементируется на единицу.

После этого функция прекращает свою работу.

Рисунок 4.1 — Блок-схема алгоритма добавления элемента в начало двусвязного списка

4.2 Алгоритм удаления информации о студенте из двусвязного списка по индексу

Данный алгоритм реализуется в виде функции voidrem (intindex).

void rem (int index) {

if (size == 0) {

printf («Списокпуст!n»);

system («pause»);

} else if (index == 1 & & index≠ size) {

node *temp = first;

first-> next->prev = NULL;

first = first-> next;

delete temp;

size--;

} else if (index == size & & index≠1) {

node *temp = last;

last-> prev->next = NULL;

last = last-> prev;

delete temp;

size--;

} else if (index == size & & index == 1) {

delete first;

first = NULL;

last = NULL;

size--;

} else if (index > 1 & & index < size) {

node *current = first;

for (int i=1; i< index; i++) {

current = current-> next;

}

current-> prev->next = current-> next;

current-> next->prev = current-> prev;

delete current;

size--;

};

}

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

указатель на временный узел инициализируется указателем на первый узел;

снимается связанный с первым элементом указатель на предыдущий;

далее назначается первым элементом следующий за ним элемент;

удаляется временный элемент;

размер уменьшается на единицу.

Если предыдущее условие не выполняется, то следует проверка на удаление последнего элемента. Если она выполняется, то:

указатель на временный элемент инициализируется указателем на последний узел;

снимается связанный с последним элементом указатель наследующий;

далее назначается последним элементом идущий перед ним элемент;

удаляется временный элемент;

размер уменьшается на единицу.

Если предыдущее условие не выполняется, то происходит проверка на удаление единственного элемента из списка. Если это так, то:

удаляется первый элемент;

указатель на первый элемент приравнивается NULL;

указатель на последний элемент приравнивается NULL;

размер уменьшается на единицу.

Если и это условие не выполняется, то происходит проверка, удаляется ли элемент из середины списка. Если условие выполняется, то необходимы следующие действия:

указатель на текущий узел инициализируется первым;

в цикле от i=1 до i< index с шагом инкрементации, равным единице, перемещаемся по списку через указатель на следующий узел от текущего;

обнуляем связанные с элементов указатели;

удаляем текущий узел;

уменьшаем размер на единицу.

Если условие не выполняется, то функция прекращает свою работу.

Рисунок 4.2 — Алгоритм удаления записи из двусвязного списка по индексу

4.3 Алгоритм фильтрации данных о студентах по имени

Данный алгоритм реализуется с помощью функции voidfilter_name ().

void filter_name () {

if (size == 0) {

system («cls»);

printf («Списокпуст!n»);

} else {

node *current = first;

int i = 1;

student s;

s. enter_name ();

system («cls»);

printf («# | Группа | ФамилияИмяОтчество | О.1 | О.2 | О.3 | Соц |n»);

printf («----|--------|-------------------------------------|-----|-----|-----|-----|n»);

while (current ≠ NULL) {

student stud = current-> data;

if (strcmp (s. name, stud. name)==0) %6s

i++;

current = current-> next;

}

printf («----|--------|-------------------------------------|-----|-----|-----|-----|n»);

}

};

Рисунок 4.3 — Алгоритм фильтрации данных о студентах по имени

Сперва проверяется, пустой список или нет. Если пустой, то выводится предупреждение, если нет, выполняется следующая последовательность действий:

значению текущего узла присваивается указатель на первый узел;

вводится переменная i, равная единице;

объявляется структура s типа student;

вызывается функция для ввода пользователем имени студента;

выводится на экран шапка таблицы;

при помощи цикла происходит проход по списку, если имя записи совпадает с введённым, то запись попадает в таблицу;

наращивается счётчик i на единицу происходит перемещение по списку через указатель на следующий узел;

выводится окончание таблицы.

5. ОПИСАНИЕ ПРОГРАММЫ

Прежде всего, чтобы начать работы с системой, мы должны выполнить авторизацию. Для этого предназначена функция authorize, которая принимает параметры права (пользователь либо администратор) и предлагает ввести логин и пароль. Далее сверка с данными в файле. В случае, если пользователь не забанен и такие данные существуют, то открывается доступ к работе с данными. Если же эти условия не выполняются, то выводится сообщение о том, что данные введены неправильно. В данной программе содержится 2 типа пользователей: обычные пользователи и администратор. В дальнейшем, всё зависит от прав, пользователь имеет возможность выполнять либо набор обычного пользовательского функционала, предоставленного пользовательским меню (выбрать файл для работы с данными, просмотреть все записи, выполнить задачу, поиск и фильтрация данных, выход из учётной записи), либо набор администраторского функционала, предоставляемого меню администратора (выбрать файл для работы с данными, добавить запись, отредактировать запись, удалить запись, посмотреть все записи, поиск и фильтрация данных, управление пользователями, выход из учётной записи).

Первое и второе меню первым пунктом предлагают выбрать файл для работы. Для этого необходима функция char* choose_file (), она открывает имеющийся с таким именем файл или создаёт новый файл с указанным именем. При помощи двух двусвязных списков, хранящих информацию о студентах и пользователях, происходит взаимодействие данных с файлом. За счёт реализованных в списках функций есть возможность добавлять, удалять, редактировать, фильтровать записи, получать данные и размер списка, очищать список и другое. Сами же эти функции описаны внутри структуры, которая описывает сам список.

Главным пунктом меню стоит считать пункт «Выполнить задачу», так как именно он решает поставленную задачу. Для выполнения этого пункта реализована функция void complete_target (). Она работает со списком имеющихся студентов, определённых степенью активности и группой, высчитывает средний балл из трёх имеющихся и в зависимости от этого начисляет стипендию в том или ином размере.

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

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

Для работы со студентами и пользователями реализованы 2 различные структуры, хранящие данные о тех и других, и два двусвязных списка, хранящих информацию о наборах первых и вторых. Оба списка поддерживают практически одинаковый набор функций: добавление в начало, конец, очистка, удаление, получение данных, печать и др.

При запуске программы пользователю предлагается сперва предлагается три варианта: войти как администратор, войти как пользователь, выход.

Рисунок 5.1 — Меню первого уровня

Рассмотрим случай выбора работы в качестве администратора. После ввода логина и пароля в случае нахождения таковых в файле предлагается выбрать файл для работы с данными.

Рисунок 5.2 — Выбор файла для работы

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

Рисунок 5.3 — Меню администратора

При выборе добавления записи последовательно предлагает ввести Ф.И.О., номер группы, три отметки и определить, является ли студент активистом. После этого администратор вновь выходит в меню.

Выберем просмотр всех записей. На экране появилась табличка с добавленным ранее пользователем.

Рисунок 5.4 — Вывод данных на экран

Далее добавим ещё одного студента с неактивной общественной позицией и выберем пункт меню «Фильтрация и поиск», в качестве параметра поиска будем принимать неактивных студентов группы 222 223. В результате на экране появится таблица с добавленным нами пользователем.

Рисунок 5.5 — Фильтрация и поиск данных

При этом при выводе всех студентов на экран получим следующую таблицу:

Рисунок 5.6 — Вывод данных о студентах

Если мы войдём в систему в качестве пользователя, воспользуемся уже заполненным файлом и решим узнать о стипендиях, то в группе 111 112 будут следующие данные начисления стипендии:

Рисунок 5.7 — Начисление стипендии студентам

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

ЗАКЛЮЧЕНИЕ

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

Программа удовлетворяет поставленным изначально условиям: реализована возможность работы двух видов пользователей с разным уровнем прав и доступа (администратор и обычный пользователь), при этом поддерживается авторизация пользователей с вводом логина и пароля, пароль шифруется; использована работа с файлами (чтение, запись); в программе используются структуры для описания сущностей, а также двусвязные списки для работы с набором данных; имеются меню нескольких уровней; используются встроенные функции для работы со строками; предусмотрена обработка ситуаций ввода неверных данных. Данные выводятся на экран в виде таблицы, код оформлен в соответствии с Code Convension.

Решена задача, поставленная в условии: формируется список студентов для начисления стипендии, зависящей от их учебных достижений и общественной активности. Интерфейс программы поддерживает русский язык.

СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ

1. Кормен, Т. Алгоритмы: учебник / Т. Кормен [и др.].: Москва — Санкт-Петербург — Киев 2005. — 1290 с.

2. С. Панасенко — Алгоритмы шифрования — СПб.: БХВ-Петербург, 2009

3. Дейтел, П. Дж. Как програмировать на Си / учебник: Бином-Пресс, 2009. — 994 с.

4. Б. Керниган, Д. Ритчи — Язык программирования Си — Вильямс, 2009

5. Р. Хэзфилд — Искусство программирования на С- Диа-Софт, 2001

6. Wikipedia [Электронный ресурс]. — http: //ru. wikipedia. org

7. БГУИР [Электронный ресурс] - официальный сайт высшего учебного заведение БГУИР. -http: //www. bsuir. by

ПРИЛОЖЕНИЕ А

Блок-схемы

Рисунок 1 — Блок-схема алгоритма добавления элемента в начало двусвязного списка

Рисунок 2 — Алгоритм удаления записи из двусвязного списка по индексу

Рисунок 3 — Алгоритм фильтрации данных о студентах по имени

ПРИЛОЖЕНИЕ Б

Листинг кода

#pragma once

//структура с данными о студенте

structstudent

{

//группа

char group[7];

//фио

char name[35];

//3 оценки

intmark[3];

//активист или нет

bool social;

//функция изменения информации о студенте

void change () {

char symbol;

do {

//вывод на экран текущих данных

system («cls»);

printf («Группа | Фамилия Имя Отчество | О.1 | О.2 | О.3 | Соц |n»);

printf («--------|-------------------------------------|-----|-----|-----|-----|n»);

printf («%6s | %35s | %3d | %3d | %3d | %3s |n», group, name, mark[0], mark[1], mark[2], social?"Да": «Нет»);

printf («--------|-------------------------------------|-----|-----|-----|-----|nn»);

//меню

printf («1) Изменить Ф.И.О. n»);

printf («2) Изменить группуn»);

printf («3) Изменить оценкиn»);

printf («4) Изменить социальную активностьn»);

printf («0) Вернуться в главное менюn»);

printf («>: «);

fflush (stdin);

scanf («%c», & symbol);

//просто вызов соответствующих функций ввода информации

switch (symbol) {

case '1':

enter_name ();

break;

case '2':

enter_group ();

break;

case '3':

enter_mark ();

break;

case '4':

enter_social ();

break;

default:

break;

}

} while (symbol ≠ '0');

}

//вводФИО

void enter_name () {

system («cls»);

printf («ВведитеФ.И.О. n»);

printf («>: «);

fflush (stdin);

//используем для того, чтобы не набрать больше 35 символов

gets_s (name, 35);

OemToCharA (name, name);

}

//ввод группы

void enter_group () {

do {

system («cls»);

printf («Введите группуn»);

printf («>: «);

fflush (stdin);

//тоже самое с fgets, не больше 7 символов

fgets (group, 7, stdin);

group[strlen (group)]='';

//проверка на длину

if (strlen (group)> =6) {

break;

}

} while (true);

}

//ввод оценки

void enter_mark () {

system («cls»);

//циклна 3 оценки

for (int i=0; i< 3; i++) {

do{

printf («Введите оценку #%d», (i+1));

printf («>: «);

fflush (stdin);

scanf («%d», & mark[i]);

//проверка что больше или равно 4 и меньше или равно 10

if (mark[i] >= 4 & & mark[i] <= 10) {

break;

}

} while (true);

}

}

//ввод активист или нет

void enter_social () {

char symbol;

do {

system («cls»);

printf («1) Активистn»);

printf («0) Не активистn»);

printf («>: «);

fflush (stdin);

scanf («%c», & symbol);

switch (symbol) {

case '1':

social = true;

symbol='';

break;

case '0':

social = false;

symbol='';

break;

default:

break;

}

} while (symbol≠'');

}

};

#pragma once

#include «student. h»

#define MIN_INCOME 400 000

//узел списка, двусвязного

struct node {

//данные узла

student data;

//указатель на предыдущий

node *prev;

//указатель на следующий

node *next;

};

struct student_list {

//указатель на первый элемент

node *first;

//указатель на последний элемент

node *last;

//размерсписка

intsize;

//функция для начальной инициализации

void init () {

size = 0;

first = NULL;

last = NULL;

}

//добавление в начало списка

void add_front (student pdata) {

//если список пуст

if (size == 0) {

//выделяем память

first = new node ();

//записываем данные

first-> data = pdata;

//обнуляем указателя на след и пред

first-> next = NULL;

first-> prev = NULL;

//последний он же будет и первым

last = first;

//увеличиваем размер

size++;

}

//если список не пуст

else {

//выделяем память

node *temp = newnode ();

//записываем данные

temp-> data = pdata;

//указатель на след теперь указываем на первый

temp-> next = first;

//предыдущегонет

temp-> prev = NULL;

//указатель на предыдущий первого элемента указывает на новый элемент

first-> prev=temp;

//новый элемент становится первым

first = temp;

//увеличиваем размер

size++;

};

}

//добавление в конец списка

void add_back (student pdata) {

//если список пуст

if (size == 0) {

//выделяем память

last = new node ();

//записываемданные

last-> data = pdata;

//указатели на пред и след не существуют

last-> next = NULL;

last-> prev = NULL;

//первый он же последний

first = last;

//увеличиваем размер

size++;

}

//если список не пуст

else {

//выделяемпамять

node *temp = newnode ();

//записываем данные

temp-> data = pdata;

//указатель на предыдущий нового элемента указывает на последний элемент

temp-> prev = last;

//указатель на след нового элемента пуст

temp-> next = NULL;

//указатель на следующий последнего указывает теперь на новый элемент

last-> next = temp;

//новый элемент теперь последний

last = temp;

//увеличиваем размер

size++;

};

}

//функция дял удаления по индексу

void rem (int index) {

//если удалять нечего, то выводи на экран предупреждение

if (size == 0) {

printf («Списокпуст!n»);

system («pause»);

//если удаляем первый элемент

} else if (index == 1 & & index≠ size) {

//запоминаем его указатель

node *temp = first;

//снимаем связанный с первым элементом указатель на предыдущий

first-> next->prev = NULL;

//теперь первый элемент — это следующий за первым

first = first-> next;

//удаляем запомненный первый элемент

delete temp;

//уменьшаем размер

size--;

//если удаляем последний, то примерно тоже самое происходит

} else if (index == size & & index≠1) {

node *temp = last;

last-> prev->next = NULL;

last = last-> prev;

delete temp;

size--;

//если удаляем элемент, который является единственным в списке

} else if (index == size & & index == 1) {

//просто удаляем

delete first;

//обнуляем указатели на первый и последний элементы

first = NULL;

last = NULL;

//уменьшаемразмер

size--;

//если удаляем из середины списка

} else if (index > 1 & & index < size) {

node *current = first;

//в цикле проходим от начала списка до нужного места

for (int i=1; i< index; i++) {

current = current-> next;

}

//обнуляем связанные с элементмо указатели

current-> prev->next = current-> next;

current-> next->prev = current-> prev;

//удаляем элемент

delete current;

//уменьшаем размер

size--;

};

}

//функция получение элемента из списка

student get (int index) {

node *current = first;

//проходим по циклу до нужного элемента

for (int i=1; i< index; i++) {

current = current-> next;

}

//возвращаем содержимое узла

return current-> data;

}

//размер списка

int get_size () {

//возвращаем размер списка

return size;

}

//функция изменения элемента списка

voidchange (intindex) {

//проверка на индексы

if (index<= 0 || index> size) {

printf («Неверный индекс! n»);

system («pause»);

//на размер списка

} else if (size == 0) {

printf («Списокпуст!n»);

system («pause»);

//если изменяем первый, то вызываем функция изменения из структуры со студентом

} else if (index == 1) {

first-> data. change ();

//если последний, то точно также

} else if (index == size) {

last-> data. change ();

//если где-то посередине списка

} else if (index > 1 & & index < size) {

node *current = first;

//проходим в цикле до нужного элемента

for (int i=0; i< index; i++) {

current = current-> next;

}

//вызываем функцию изменения из структуры со студентом

current-> data. change ();

}

}

//функция распечатки

voidprint () {

//если размер равен 0, то выводим предупреждение

if (size == 0) {

system («cls»);

printf («Списокпуст!n»);

} else О. 3

}

//функция очистки списка

void clear () {

//если есть что очищать

if (size > 0) {

//в цикле вызываем функцию удаления по индексу

for (int i=1; i< =size; i++) {

rem (i);

}

}

}

voidfilter_soc () {

//если размер равен 0, то выводим предупреждение

if (size == 0) {

system («cls»);

printf («Списокпуст!n»);

} else {

//иначе рисуем красивую таблицу, проходясь в цикле по всему списку

node *current = first;

int i = 1;

student s;

s. enter_social ();

system («cls»);

printf («# | Группа | ФамилияИмяОтчество | О.1 | О.2 | О.3 | Соц |n»);

printf («----|--------|-------------------------------------|-----|-----|-----|-----|n»);

while (current ≠ NULL) {

student stud = current-> data;

if (s. social == stud. social) %3d

i++;

current = current-> next;

}

printf («----|--------|-------------------------------------|-----|-----|-----|-----|n»);

}

};

void filter_soc_group () {

//если размер равен 0, то выводим предупреждение

if (size == 0) {

system («cls»);

printf («Списокпуст!n»);

} else {

//иначе рисуем красивую таблицу, проходясь в цикле по всему списку

node *current = first;

int i = 1;

student s;

s. enter_social ();

s. enter_group ();

system («cls»);

printf («# | Группа | ФамилияИмяОтчество | О.1 | О.2 | О.3 | Соц |n»);

printf («----|--------|-------------------------------------|-----|-----|-----|-----|n»);

while (current ≠ NULL) {

student stud = current-> data;

if (strcmp (s. group, stud. group)==0 & & s. social == stud. social) %3d

i++;

current = current-> next;

}

printf («----|--------|-------------------------------------|-----|-----|-----|-----|n»);

}

};

void filter_soc_excellent () {

//если размер равен 0, то выводим предупреждение

if (size == 0) {

system («cls»);

printf («Списокпуст!n»);

} else {

//иначе рисуем красивую таблицу, проходясь в цикле по всему списку

node *current = first;

int i = 1;

system («cls»);

printf («# | Группа | ФамилияИмяОтчество | О.1 | О.2 | О.3 | Соц |n»);

printf («----|--------|-------------------------------------|-----|-----|-----|-----|n»);

while (current ≠ NULL) {

student stud = current-> data;

int avg = stud. mark[0] + stud. mark[1] + stud. mark[2];

avg/=3;

if (stud. social & & avg >= 8) %35s

i++;

current = current-> next;

}

printf («----|--------|-------------------------------------|-----|-----|-----|-----|n»);

}

};

void filter_group () {

//если размер равен 0, то выводим предупреждение

if (size == 0) {

system («cls»);

printf («Списокпуст!n»);

} else {

//иначе рисуем красивую таблицу, проходясь в цикле по всему списку

node *current = first;

int i = 1;

student s;

s. enter_group ();

system («cls»);

printf («# | Группа | ФамилияИмяОтчество | О.1 | О.2 | О.3 | Соц |n»);

printf («----|--------|-------------------------------------|-----|-----|-----|-----|n»);

while (current ≠ NULL) {

student stud = current-> data;

if (strcmp (s. group, stud. group)==0)

printf («%3d

i++;

current = current-> next;

}

printf («----|--------|-------------------------------------|-----|-----|-----|-----|n»);

}

};

void filter_name_group () {

//если размер равен 0, то выводим предупреждение

if (size == 0) {

system («cls»);

printf («Списокпуст!n»);

} else {

//иначе рисуем красивую таблицу, проходясь в цикле по всему списку

node *current = first;

int i = 1;

student s;

s. enter_name ();

s. enter_group ();

system («cls»);

printf («# | Группа | ФамилияИмяОтчество | О.1 | О.2 | О.3 | Соц |n»);

printf («----|--------|-------------------------------------|-----|-----|-----|-----|n»);

while (current ≠ NULL) {

student stud = current-> data;

if (strcmp (s. name, stud. name)==0 & & strcmp (s. group, stud. group)==0) n", i, stud. group, stud. name, stud. mark[0], stud. mark[1],

stud. mark[2], stud. social?"Да":"Нет");

i++;

current = current-> next;

}

printf («----|--------|-------------------------------------|-----|-----|-----|-----|n»);

}

};

void complete_target () {

//если размер равен 0, то выводим предупреждение

if (size == 0) {

system («cls»);

printf («Списокпуст!n»);

} else {

//иначе рисуем красивую таблицу, проходясь в цикле по всему списку

node *current = first;

int i = 1;

student s;

s. enter_group ();

system («cls»);

printf («# | Группа | Фамилия Имя Отчество | %-7s | Соц | %-9s |n», «Ср. балл», «Стипендия»);

printf («---|--------|-------------------------------------|---------|-----|-----------|n»);

while (current ≠ NULL) {

student stud = current-> data;

if (strcmp (stud. group, s. group)==0) {

int income;

int avg = stud. mark[0] + stud. mark[1] + stud. mark[2];

avg/=3;

if (avg > 4) {

income = MIN_INCOME;

if (avg>= 8 & &stud. social) {

income += MIN_INCOME/2;

} else if (avg >= 8) {

income += MIN_INCOME/4;

}

} else {

income = 0;

}

printf («%2d | %6s | %35s | %-7d | %3s | %-9d |n», i, stud. group, stud. name, avg,

stud. social?"Да":"Нет", income);

}

i++;

current = current-> next;

}

printf («---|--------|-------------------------------------|---------|-----|-----------|n»);

}

};

};

#pragma once

//структура с данными о пользователе

struct user_data

{

//логин

char login[15];

//пароль

charpassword[15];

//права доступа

charrights[6];

//забанен или нет

bool active;

//функция для начальной инициализации

void init (char *prights) {

strcpy (rights, prights);

active = true;

}

//вводлогина

void enter_login () {

system («cls»);

printf («Введите логин. Помните, что максимальная длина логина 15 символов! n»);

printf («>: «);

fflush (stdin);

//через fgets чтобы не набрать больше 15 символов

fgets (login, 15, stdin);

login[strlen (login)-1]='';

}

//вводпароля

void enter_password () {

char symbol;

int index = 0;

system («cls»);

printf («Введите пароль. Помните, что максимальная длина пароля 15 символов! n»);

printf («>: «);

do

{

//читаем посимвольно

fflush (stdin);

symbol = _getch ();

switch (symbol)

{

case 8:

//если клавиша удаления, удаляем последний символ с консоли

if (index > 0) {

printf («b b»);

index--;

}

break;

case 13:

//если enter, то ставим ноль-символ

password[index] = '';

break;

default:

//если что-то другое, то сохраняем введенный символ и выводим на экран звездочку

password[index] = symbol;

password[index+1] = '';

_putch ('*');

index++;

break;

}

} while (symbol ≠ 13 & & index < 15);

//в конце ввода шифруем пароль

encrypt ();

}

//шифрование пароля

void encrypt () {

char *result = new char[strlen (password)];

int hash = 0;

//умножаем длину пароля на 11

hash = 11 * strlen (password);

//прибавляем к полученному ранее результату код каждого символа, умноженный на 11

for (int i=0; i< strlen (password)-1; i++) {

hash *= 11 * password[i];

}

//из инта переделываем в char, в 16-ричной системе счисления, таким образом получаем зашифрованный пароль

_itoa (hash, result, 16);

//копируем зашифрованный пароль

strcpy (password, result);

}

};

#pragmaonce

#include «user_data. h»

//узелсписка, двусвязного

structnode_user_data {

//данные узла

user_datadata;

//указатель на предыдущий

node_user_data *prev;

//указатель наследующий

node_user_data *next;

};

struct user_data_list {

//указатель на первый элемент

node_user_data *first;

//указатель на последний элемент

node_user_data *last;

//размер списка

int size;

//функция для начальной инициализации

void init () {

size = 0;

first = NULL;

last = NULL;

}

//добавление в начало списка

void add_front (user_data pdata) {

//если список пуст

if (size == 0) {

//выделяем память

first = new node_user_data ();

//записываем данные

first-> data = pdata;

//обнуляем указателя на след и пред

first-> next = NULL;

first-> prev = NULL;

//последний он же будет и первым

last = first;

//увеличиваем размер

size++;

}

//если список не пуст

else {

//выделяем память

node_user_data *temp = new node_user_data ();

//записываем данные

temp-> data = pdata;

//указатель на след теперь указываем на первый

temp-> next = first;

//предыдущего нет

temp-> prev = NULL;

//указатель на предыдущий первого элемента указывает на новый элемент

first-> prev=temp;

//новый элемент становится первым

first = temp;

//увеличиваем размер

size++;

};

}

//добавление в конец списка

void add_back (user_data pdata) {

//если список пуст

if (size == 0) {

//выделяем память

last = new node_user_data ();

//записываем данные

last-> data = pdata;

//указатели на пред и след не существуют

last-> next = NULL;

last-> prev = NULL;

//первый он же последний

first = last;

//увеличиваем размер

size++;

}

//если список не пуст

else {

//выделяем память

node_user_data *temp = new node_user_data ();

//записываем данные

temp-> data = pdata;

//указатель на предыдущий нового элемента указывает на последний элемент

ПоказатьСвернуть
Заполнить форму текущей работой