240 likes | 252 Views
Build a program to compute Dean’s List for full-time students with GPA ≥ 3.0. Read student data file and output qualifying students.
E N D
Practice Building Classes Modeling Objects
Problem Write a program that computes the Dean’s List (full-time students whose GPA ³ 3.0), using a student data file. Each student-record in the file consists of four lines: 12345 Jane Doe 3.35 14 representing student Jane Doe, with student id 12345, with GPA 3.35 and 14 credit hrs this semester.
Behavior Our program should prompt for and read the name of the data file from the user. It should then open an ifstream to that file. It should then prompt for and read the name of an output file and open an ofstream to that file. Using an input loop, our program should read in the sequence of students. It should then process this sequence by printing to the ofstream each full-time student whose GPA is 3.0 or greater.
Objects Description Type Kind Name in-file name string varying inFileName out-file name string varying outFileName input fstream ifstream varying fin output fstream ofstream varying fout students vector<Student> varying students GPA double varying students[i].GPA()
Operations display a string yes string << Description Predefined? Library? Name read a string yes string >> open/close fstreams yes fstream -- read students in an ?? -- for, if input loop break identify Deans List ?? -- for, if students [], ?? output a student ?? -- ??
Algorithm 0. Display purpose of program 1. Prompt for and read name of input file from cin into inFileName. 2. Open fin to inFileName, fout to outFileName, verify opens. 3. Read sequence of students from fin into students, using an input loop. 4. Close fin. 5. Prompt for and read name of output file from cin into outFileName. 6. Write students qualifying for the Dean’s List to fout. 7. Close fout. 8. Display a ‘processing completed’ message via cout.
OCD with Classes 0. Specify the behavior of the program. 1. Identify the objects in the behavior. 1a. If an object cannot be modeled with available types, declare a class by which such objects can be modeled. 2. Identify the operations in the behavior. 2a. If an operation is not predefined, build a function to perform that operation. 2b. If the left operand of an operation is a class object, make the operation a function member of the class. 3. Organize your objects and operations into an algorithm.
A Student Class Begin by defining variables to store the attributes of the object being represented (a student) in a class header file (e.g., Student.h): int myID; string myName; double myGPA; int myCredits; Clearly, it would be easy to add other data members (academic year, address, ...) as necessary.
Building Classes class Student { public: private: int myID; string myName; double myGPA; int myCredits; }; We then wrap these variables in a class declaration:
Prototypes Student(); Student(int id, const string & Name, double gpa, int credits); int ID() const; string Name() const; double GPA() const; int Credits() const; friend istream & operator>>(istream & in, Student & stu); friend ostream & operator<<(ostream & in, const Student & stu); class Student { public: private: // ... data members omitted };
Operation: Default Constructor The default constructor initializes the data members to default values: Student aStudent; Specification: Postcondition: myid == 0 && myName == “” && myGPA == 0.0 && myCredits == 0.
Default Constructor This is sufficiently simple to define inline in Student.h: inline Student::Student() { myID = 0; myName = “”; myGPA = 0.0; myCredits = 0; }
Operation:Explicit-Value Constructor This constructor lets you initialize the data members to specified values: Specification: Receive: id, an int; name, a string; gpa, a double, and credits, an int. Precondition: id is a valid id, gpa is a valid gpa, and credits is a valid number of credits. Postcondition: myid == id && myName == name && myGPA == gpa && myCredits == credits. Student aStudent(12345, “Jane Doe”, 3.35, 14);
Explicit-Value Constructor This is sufficiently complicated to define in Student.cpp: // ... #include “Student.h” Student::Student(int id, const string & name, double gpa, int credits) { assert(id > 0 && gpa >= 0.0 && gpa <= 4.0 && credits > 0 && credits < 21); myID = id; myName = name; myGPA = gpa; myCredits = credits; }
Operation: Extractors The extractors retrieve data member values: cout << aStudent.ID() << aStudent.Name() << aStudent.GPA() << aStudent.Credits(); Specifications: ID: Return myID. Name: Return myName. GPA: Return myGPA. Credits: Return myCredits.
Default Constructor These are sufficiently simple to define inline in Student.h: inline int Student::ID() const { return myID; } inline string Student::Name() const { return myName; } inline string Student::GPA() const { return myGPA; } inline string Student::Credits() const { return myCredits; }
Operation:Input The input operator lets you read Student values: cin >> aStudent; Specification: Receive: in, an istream; stu, a Student. Precondition: in contains a valid Student value. Input: the Student value from in. Passback: in, the Student value extracted from it; stu, containing the extracted value. Return: in, for chaining.
Input Operator This is sufficiently complicated to define in Student.cpp. Its form is dictated by the record-format in the data file: // ... istream & operator>>(istream & in, Student & stu) { in >> stu.myID; // read id on one line char ch; in.get(ch); // eat the newline getline(in, stu.myName); // read name (2 words) in >> stu.myGPA // read GPA >> stu.myCredits; // read credits assert(in.good()); // weak precondition check return in; // allow chaining }
Operation:Output The output operator lets you write Student values: cout << aStudent << endl; Specification: Receive: out, an ostream; stu, a Student. Output: stu’s Student value, via out. Passback: out, with the Student value inserted into it. Return: out, for chaining.
Output Operator This is sufficiently complicated to define in Student.cpp. We will use a format consistent with that in the data file: // ... ostream & operator<<(ostream & out, const Student & stu) { out << stu.myID << ‘\n’ // put id on one line << stu.myName << ‘\n’ // put name << stu.myGPA << ‘ ‘ // put GPA << stu.myCredits; // put credits return out; // allow chaining }
Coding Our Algorithm // deansList.cpp // ... documentation // ... other #includes #include “Student.h” int main() { cout << “\nTo generate the Dean’s List,” << “\n enter the input file name: “; string inFileName; cin >> inFileName; ifstream fin(inFileName.data()); assert(fin.is_open()); We are now ready to implement our algorithm...
Coding (Ct’d) // ... deansList.cpp continued Student aStudent; vector<Student> students; for (;;) { fin >> aStudent; if (fin.eof()) break; students.push_back(aStudent); } fin.close(); // ...
Coding (Ct’d) // ... deansList.cpp continued cout << “\nEnter the output file name: “; string outFileName; cin >> outFileName; ofstream fout(outFileName.data()); assert(fout.is_open()); for (unsigned i = 0; i < students.size(); i++) if (students[i].GPA() >= 3.0 && students[i].Credits() >= 12) fout << students[i] << “\n\n”; fout.close(); cout << “\nProcessing complete. Results are in “ << outFileName << endl; }
Summary C++ classes allow “real world” objects to be modeled in software. Classes are objects, and can be stored in containers, such as the STL vector. Most classes require at least: • a default-value constructor • an explicit-value constructor • extractor functions • I/O functions