#include <iostream>
#include <iomanip>
int i = 0;
template<typename T>
class linkedlist {
private:
struct node {
node *prev;
node *next;
T data;
node() {
}
node(node *prev, node *next, const T &data) :
prev(prev), next(next), data(data) {
}
};
node first;
node last;
public:
linkedlist() :
first(nullptr, &last, T()),
last(&first, &last, T()) {
}
linkedlist(const T & nil) :
first(nullptr, &last, nil),
last(&first, &last, nil) {
}
linkedlist(const linkedlist<T> &other) :
first(nullptr, &last, T()),
last(&first, &last, T()) {
(*this) = other;
}
class iterator {
friend class linkedlist;
private:
node *current_node;
iterator(node *current_node) : current_node(current_node) {
}
public:
iterator(const iterator &other_iterator) : current_node(other_iterator.current_node) {
}
T &operator*() {
return current_node->data;
}
const T &operator*() const {
return current_node->data;
}
iterator &operator++() {
current_node = current_node->next;
return *this;
}
iterator operator++(int) {
iterator tmp = iterator(*this);
++(*this);
return tmp;
}
bool operator!=(const iterator &other) const {
return current_node != other.current_node;
}
bool operator==(const iterator &other) const {
return current_node == other.current_node;
}
};
class const_iterator {
friend class linkedlist;
private:
const node *current_node;
const_iterator(const node *current_node) : current_node(current_node) {
}
public:
const_iterator(const const_iterator &other_iterator) : current_node(other_iterator.current_node) {
}
const T &operator*() const {
return current_node->data;
}
const_iterator &operator++() {
current_node = current_node->next;
return *this;
}
const_iterator operator++(int) {
const_iterator tmp = const_iterator(*this);
++(*this);
return tmp;
}
bool operator!=(const const_iterator &other) const {
return current_node != other.current_node;
}
bool operator==(const const_iterator &other) const {
return current_node == other.current_node;
}
};
T &append(const T &data) {
node *new_node = new node(last.prev, &last, data);
new_node->prev->next = new_node;
new_node->next->prev = new_node;
return new_node->data;
}
iterator &erase(iterator &&iterator) {
if (iterator.current_node == &first || iterator.current_node == &last)
return iterator;
node *to_remove = iterator.current_node;
++iterator;
to_remove->prev->next = to_remove->next;
to_remove->next->prev = to_remove->prev;
delete to_remove;
return iterator;
}
iterator erase(iterator &iterator) {
if (iterator.current_node == &first || iterator.current_node == &last)
return iterator;
node *to_remove = iterator.current_node;
++iterator;
to_remove->prev->next = to_remove->next;
to_remove->next->prev = to_remove->prev;
delete to_remove;
return iterator;
}
iterator begin() {
return iterator(first.next);
}
iterator end() {
return iterator(&last);
}
const_iterator cbegin() const {
return const_iterator(first.next);
}
const_iterator cend() const {
return const_iterator(&last);
}
iterator find(const T &data) {
for (iterator it = begin(); it != end(); ++it) {
T ¤t_item = *it;
if (current_item == data) {
return it;
}
}
return end();
}
bool operator==(const linkedlist<T> &other) {
const_iterator other_it = other.cbegin();
const_iterator self_it = cbegin();
while (other_it != other.cend() || other_it != other.cend()) {
if (*self_it != *other_it) return false;
++self_it;
++other_it;
}
return other_it == other.cend() && other_it == other.cend();
}
linkedlist<T>&operator=(const linkedlist<T> &other) {
this->first.data = other.first.data;
this->last.data = other.last.data;
for (linkedlist<T>::const_iterator it = other.cbegin(); it != other.cend(); it++) {
append(*it);
}
return *this;
}
~linkedlist() {
while (begin() != end()) {
erase(begin());
}
}
};
struct student {
double grade[100];
std::string name;
linkedlist<std::string> courses;
student() : name(""), courses("") ,grade() {
}
student(const student &student) : name(student.name), courses(student.courses) {
}
student(const std::string &name) : name(name), courses("") , grade() {
}
student(const double &grade) : name(name), courses("") {
}
bool operator==(const student &other) {
return name == other.name && courses == other.courses;
}
};
linkedlist<student> database;
linkedlist<student> grade;
void add_course(student &std) {
std::cout << "Main > Student \"" << std.name << "\"" << " > Add course" << std::endl;
while (true) {
std::cout << "Enter course to add (or \"back\" to go back): ";
std::string query;
std::cin >> query;
double grades;
std::cout <<"Enter Grade :";
std::cin >> grades;
std.grade[i] = grades;
i++;
if (query == "back")
return;
linkedlist<std::string>::iterator found = std.courses.find(query);
if (found == std.courses.end()) {
std.courses.append(query);
for (linkedlist<student>::const_iterator it = database.cbegin(); it != database.cend(); it++ ) {
const student &older_student = *it;
}
std::cout << "Course " << "\"" << query << "\"" << " successfully created" << std::endl;
return;
}
else {
std::cout << "Course " << "\"" << query << "\"" << " already exists" << std::endl;
}
}
}
void remove_course(student &std) {
std::cout << "Main > Student \"" << std.name << "\"" << std::endl;
while (true) {
std::cout << "Enter course to remove (or \"back\" to go back): ";
std::string query;
std::cin >> query;
if (query == "back")
return;
linkedlist<std::string>::iterator found = std.courses.find(query);
if (found == std.courses.end()) {
std::cout << "Course " << "\"" << query << "\"" << " Not found" << std::endl;
}
else {
std.courses.erase(found);
std::cout << "Course " << "\"" << query << "\"" << " successfully removed" << std::endl;
return;
}
}
}
void remove_student(student &std) {
linkedlist<student>::iterator iterator = database.find(std);
database.erase(iterator);
std::cout << "Student \"" << std.name << "\" removed successfully" << std::endl;
}
void show_courses(student &std) {
int j=0;
std::cout << "Main > Student \"" << std.name << "\" > Course List" << std::endl;
int i = 0;
for (linkedlist<std::string>::const_iterator it = std.courses.cbegin(); it != std.courses.cend(); it++) {
std::string course_name = *it;
std::cout << " Course Name : " << course_name << " / Grade : " << std.grade[j];
j++;
}
}
void student_menu(student &std) {
while (true) {
std::cout << "Main > Student \"" << std.name << "\"" << std::endl
<< "\t1) Add course" << std::endl
<< "\t2) Remove course" << std::endl
<< "\t3) Show courses" << std::endl
<< "\t4) Remove student" << std::endl
<< "\t5) Go back" << std::endl
<< "Enter your option: ";
int option = 0;
std::cin >> option;
switch (option) {
case 1:
std::cout << std::endl;
add_course(std);
std::cout << std::endl;
break;
case 2:
std::cout << std::endl;
remove_course(std);
std::cout << std::endl;
break;
case 3:
std::cout << std::endl;
show_courses(std);
std::cout << std::endl;
break;
case 4:
std::cout << std::endl;
remove_student(std);
return;
case 5:
return;
default:
std::cout << "Invalid option: " << option << std::endl;
}
}
}
void add_student() {
std::cout << "Main > Create new student " << std::endl;
std::string student_name;
while (true) {
std::cout << "Enter student name (or \"back\" to go back): ";
std::cin >> student_name;
if (student_name == "back")
return;
if (student_name.empty()) {
std::cout << "Error: Student name can not be empty!" << std::endl;
continue;
}
for (linkedlist<student>::const_iterator it = database.cbegin(); it != database.cend(); it++) {
const student &older_student = *it;
if (older_student.name == student_name) {
std::cout << "Error: Student already exists" << std::endl;
continue;
}
}
std::cout << "Student \"" << student_name << "\" created successfully" << std::endl;
break;
}
student student(student_name);
std::cout << std::endl;
student_menu(database.append(student));
}
void list_students() {
std::cout << "Main > List students" << std::endl;
int i = 0;
for (linkedlist<student>::const_iterator it = database.cbegin(); it != database.cend(); it++) {
const student &std = *it;
std::cout << std::setw(5) << std::left << ++i << std.name << std::endl;
}
}
void find_student() {
std::cout << "Main > Find student" << std::endl;
while (true) {
std::cout << "Enter student name (or enter \"back\" to go back): ";
std::string query;
std::cin >> query;
if (query == "back") return;
for (linkedlist<student>::iterator it = database.begin(); it != database.end(); it++) {
student &std = *it;
if (std.name == query) {
student_menu(std);
break;
}
}
std::cout << "Error: Student not found!" << std::endl;
}
}
void main_menu() {
while (true) {
std::cout << "Main" << std::endl
<< "\t1) Add student" << std::endl
<< "\t2) List students" << std::endl
<< "\t3) Find a student" << std::endl
<< "\t4) Exit" << std::endl
<< "Enter your option: ";
int option = 0;
std::cin >> option;
std::cout << std::endl;
switch (option) {
case 1:
add_student();
break;
case 2:
list_students();
break;
case 3:
find_student();
break;
case 4:
std::cout << "Goodbye";
return;
default:
std::cout << "Invalid option: " << option << std::endl;
}
std::cout << std::endl;
}
}
int main() {
main_menu();
return EXIT_SUCCESS;
}