#include <iostream>
#include <string>
#include <fstream>
#include <limits>
using namespace std;
// Forward declarations
struct Course;
struct Student;
// Node for Course linked list
struct CourseNode {
Course* course;
CourseNode* next;
};
// Node for Student linked list
struct StudentNode {
Student* student;
StudentNode* next;
};
// Node for Student's registered courses linked list
struct StudentCourseNode {
Course* course;
StudentCourseNode* next;
};
// Course structure
struct Course {
string courseID;
string title;
int creditHour;
int maxCapacity;
int enrolledCount;
string prerequisite; // New field for prerequisite course ID
StudentNode* enrolledStudents;
};
struct CompletedCourseNode {
Course* course;
CompletedCourseNode* next;
};
// Student structure
struct Student {
string studentID;
string name;
string email;
float cgpa;
int currentCreditHours;
StudentCourseNode* registeredCourses;
CompletedCourseNode* completedCourses; // New field
};
// Global lists
const float CGPA_THRESHOLD_1 = 2.0;
const float CGPA_THRESHOLD_2 = 2.5;
const float CGPA_THRESHOLD_3 = 3.0;
const float CGPA_THRESHOLD_4 = 3.5;
const int MAX_CREDITS_LOW = 9;
const int MAX_CREDITS_MEDIUM = 12;
const int MAX_CREDITS_HIGH = 15;
const int MAX_CREDITS_TOP = 18;
CourseNode* allCourses = nullptr;
StudentNode* allStudents = nullptr;
// File names
const string COURSES_FILE = "courses.txt";
const string STUDENTS_FILE = "students.txt";
const string REGISTRATIONS_FILE = "registrations.txt";
// Function prototypes
void adminMenu();
void studentMenu(Student* student);
void addNewCourse();
void updateCourse();
void dropCourse();
void registerNewStudent();
void dropStudentFromCourse();
void studentLogin();
void registerForCourse(Student* student);
void dropStudentCourse(Student* student);
void viewRegisteredCourses(Student* student);
void listAllStudentsWithCourses();
void listAllCoursesWithEnrollment();
void listStudentsInCourse();
Course* findCourse(const string& courseID);
Student* findStudent(const string& studentID);
bool isStudentRegistered(Student* student, Course* course);
void enrollStudentInCourse(Student* student, Course* course);
void unenrollStudentFromCourse(Student* student, Course* course);
void printAllCourses();
int getRemainingCredits(Student* student);
int getMaxAllowedCredits(float cgpa);
// File handling functions
void saveData();
void loadData();
void saveCourses();
void loadCourses();
void saveStudents();
void loadStudents();
void saveRegistrations();
void loadRegistrations();
int main() {
// Load data from files at startup
loadData();
while (true) {
cout << "\nUniversity Course Registration System\n";
cout << "1. Admin Login\n";
cout << "2. Student Login\n";
cout << "3. Exit\n";
cout << "Enter your choice: ";
int choice;
cin >> choice;
cin.ignore(); // Clear newline character
switch (choice) {
case 1:
adminMenu();
break;
case 2:
studentLogin();
break;
case 3:
cout << "Exiting system. Goodbye!\n";
saveData(); // Save data before exiting
return 0;
default:
cout << "Invalid choice. Please try again.\n";
}
}
}
void saveData() {
saveCourses();
saveStudents();
saveRegistrations();
cout << "All data saved successfully.\n";
}
void loadData() {
loadCourses();
loadStudents();
loadRegistrations();
cout << "All data loaded successfully.\n";
}
void saveCourses() {
ofstream outFile(COURSES_FILE);
if (!outFile) {
cerr << "Error opening courses file for writing.\n";
return;
}
CourseNode* current = allCourses;
while (current != nullptr) {
outFile << current->course->courseID << "\n"
<< current->course->title << "\n"
<< current->course->creditHour << "\n"
<< current->course->maxCapacity << "\n"
<< current->course->enrolledCount << "\n"
<< current->course->prerequisite << "\n"; // Add this line
current = current->next;
}
outFile.close();
}
void loadCourses() {
ifstream inFile(COURSES_FILE);
if (!inFile) {
// File doesn't exist yet, that's okay
return;
}
while (true) {
Course* newCourse = new Course();
if (!getline(inFile, newCourse->courseID)) break;
getline(inFile, newCourse->title);
inFile >> newCourse->creditHour;
inFile >> newCourse->maxCapacity;
inFile >> newCourse->enrolledCount;
inFile.ignore(); // skip newline after numbers
getline(inFile, newCourse->prerequisite); // Add this line
newCourse->enrolledStudents = nullptr;
// Add to global course list
CourseNode* newNode = new CourseNode();
newNode->course = newCourse;
newNode->next = allCourses;
allCourses = newNode;
}
inFile.close();
}
void saveStudents() {
ofstream outFile(STUDENTS_FILE);
if (!outFile) {
cerr << "Error opening students file for writing.\n";
return;
}
StudentNode* current = allStudents;
while (current != nullptr) {
outFile << current->student->studentID << "\n"
<< current->student->name << "\n"
<< current->student->email << "\n"
<< current->student->cgpa << "\n"
<< current->student->currentCreditHours << "\n";
current = current->next;
}
outFile.close();
}
void loadStudents() {
ifstream inFile(STUDENTS_FILE);
if (!inFile) {
// File doesn't exist yet, that's okay
return;
}
while (true) {
Student* newStudent = new Student();
if (!getline(inFile, newStudent->studentID)) break;
getline(inFile, newStudent->name);
getline(inFile, newStudent->email);
inFile >> newStudent->cgpa;
inFile >> newStudent->currentCreditHours;
inFile.ignore(); // skip newline after numbers
newStudent->registeredCourses = nullptr;
// Add to global student list
StudentNode* newNode = new StudentNode();
newNode->student = newStudent;
newNode->next = allStudents;
allStudents = newNode;
}
inFile.close();
}
void saveRegistrations() {
ofstream outFile(REGISTRATIONS_FILE);
if (!outFile) {
cerr << "Error opening registrations file for writing.\n";
return;
}
StudentNode* currentStudent = allStudents;
while (currentStudent != nullptr) {
StudentCourseNode* currentCourse = currentStudent->student-
>registeredCourses;
while (currentCourse != nullptr) {
outFile << currentStudent->student->studentID << "\n"
<< currentCourse->course->courseID << "\n";
currentCourse = currentCourse->next;
}
currentStudent = currentStudent->next;
}
outFile.close();
}
void loadRegistrations() {
ifstream inFile(REGISTRATIONS_FILE);
if (!inFile) {
// File doesn't exist yet, that's okay
return;
}
while (true) {
string studentID, courseID;
if (!getline(inFile, studentID)) break;
getline(inFile, courseID);
Student* student = findStudent(studentID);
Course* course = findCourse(courseID);
if (student && course) {
enrollStudentInCourse(student, course);
}
}
inFile.close();
}
void adminMenu() {
string password;
cout << "Enter admin password: ";
getline(cin, password);
if (password != "admin123") { // Simple password for demo
cout << "Invalid password!\n";
return;
}
while (true) {
cout << "\nAdmin Menu\n";
cout << "1. Register a New Student\n";
cout << "2. Add a New Course\n";
cout << "3. Update an Existing Course\n";
cout << "4. Drop an Existing Course\n";
cout << "5. Drop a Student from a Course\n\n";
cout << "6. List all Students with Registered Courses\n";
cout << "7. List all Courses with Enrollment Count\n";
cout << "8. List Students in a Particular Course\n";
cout << "9. View All Courses\n";
cout << "10. Save Data to Files\n";
cout << "11. Return to Main Menu\n";
cout << "Enter your choice: ";
int choice;
cin >> choice;
cin.ignore();
switch (choice) {
case 1:
registerNewStudent();
break;
case 2:
addNewCourse();
break;
case 3:
updateCourse();
break;
case 4:
dropCourse();
break;
case 5:
dropStudentFromCourse();
break;
case 6:
listAllStudentsWithCourses();
break;
case 7:
listAllCoursesWithEnrollment();
break;
case 8:
listStudentsInCourse();
break;
case 9:
printAllCourses();
break;
case 10:
saveData();
break;
case 11:
return;
default:
cout << "Invalid choice. Please try again.\n";
}
}
}
void studentMenu(Student* student) {
while (true) {
int maxAllowed = getMaxAllowedCredits(student->cgpa);
int remaining = getRemainingCredits(student);
cout << "\n=============================================\n";
cout << " Student Menu (" << student->name << ")\n";
cout << " CGPA: " << student->cgpa << " | ";
cout << "Credits: " << student->currentCreditHours << "/" << maxAllowed;
cout << " (" << remaining << " remaining)\n";
cout << "=============================================\n";
cout << "1. Register for a Course\n";
cout << "2. Drop a Course\n";
cout << "3. View Registered Courses\n";
cout << "4. Return to Main Menu\n";
cout << "Enter your choice: ";
int choice;
cin >> choice;
cin.ignore();
switch (choice) {
case 1:
registerForCourse(student);
break;
case 2:
dropStudentCourse(student);
break;
case 3:
viewRegisteredCourses(student);
break;
case 4:
return;
default:
cout << "Invalid choice. Please try again.\n";
}
}
}
void addNewCourse() {
Course* newCourse = new Course();
cout << "Enter Course ID (e.g., CSE101): ";
getline(cin, newCourse->courseID);
// Check if course already exists
if (findCourse(newCourse->courseID) != nullptr) {
cout << "Course with this ID already exists!\n";
delete newCourse;
return;
}
cout << "Enter Course Title: ";
getline(cin, newCourse->title);
cout << "Enter Credit Hours: ";
cin >> newCourse->creditHour;
cout << "Enter Maximum Capacity: ";
cin >> newCourse->maxCapacity;
cin.ignore(); // Clear newline
cout << "Enter Prerequisite Course ID (leave empty if none): ";
getline(cin, newCourse->prerequisite);
// Validate prerequisite exists if specified
if (!newCourse->prerequisite.empty() && findCourse(newCourse->prerequisite) ==
nullptr) {
cout << "Prerequisite course not found! Course not added.\n";
delete newCourse;
return;
}
newCourse->enrolledCount = 0;
newCourse->enrolledStudents = nullptr;
// Add to global course list
CourseNode* newNode = new CourseNode();
newNode->course = newCourse;
newNode->next = allCourses;
allCourses = newNode;
cout << "Course added successfully!\n";
}
int getRemainingCredits(Student* student) {
int maxAllowed = getMaxAllowedCredits(student->cgpa);
return maxAllowed - student->currentCreditHours;
}
void updateCourse() {
string courseID;
cout << "Enter Course ID to update: ";
getline(cin, courseID);
Course* course = findCourse(courseID);
if (course == nullptr) {
cout << "Course not found!\n";
return;
}
cout << "Current Course Title: " << course->title << "\n";
cout << "Enter new Title (leave blank to keep current): ";
string newTitle;
getline(cin, newTitle);
if (!newTitle.empty()) {
course->title = newTitle;
}
cout << "Current Credit Hours: " << course->creditHour << "\n";
cout << "Enter new Credit Hours (enter 0 to keep current): ";
int newCredit;
cin >> newCredit;
cin.ignore();
if (newCredit > 0) {
course->creditHour = newCredit;
}
cout << "Current Maximum Capacity: " << course->maxCapacity << "\n";
cout << "Enter new Maximum Capacity (enter 0 to keep current): ";
int newCapacity;
cin >> newCapacity;
cin.ignore();
if (newCapacity > 0) {
// Ensure new capacity isn't less than currently enrolled students
if (newCapacity >= course->enrolledCount) {
course->maxCapacity = newCapacity;
} else {
cout << "Cannot set capacity below current enrollment (" << course-
>enrolledCount << " students).\n";
}
}
cout << "Current Prerequisite: " << (course->prerequisite.empty() ? "None" :
course->prerequisite) << "\n";
cout << "Enter new Prerequisite Course ID (leave blank to keep current, 'none'
to remove): ";
string newPrereq;
getline(cin, newPrereq);
if (newPrereq == "none") {
course->prerequisite = "";
} else if (!newPrereq.empty()) {
if (findCourse(newPrereq)) {
course->prerequisite = newPrereq;
} else {
cout << "Prerequisite course not found! Prerequisite not updated.\n";
}
}
cout << "Course updated successfully!\n";
}
void dropCourse() {
string courseID;
cout << "Enter Course ID to drop: ";
getline(cin, courseID);
CourseNode* prev = nullptr;
CourseNode* current = allCourses;
while (current != nullptr) {
if (current->course->courseID == courseID) {
// First, unenroll all students from this course
StudentNode* studentNode = current->course->enrolledStudents;
while (studentNode != nullptr) {
Student* student = studentNode->student;
// Remove from student's registered courses
StudentCourseNode* scPrev = nullptr;
StudentCourseNode* scCurrent = student->registeredCourses;
while (scCurrent != nullptr) {
if (scCurrent->course->courseID == courseID) {
if (scPrev == nullptr) {
student->registeredCourses = scCurrent->next;
} else {
scPrev->next = scCurrent->next;
}
delete scCurrent;
break;
}
scPrev = scCurrent;
scCurrent = scCurrent->next;
}
StudentNode* nextStudent = studentNode->next;
delete studentNode;
studentNode = nextStudent;
}
// Remove from global course list
if (prev == nullptr) {
allCourses = current->next;
} else {
prev->next = current->next;
}
delete current->course;
delete current;
cout << "Course dropped successfully!\n";
return;
}
prev = current;
current = current->next;
}
cout << "Course not found!\n";
}
void registerNewStudent() {
Student* newStudent = new Student();
cout << "Enter Student ID: ";
getline(cin, newStudent->studentID);
// Check if student already exists
if (findStudent(newStudent->studentID) != nullptr) {
cout << "Student with this ID already exists!\n";
delete newStudent;
return;
}
cout << "Enter Name: ";
getline(cin, newStudent->name);
cout << "Enter Email: ";
getline(cin, newStudent->email);
cout << "Enter CGPA (0.0-4.0): ";
while (!(cin >> newStudent->cgpa) || newStudent->cgpa < 0.0 || newStudent->cgpa
> 4.0) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input! Please enter CGPA between 0.0 and 4.0: ";
}
cin.ignore();
newStudent->currentCreditHours = 0;
newStudent->registeredCourses = nullptr;
newStudent->completedCourses = nullptr; // Initialize completed courses list
// Optionally ask for completed courses during registration
char choice;
cout << "Does the student have any completed courses? (y/n): ";
cin >> choice;
cin.ignore();
if (tolower(choice) == 'y') {
while (true) {
string courseID;
cout << "Enter completed course ID (or 'done' to finish): ";
getline(cin, courseID);
if (courseID == "done") break;
// Find the course in the system
Course* completedCourse = findCourse(courseID);
if (completedCourse) {
// Add to completed courses list
CompletedCourseNode* newCompleted = new CompletedCourseNode();
newCompleted->course = completedCourse;
newCompleted->next = newStudent->completedCourses;
newStudent->completedCourses = newCompleted;
cout << "Added " << courseID << " to completed courses.\n";
} else {
cout << "Course not found! Skipping...\n";
}
}
}
// Add student to the system
StudentNode* newNode = new StudentNode();
newNode->student = newStudent;
newNode->next = allStudents;
allStudents = newNode;
cout << "Student registered successfully!\n";
}
void dropStudentFromCourse() {
string studentID, courseID;
cout << "Enter Student ID: ";
getline(cin, studentID);
Student* student = findStudent(studentID);
if (student == nullptr) {
cout << "Student not found!\n";
return;
}
// Show student info including CGPA
cout << "\nStudent Info:\n";
cout << "ID: " << student->studentID << "\n";
cout << "Name: " << student->name << "\n";
cout << "CGPA: " << student->cgpa << "\n";
cout << "Current Credits: " << student->currentCreditHours << "\n\n";
cout << "Enter Course ID: ";
getline(cin, courseID);
Course* course = findCourse(courseID);
if (course == nullptr) {
cout << "Course not found!\n";
return;
}
if (!isStudentRegistered(student, course)) {
cout << "Student is not registered in this course!\n";
return;
}
unenrollStudentFromCourse(student, course);
cout << "Student dropped from course successfully!\n";
}
void studentLogin() {
string studentID;
cout << "Enter Student ID: ";
getline(cin, studentID);
Student* student = findStudent(studentID);
if (student == nullptr) {
cout << "Student not found!\n";
return;
}
studentMenu(student);
}
void registerForCourse(Student* student) {
string courseID;
cout << "Enter Course ID to register: ";
getline(cin, courseID);
Course* course = findCourse(courseID);
if (course == nullptr) {
cout << "Course not found!\n";
return;
}
// Enhanced prerequisite checking with completed courses
if (!course->prerequisite.empty()) {
bool hasPrerequisite = false;
string whereFound = "";
// 1. First check completed courses
CompletedCourseNode* completedNode = student->completedCourses;
while (completedNode != nullptr) {
if (completedNode->course->courseID == course->prerequisite) {
hasPrerequisite = true;
whereFound = "completed courses";
break;
}
completedNode = completedNode->next;
}
// 2. If not found in completed, check currently registered courses
if (!hasPrerequisite) {
StudentCourseNode* current = student->registeredCourses;
while (current != nullptr) {
if (current->course->courseID == course->prerequisite) {
hasPrerequisite = true;
whereFound = "currently registered courses";
break;
}
current = current->next;
}
}
if (!hasPrerequisite) {
Course* prereqCourse = findCourse(course->prerequisite);
string prereqTitle = prereqCourse ? prereqCourse->title : "Unknown
Course";
cout << "\n=== PREREQUISITE REQUIREMENT NOT MET ===\n";
cout << "Course: " << course->title << " (" << course->courseID << ")\
n";
cout << "Requires: " << course->prerequisite << " (" << prereqTitle <<
")\n\n";
// Check if prerequisite exists in system
if (!prereqCourse) {
cout << "Warning: The prerequisite course doesn't exist in the
system!\n";
}
// Suggest action plan
cout << "Action Required:\n";
cout << "1. Complete " << course->prerequisite << " first\n";
// Check if prerequisite is offered
CourseNode* curr = allCourses;
bool prereqOffered = false;
while (curr) {
if (curr->course->courseID == course->prerequisite) {
prereqOffered = true;
break;
}
curr = curr->next;
}
if (prereqOffered) {
cout << "2. Register for " << course->prerequisite << " in the
current semester\n";
} else {
cout << "2. " << course->prerequisite << " is not currently
offered\n";
}
return;
} else {
cout << "Prerequisite satisfied (" << course->prerequisite << " found
in " << whereFound << ")\n";
}
}
// Existing validation checks (credit hours, capacity, etc.)
if (course->creditHour <= 0) {
cout << "Invalid course credit hours!\n";
return;
}
if (isStudentRegistered(student, course)) {
cout << "You are already registered in this course!\n";
return;
}
if (course->enrolledCount >= course->maxCapacity) {
cout << "Course is at maximum capacity!\n";
return;
}
// Credit limit check
int maxAllowed = getMaxAllowedCredits(student->cgpa);
int remaining = getRemainingCredits(student);
if (student->currentCreditHours + course->creditHour > maxAllowed) {
cout << "\n=== CREDIT LIMIT WARNING ===\n";
cout << "Cannot register for this course. You would exceed your maximum
allowed credit hours.\n";
cout << "Your CGPA: " << student->cgpa << " (Max Credits: " << maxAllowed
<< ")\n";
cout << "Current Credits: " << student->currentCreditHours << endl;
cout << "Course Credits: " << course->creditHour << endl;
cout << "Remaining Available Credits: " << remaining << endl;
if (remaining > 0) {
cout << "\nAlternative courses within your credit limit:\n";
CourseNode* current = allCourses;
while (current != nullptr) {
if (!isStudentRegistered(student, current->course) &&
current->course->creditHour <= remaining &&
current->course->enrolledCount < current->course->maxCapacity)
{
cout << "- " << current->course->courseID << ": "
<< current->course->title << " ("
<< current->course->creditHour << " credits)\n";
}
current = current->next;
}
}
return;
}
// Final registration
enrollStudentInCourse(student, course);
student->currentCreditHours += course->creditHour;
cout << "\n=== REGISTRATION SUCCESSFUL ===\n";
cout << "Course: " << course->title << " (" << course->courseID << ")\n";
cout << "Credits: " << course->creditHour << " (Total: "
<< student->currentCreditHours << "/" << maxAllowed << ")\n";
}
void dropStudentCourse(Student* student) {
string courseID;
cout << "Enter Course ID to drop: ";
getline(cin, courseID);
Course* course = findCourse(courseID);
if (course == nullptr) {
cout << "Course not found!\n";
return;
}
if (!isStudentRegistered(student, course)) {
cout << "You are not registered in this course!\n";
return;
}
// Remove this line since unenrollStudentFromCourse already handles it:
// student->currentCreditHours -= course->creditHour;
unenrollStudentFromCourse(student, course);
int maxAllowed = getMaxAllowedCredits(student->cgpa);
cout << "Successfully dropped " << course->title << " (" << course->creditHour
<< " credits)!\n";
cout << "New credit status: " << student->currentCreditHours << "/" <<
maxAllowed << " credits\n";
}
void viewRegisteredCourses(Student* student) {
int maxAllowed = getMaxAllowedCredits(student->cgpa);
int remaining = getRemainingCredits(student);
cout << "\n=== Your Course Registration Status ===\n";
cout << "CGPA: " << student->cgpa << endl;
cout << "Maximum Allowed Credits: " << maxAllowed << endl;
cout << "Currently Registered Credits: " << student->currentCreditHours <<
endl;
cout << "Remaining Available Credits: " << remaining << endl;
cout << "----------------------------------------\n";
if (student->registeredCourses == nullptr) {
cout << "You are not registered in any courses.\n";
return;
}
cout << "Your Registered Courses:\n";
cout << "ID\tTitle\t\t\tCredit Hours\n";
cout << "----------------------------------------\n";
StudentCourseNode* current = student->registeredCourses;
while (current != nullptr) {
cout << current->course->courseID << "\t"
<< current->course->title << "\t\t"
<< current->course->creditHour << "\n";
current = current->next;
}
cout << "\nCredit Summary:\n";
cout << "You can register for " << remaining << " more credits this semester.\
n";
if (remaining < 3) {
cout << "Note: Most courses are 3 credits, so you may not be able to
register for additional courses.\n";
}
}
void listAllStudentsWithCourses() {
if (allStudents == nullptr) {
cout << "No students registered in the system.\n";
return;
}
cout << "All Students with Registered Courses:\n";
cout << "====================================================================\
n";
StudentNode* currentStudent = allStudents;
while (currentStudent != nullptr) {
Student* student = currentStudent->student;
cout << "Student ID: " << student->studentID << "\n";
cout << "Name: " << student->name << "\n";
cout << "Email: " << student->email << "\n";
cout << "CGPA: " << student->cgpa << "\n"; // Added CGPA display
cout << "Current Credit Hours: " << student->currentCreditHours << "\
n"; // Added credit hours
if (student->registeredCourses == nullptr) {
cout << "No registered courses.\n";
} else {
cout << "Registered Courses:\n";
StudentCourseNode* currentCourse = student->registeredCourses;
while (currentCourse != nullptr) {
cout << " - " << currentCourse->course->courseID << ": "
<< currentCourse->course->title << " ("
<< currentCourse->course->creditHour << " credits)\n";
currentCourse = currentCourse->next;
}
}
cout <<
"--------------------------------------------------------------------\n";
currentStudent = currentStudent->next;
}
}
void listAllCoursesWithEnrollment() {
if (allCourses == nullptr) {
cout << "No courses available in the system.\n";
return;
}
cout << "All Courses with Enrollment Information:\n";
cout << "====================================================================\
n";
cout << "ID\tTitle\t\t\tCredit\tEnrolled/Max\n";
cout << "--------------------------------------------------------------------\
n";
CourseNode* current = allCourses;
while (current != nullptr) {
Course* course = current->course;
cout << course->courseID << "\t"
<< course->title << "\t\t"
<< course->creditHour << "\t"
<< course->enrolledCount << "/" << course->maxCapacity << "\n";
current = current->next;
}
}
void listStudentsInCourse() {
string courseID;
cout << "Enter Course ID: ";
getline(cin, courseID);
Course* course = findCourse(courseID);
if (course == nullptr) {
cout << "Course not found!\n";
return;
}
cout << "Students enrolled in " << course->title << " (" << course->courseID <<
"):\n";
cout << "----------------------------------------------------------------\n";
cout << "ID\tName\t\tCGPA\tCredits\n"; // Added header with CGPA
cout << "----------------------------------------------------------------\n";
if (course->enrolledStudents == nullptr) {
cout << "No students enrolled in this course.\n";
return;
}
StudentNode* current = course->enrolledStudents;
while (current != nullptr) {
cout << current->student->studentID << "\t"
<< current->student->name << "\t"
<< current->student->cgpa << "\t"
<< current->student->currentCreditHours << "\n";
current = current->next;
}
}
void printAllCourses() {
if (allCourses == nullptr) {
cout << "No courses available in the system.\n";
return;
}
cout << "All Available Courses:\n";
cout << "====================================================================\
n";
cout << "ID\tTitle\t\t\tCredit\tPrereq\tEnrolled/Max\n";
cout << "--------------------------------------------------------------------\
n";
CourseNode* current = allCourses;
while (current != nullptr) {
Course* course = current->course;
cout << course->courseID << "\t"
<< course->title << "\t\t"
<< course->creditHour << "\t"
<< (course->prerequisite.empty() ? "None" : course->prerequisite) <<
"\t"
<< course->enrolledCount << "/" << course->maxCapacity << "\n";
current = current->next;
}
}
// Helper functions
Course* findCourse(const string& courseID) {
CourseNode* current = allCourses;
while (current != nullptr) {
if (current->course->courseID == courseID) {
return current->course;
}
current = current->next;
}
return nullptr;
}
Student* findStudent(const string& studentID) {
StudentNode* current = allStudents;
while (current != nullptr) {
if (current->student->studentID == studentID) {
return current->student;
}
current = current->next;
}
return nullptr;
}
bool isStudentRegistered(Student* student, Course* course) {
StudentCourseNode* current = student->registeredCourses;
while (current != nullptr) {
if (current->course->courseID == course->courseID) {
return true;
}
current = current->next;
}
return false;
}
void enrollStudentInCourse(Student* student, Course* course) {
// Add to student's registered courses
StudentCourseNode* newSCNode = new StudentCourseNode();
newSCNode->course = course;
newSCNode->next = student->registeredCourses;
student->registeredCourses = newSCNode;
// Add to course's enrolled students
StudentNode* newSNode = new StudentNode();
newSNode->student = student;
newSNode->next = course->enrolledStudents;
course->enrolledStudents = newSNode;
course->enrolledCount++;
}
void unenrollStudentFromCourse(Student* student, Course* course) {
// Remove from student's registered courses
StudentCourseNode* scPrev = nullptr;
StudentCourseNode* scCurrent = student->registeredCourses;
while (scCurrent != nullptr) {
if (scCurrent->course->courseID == course->courseID) {
if (scPrev == nullptr) {
student->registeredCourses = scCurrent->next;
} else {
scPrev->next = scCurrent->next;
}
student->currentCreditHours -= course->creditHour; // Added this line
delete scCurrent;
break;
}
scPrev = scCurrent;
scCurrent = scCurrent->next;
}
// Remove from course's enrolled students
StudentNode* sPrev = nullptr;
StudentNode* sCurrent = course->enrolledStudents;
while (sCurrent != nullptr) {
if (sCurrent->student->studentID == student->studentID) {
if (sPrev == nullptr) {
course->enrolledStudents = sCurrent->next;
} else {
sPrev->next = sCurrent->next;
}
delete sCurrent;
break;
}
sPrev = sCurrent;
sCurrent = sCurrent->next;
}
course->enrolledCount--;
}
int getMaxAllowedCredits(float cgpa) {
if (cgpa < CGPA_THRESHOLD_1) return MAX_CREDITS_LOW;
if (cgpa < CGPA_THRESHOLD_2) return MAX_CREDITS_MEDIUM;
if (cgpa < CGPA_THRESHOLD_4) return MAX_CREDITS_HIGH;
return MAX_CREDITS_TOP;
}