Summary.
This project is a foundational implementation of a CRUD (Create, Read, Update, Delete) application designed for the Code::Blocks environment. It focuses on managing student records using Object-Oriented principles, ensuring data persistence during the session via dynamic memory or container management.
Learning Objectives:
Encapsulation: Implementing private data members with public getter/setter interfaces.
Object Composition: Managing a collection of objects within a controller class.
Input Validation: Utilizing <limits> to handle stream errors and prevent infinite loops.
Formatted Output: Mastering <iomanip> for professional, tabular console reports.
Memory Safety: Understanding object lifecycles within the scope of a management system.
The Source Code
This code is optimized for the MinGW compiler. Ensure your Code::Blocks project is set to the ISO C++11 standard or higher (Project > Build Options > Compiler Flags).
#include <iostream> #include <vector> #include <string> #include <iomanip> #include <limits>
using namespace std;
// --- Entity Class --- class Student { private: int id; string name; float gpa;
public: Student(int id, string name, float gpa) : id(id), name(name), gpa(gpa) {}
int getId() const { return id; } string getName() const { return name; } float getGpa() const { return gpa; }
void displayRow() const { cout << left << setw(10) << id << setw(25) << name << fixed << setprecision(2) << setw(10) << gpa << endl; } };
// --- Controller Class --- class ManagementSystem { private: vector<Student> database;
void clearBuffer() { cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); }
public: void addStudent() { int id; string name; float gpa;
cout << "\n--- Add New Student ---" << endl; cout << "Enter ID (Integer): "; while (!(cin >> id)) { cout << "Invalid input. Enter a numeric ID: "; clearBuffer(); } clearBuffer(); // Clean buffer before getline cout << "Enter Name: "; getline(cin, name);
cout << "Enter GPA (0.0 - 4.0): "; while (!(cin >> gpa) || gpa < 0 || gpa > 4.0) { cout << "Invalid GPA. Enter a value between 0.0 and 4.0: "; clearBuffer(); }
database.emplace_back(id, name, gpa); cout << "Student record added successfully!\n"; }
void viewAll() const { if (database.empty()) { cout << "\n[!] No records found.\n"; return; }
cout << "\n" << string(45, '-') << endl; cout << left << setw(10) << "ID" << setw(25) << "Name" << setw(10) << "GPA" << endl; cout << string(45, '-') << endl;
for (const auto& s : database) { s.displayRow(); } cout << string(45, '-') << endl; }
void searchById() const { int searchId; cout << "Enter Student ID to search: "; cin >> searchId;
for (const auto& s : database) { if (s.getId() == searchId) { cout << "\nRecord Found:\nName: " << s.getName() << "\nGPA: " << s.getGpa() << endl; return; } } cout << "\n[!] Student ID " << searchId << " not found.\n"; }
void run() { int choice; do { cout << "\n=== STUDENT MANAGEMENT SYSTEM ==="; cout << "\n1. Add Student\n2. View All\n3. Search by ID\n4. Exit"; cout << "\nSelection: "; if (!(cin >> choice)) { cout << "Invalid selection. Please use numbers 1-4.\n"; clearBuffer(); continue; }
switch (choice) { case 1: addStudent(); break; case 2: viewAll(); break; case 3: searchById(); break; case 4: cout << "Exiting system...\n"; break; default: cout << "Choice out of range.\n"; } } while (choice != 4); } };
int main() { ManagementSystem sms; sms.run(); return 0; } |
Execution Trace (Sample Session)
=== STUDENT MANAGEMENT SYSTEM === 1. Add Student 2. View All 3. Search by ID 4. Exit Selection: 1
--- Add New Student --- Enter ID (Integer): 101 Enter Name: Alice Hamilton Enter GPA (0.0 - 4.0): 3.85 Student record added successfully!
=== STUDENT MANAGEMENT SYSTEM === Selection: 2
--------------------------------------------- ID Name GPA --------------------------------------------- 101 Alice Hamilton 3.85 ---------------------------------------------
=== STUDENT MANAGEMENT SYSTEM === Selection: 1
--- Add New Student --- Enter ID (Integer): ABC Invalid input. Enter a numeric ID: 102 Enter Name: Bob Marley Enter GPA (0.0 - 4.0): 9.5 Invalid GPA. Enter a value between 0.0 and 4.0: 3.20 Student record added successfully! |
Academic Learning Corner
1. The cin.clear() and numeric_limits Fix
In Code::Blocks (MinGW), if a user enters a character like 'A' into an int variable, the input stream enters a "fail state." Without cin.clear(), the program will skip all future inputs, creating an infinite loop. Using numeric_limits<streamsize>::max() ensures we purge the entire keyboard buffer so the next getline() doesn't capture leftover newline characters.
2. Formatting with <iomanip>
We use left and setw(n) to create columns. Note that setw only applies to the very next output operation, which is why it must be repeated for every column. fixed and setprecision(2) ensure that even a GPA of 4 is displayed as 4.00, maintaining the professional "Report" look.
3. Encapsulation Logic
The Student class keeps data private. This prevents the ManagementSystem from accidentally modifying a student's ID, which should ideally be immutable once set. We provide "Getters" to access the data for display purposes only.
No comments:
Post a Comment