// Program: classlist
// File: classlist_vec.cpp
// Author: Chuck Stewart
// Purpose: Build and maintain a list of students enrolled in a class and a waiting list.
// Initially it uses vectors, but we will change it to use iterators, and then lists.
#include
#include
#include
#include
#include
using namespace std;
void enroll_student(const string& id_number, unsigned int max_students,
list& enrolled, list& waiting);
void remove_student(const string& id_number, unsigned int max_students,
list& enrolled, list& waiting);
void erase_from_list(list::iterator itr, list& lst);
int main() {
// Read in the maximum number of students in the course
unsigned int max_students;
cout << "\nWelcome to the enrollment program for CSCI 1200\n"
<< "Please enter the maximum number of students allowed\n";
cin >> max_students;
// Initialize the list
list enrolled;
list waiting;
// Invariant:
// (1) enrolled contains the students already in the course,
// (2) waiting contains students who would will to be admitted (in
// the order of request) if a spot opens up, in the
// (3) enrolled.size() <= max_students,
// (4) if the course is not filled (enrolled.size() != max_students)
// then waiting is empty
do {
// check (part of) the invariant
assert (enrolled.size() <= max_students);
assert (enrolled.size() == max_students || waiting.size() == 0);
cout << "\nOptions:\n"
<< " To enroll a student type 0\n"
<< " To remove a student type 1\n"
<< " To end type 2\n"
<< "Type option ==> ";
int option;
if (!(cin >> option)) {
// if we can't read the input integer, then just fail.
cout << "Illegal input. Good-bye.\n";
return 1;
} else if (option == 2) {
// quit by breaking out of the loop.
break;
} else if (option != 0 && option != 1) {
cout << "Invalid option. Try again.\n";
} else { // option is 0 or 1
string id_number;
cout << "Enter student id: ";
if (!(cin >> id_number)) {
cout << "Illegal input. Good-bye.\n";
return 1;
} else if (option == 0) {
enroll_student(id_number, max_students, enrolled, waiting);
} else {
remove_student(id_number, max_students, enrolled, waiting);
}
}
}
while (true);
// some nice output
enrolled.sort();
cout << "\nAt the end of the enrollment period, the following students\n"
<< "are in the class:\n\n";
for (list::iterator itr = enrolled.begin(); itr != enrolled.end(); itr++) {
cout << *itr << endl;
}
if (! waiting.empty()) {
cout << "\nStudents are on the waiting list in the following order:\n";
for (list::iterator itr = waiting.begin(); itr != waiting.end(); itr++) {
cout << *itr << endl;
}
}
return 0;
}
// Enroll a student in the course if there is room and if the student
// is not already in the course or on the waiting list.
void enroll_student(const string& id_number, unsigned int max_students,
list& enrolled, list& waiting) {
// Check to see if the student is already enrolled. If so, output a
// message and return.
list::iterator itr;
for (itr = enrolled.begin(); itr != enrolled.end(); itr++) {
if (*itr == id_number) {
cout << "Student " << id_number << " is already enrolled." << endl;
return;
}
}
// If the course isn't full, add the student. Then return.
if (enrolled.size() < max_students) {
enrolled.push_back(id_number);
cout << "Student " << id_number << " added.\n" << enrolled.size()
<< " students are now in the course." << endl;
return;
}
// Otherwise, we have to deal with the waiting list. Check to see
// if the student is already on the waiting list.
for (itr = waiting.begin(); itr != waiting.end(); itr++) {
if (*itr == id_number) {
cout << "Student " << id_number << " is already on the waiting list." << endl;
return;
}
}
// Otherwise, add the student to the waiting list.
waiting.push_back(id_number);
cout << "The course is full. Student " << id_number
<< " has been added to the waiting list.\n" << waiting.size()
<< " students are on the waiting list." << endl;
}
// Remove a student from the course or from the waiting list. If
// removing the student from the course opens up a slot, then the
// first person on the waiting list is placed in the course.
void remove_student(const string& id_number, unsigned int max_students,
list& enrolled, list& waiting) {
// Check to see if the student is on the course list.
bool found = false;
list::iterator itr;
for (itr = enrolled.begin(); itr != enrolled.end(); itr++) {
found = (*itr == id_number);
if (found) break;
}
// If so, remove the student and see if a student can be taken from the waiting list.
if (found) {
erase_from_list(itr,enrolled);
cout << "Student " << id_number << " removed from the course." << endl;
if (waiting.size() > 0) {
itr = waiting.begin();
enrolled.push_back(*itr);
cout << "Student " << *itr << " added to the course "
<< "from the waiting list." << endl;
erase_from_list(itr,waiting);
cout << waiting.size() << " students remain on the waiting list." << endl;
} else {
cout << enrolled.size() << " students are now in the course." << endl;
}
} else {
// If not, check to see if the student is on the waiting list
found = false;
for (itr = waiting.begin(); itr != waiting.end(); itr++) {
found = (*itr == id_number);
if (found) break;
}
if (found) {
erase_from_list(itr,waiting);
cout << "Student " << id_number << " removed from the waiting list.\n"
<< waiting.size() << " students remain on the waiting list." << endl;
} else {
cout << "Student " << id_number
<< " is in neither the course nor the waiting list" << endl;
}
}
}
// Remove the value at the iterator position from a list of strings. The
// size of the list should be reduced by one when the function is finished.
void erase_from_list(list::iterator itr, list& lst) {
assert (lst.size() > 0);
int old_size = lst.size();
// use list's efficient erase member function
lst.erase(itr);
assert (lst.size() == old_size - 1);
}