#include "stdstuff.h" const int GRADESIZE = 4, NAMESIZE = 40, MAXCOURSES = 60; struct courseItem { int number; // of course char grade [GRADESIZE]; // "CUR", "ABS", "FND", "F" or one of // "D-", "D", "D+", and so on }; struct studentItem { int number; // of student char name[NAMESIZE]; // of student int actualCourses; // for this student courseItem courses[MAXCOURSES]; }; // Returns true if "grade" is one of "D-", "D", "D+", and so on. // Returns false otherwise. bool isPassingGrade (char grade[]) { static char table [][GRADESIZE] = { "D-", "D", "D+", "C-", "C", "C+", "B-", "B", "B+", "A-", "A", "A+" }; for (int i = 0; i < 12; i++) { if (stricmp(grade, table[i]) == 0) return true; } return false; } // Returns true if "grade" is "CUR" and false otherwise bool isCurrent (char grade[]) { return (stricmp (grade, "CUR") == 0); } // Returns true if grade is valid (one of "CUR", "ABS", "FND", "F", "D-", etc.) // and false otherwie. bool isValidGrade (char grade[]) { return ( isCurrent (grade) || (stricmp (grade, "ABS") == 0) || (stricmp (grade, "FND") == 0) || (stricmp (grade, "F") == 0) || isPassingGrade (grade) ); } // Reads student information from a file and stores it into an array of // "studentItem" structures. Sets "actualStudents" to the actual number // of students in the file. Returns true if entirely successful and // false otherwise. bool readInData (studentItem database[], int MAXSTUDENTS, int &actualStudents) { const int FILENAMESIZE = 60; char filename [FILENAMESIZE]; ifstream fin; int studentNumber, i; cout << "Enter filename for data file: "; cin >> setw(FILENAMESIZE) >> filename; fin.open (filename); if (fin.fail()) { cout << "Unable to open file <" << filename << ">.\n"; return false; } actualStudents = 0; // none so far for (;;) { fin >> studentNumber; if (fin.fail()) { if (fin.eof()) { return true; // normal end of reads } else { cout << "Error in reading data file (after data for " << actualStudents << " students successfully read.\n"; return false; } } if (actualStudents == MAXSTUDENTS) { cout << "Insufficient space for student data.\n"; return false; } database[actualStudents].number = studentNumber; fin >> ws; // skip whitespace after number fin.getline (database[actualStudents].name, NAMESIZE); database[actualStudents].actualCourses = 0; while (fin.peek() == '-') { i = database[actualStudents].actualCourses++; if (i == MAXCOURSES) { cout << "Student has too many courses.\n"; return false; } fin.get(); // dispose of the '-' fin >> database[actualStudents].courses[i].number >> setw(GRADESIZE) >> database[actualStudents].courses[i].grade; if (fin.fail()) { cout << "Error in reading data file (after data for " << actualStudents << " students successfully read.\n"; return false; } fin.ignore (INT_MAX, '\n'); // discard rest of line if (!isValidGrade (database[actualStudents].courses[i].grade)) { cout << "Invalid grade (" << database[actualStudents].courses[i].grade << ") encountered.\n"; return false; } } actualStudents++; } } // Returns true if the student is taking the course or has ever taken it. // Returns false otherwise. If true is returned, the student's grade in // the course is "returned" via call by reference parameter "grade". bool courseSearch (const studentItem &studentData, int course, char grade[]) { int i; for (i = 0; i < studentData.actualCourses; i++) { if (studentData.courses[i].number == course){ strcpy (grade, studentData.courses[i].grade); return true; } } return false; } // Returns false if the student is taking course "course" and does // not have a passing grade in course "requiredCourse". // Returns true otherwise. bool prerequisitesOK (const studentItem &studentData, int course, int requiredCourse) { char grade[GRADESIZE]; if (!courseSearch (studentData, course, grade) || !isCurrent (grade)) { // student is not currently taking the course return true; } if (!courseSearch (studentData, requiredCourse, grade) || !isPassingGrade (grade) ) { // student has not passed the prerequisite course return false; } return true; // student has passed the required course } // Lists all students who are taking course "course" without having // previously passed course "requiredCourse". void doPrerequisiteCheck (const studentItem database[], int actualStudents, int course, int requiredCourse) { int i, count = 0; cout << "\n"; for (i = 0; i < actualStudents; i++) { if (!prerequisitesOK (database[i], course, requiredCourse)) { cout << database[i].number << " " << database[i].name << "\n"; count++; } } if (count == 0) { cout << "No prerequisite violations found.\n"; } else { cout << count << " prerequisite violations found.\n"; } } int main () { const int MAXSTUDENTS = 500; studentItem database[MAXSTUDENTS]; int actualStudents, course, requiredCourse; if (!readInData (database, MAXSTUDENTS, actualStudents)) { cout << "Unable to read in data.\n"; pause (); return 0; } for (;;) { cout << "\nEnter numbers for course and required course (0 0 to stop): "; cin >> course >> requiredCourse; if ((course == 0) && (requiredCourse == 0)) { pause(); return 0; } doPrerequisiteCheck (database, actualStudents, course, requiredCourse); } }