Exercise 7-2
Extend the program in S4.2.3/64 to assign letter grades by ranges:
A 90-100
B 80-89.99...
C 70-79.99...
D 60-69.99...
F < 60
Solution
The strategy:
- Make a copy of the entire projects from Solution to Exercise 4-0. (i.e. the sample programs in Chapter 4 of the textbook).
- Write a new home-made getLetterGrade function that returns a string letterGrade given an input (numeric) double grade, using if/else condition.
- In the main program, use the getletterGrade function to compute the student’s string letterGrade. Have an associative array letterGradeCount that maps a string (letter grade) to integer (to keep track of letter grade occurrences).
The Program
Here summarises the entire Code::Block Project, including the header and source files.
Source File List
Header File List
Source Files
main.cpp
#include <algorithm>
#include <iomanip>
#include <ios>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
#include <map>
#include "grade.h"
#include "Student_info.h"
#include "getLetterGrade.h"
using std::cin;
using std::cout;
using std::endl;
using std::domain_error;
using std::max;
using std::setprecision;
using std::sort;
using std::streamsize;
using std::string;
using std::vector;
using std::map;
int main()
{
vector<Student_info> students;
Student_info record;
string::size_type maxlen = 0; // the length of the longest name
// read and store all the student's data.
// Invariant: students contain all the student records read so far
// maxlen contains the length of the longest name in students
while (read(cin, record))
{
// find the length of longest name
maxlen = max(maxlen, record.name.size());
students.push_back(record);
}
// alphabetize the student records
sort(students.begin(), students.end(), compare);
// write the names and grades
map<string, int> letterGradeCount; // To store letter grade occurrences.
for (vector<Student_info>::size_type i = 0;
i != students.size(); ++i)
{
//write the name, padded on teh right to maxlen + 1 characters
cout << students[i].name
<< string(maxlen + 1 - students[i].name.size(), ' ');
//compute and write the grade
try
{
double final_grade = grade(students[i]);
string letterGrade = getLetterGrade(final_grade);
letterGradeCount[letterGrade]++; // Count Letter Grades.
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade
<< setprecision(prec) << " (" << letterGrade << ")";
}
catch (domain_error e)
{
cout << e.what();
}
cout << endl;
}
// Display letter grade summary
cout << "\nLetter Grade Summary" << endl;
for (map<string, int>::const_iterator i = letterGradeCount.begin();
i != letterGradeCount.end(); ++i)
cout << i->first << ": " << i->second << endl;
return 0;
}
getletterGrade.cpp
#include <string>
using std::string;
// Convert a numeric grade into a letter grade.
// (For Exercise 7-2)
string getLetterGrade(double grade) {
string ret;
if (grade >= 90.0)
ret = "A";
else if (grade >= 80.0 && grade < 90.0)
ret = "B";
else if (grade >= 70.0 && grade < 80.0)
ret = "C";
else if (grade >= 60.0 && grade < 70.0)
ret = "D";
else
ret = "F";
return ret;
}
grade.cpp
#include <stdexcept>
#include <vector>
#include "grade.h"
#include "median.h"
#include "Student_info.h"
using std::domain_error;
using std::vector;
// definitions for the grade functions from S4.1/52, S4.1.2/54, S4.2.2/63
// compute a student's overall grade from midterm and final exam
// grades and homework grade (S4.1/52)
double grade(double midterm, double final, double homework)
{
return 0.2 * midterm + 0.4 * final + 0.4 * homework;
}
// compute a student's overall grade from midterm and final exam grades
// and vector of homework grades.
// this function does not copy its argument, because median (function) does it for us.
// (S4.1.2/54)
double grade(double midterm, double final, const vector<double>& hw)
{
if (hw.size() == 0)
throw domain_error("student has done no homework");
return grade(midterm, final, median(hw));
}
// this function computes the final grade for a Student_info object
// (S4.2.2/63)
double grade(const Student_info& s)
{
return grade(s.midterm, s.final, s.homework);
}
// source file for the median function
#include <algorithm>
#include <stdexcept>
#include <vector>
using std::domain_error;
using std::sort;
using std::vector;
// compute the median of a vector<double>
// (S4.1.1/53)
double median(vector<double> vec)
{
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
if (size == 0)
throw domain_error("median of an empty vector");
sort(vec.begin(),vec.end());
vec_sz mid = size/2;
return size % 2 == 0 ? (vec[mid] + vec[mid-1]) / 2 : vec[mid];
}
Student_info.cpp
#ifndef GUARD_STUDENT_INFO_H
#define GUARD_STUDENT_INFO_H
// Student_info.h
#include <iostream>
#include <string>
#include <vector>
struct Student_info
{
std::string name;
double midterm, final;
std::vector<double> homework;
};
bool compare(const Student_info&, const Student_info&);
std::istream& read(std::istream&, Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);
#endif // GUARD_STUDENT_INFO_H
</p>
Header Files
getletterGrade.h
#ifndef GUARD_GETLETTERGRADE_H
#define GUARD_GETLETTERGRADE_H
// getLetterGrade.h
#include <string>
std::string getLetterGrade(double);
#endif // GUARD_GETLETTERGRADE_H
grade.h
#ifndef GUARD_GRADE_H
#define GUARD_GRADE_H
//grade.h
#include <vector>
#include "Student_info.h"
double grade(double, double, double);
double grade(double, double, const std::vector<double>&);
double grade(const Student_info&);
#endif // GUARD_GRADE_H
#ifndef GUARD_MEDIAN_H
#define GUARD_MEDIAN_H
// median.h - final version
#include <vector>
double median(std::vector<double>);
#endif // GUARD_MEDIAN_H
Student_info.h
#ifndef GUARD_STUDENT_INFO_H
#define GUARD_STUDENT_INFO_H
// Student_info.h
#include <iostream>
#include <string>
#include <vector>
struct Student_info
{
std::string name;
double midterm, final;
std::vector<double> homework;
};
bool compare(const Student_info&, const Student_info&);
std::istream& read(std::istream&, Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);
#endif // GUARD_STUDENT_INFO_H
Test Program
I test the program by submitting a list of sample student grades. The program automatically compute and display the numeric and letter grades. It also creates a letter grade summary to count occurances per letter grade.
johnny 90 90 90 90 90
jason 85 85 85 85 85
billy 82 82 82 82 82
fred 80 80 80 80 80
frank 70 70 70 70 70
jay 66 66 66 66 66
bob 60 60 60 60 60
mary 50 50 50 50 50
ann 40 40 40 40 40
bill 30 30 30 30 30
goat 10 10 10 10 10
dog 0 0 0 0 0
^Z
^Z
ann 40 (F)
bill 30 (F)
billy 82 (B)
bob 60 (D)
dog 0 (F)
frank 70 (C)
fred 80 (B)
goat 10 (F)
jason 85 (B)
jay 66 (D)
johnny 90 (A)
mary 50 (F)
Letter Grade Summary
A: 1
B: 3
C: 1
D: 2
F: 5
Reference
Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000