Core.h
#ifndef GUARD_core_h
#define GUARD_core_h
// Core.h
#include <string>
#include <iostream>
#include <vector>
class Core {
public:
Core():midterm(0),final(0) { }
Core(std::istream& is) { read(is); }
std::string name() const;
virtual std::istream& read(std::istream&);
virtual double grade() const;
protected:
// accessible to derived classes
std::istream& read_common(std::istream&);
double midterm,final;
std::vector<double> homework;
private:
// accessible only to Core
std::string n;
};
std::istream& read_hw(std::istream&, std::vector<double>&);
double grade(double, double, std::vector<double>);
bool compare(const Core*, const Core*);
#endif
Core.cpp
// source file Core-related
#include "Core.h"
#include "/home/rhk/workspace/4_grade/median.h"
using std::string; using std::vector;
using std::istream;
string Core::name() const { return n; }
double Core::grade() const {
return ::grade(midterm, final, homework);
}
istream& Core::read_common(istream& in) {
// read and store the student's name and exam grades
in >> n >> midterm >> final;
return in;
}
istream& Core::read(istream& in) {
read_common(in);
read_hw(in, homework);
return in;
}
double grade(double midterm, double final, vector<double> homework) {
return 0.2 * midterm + 0.4 * final + 0.4 * median(homework);
}
// read homworks
istream& read_hw(istream& in, vector<double>& hw) {
if (in) {
// get rid of previous contents
hw.clear();
// read homework grades
double x;
while (in >> x)
hw.push_back(x);
// clear the stream so that input will work for the next student
in.clear();
}
return in;
}
bool compare(const Core* cp1, const Core* cp2) {
return cp1->name() < cp2->name();
}
Grad.h
#ifndef GUARD_grad_h
#define GUARD_grad_h
#include "Core.h"
class Grad:public Core {
public:
Grad(): thesis(0) { }
Grad(std::istream& is) { read(is); }
double grade() const;
std::istream& read(std::istream&);
private:
double thesis;
};
#endif
Grad.cpp
// source file of Grad-related
#include "Core.h"
#include "Grad.h"
#include <algorithm>
using std::istream;
using std::min;
istream& Grad::read(istream& in) {
read_common(in);
in >> thesis;
read_hw(in, homework);
return in;
}
double Grad::grade() const {
return min(Core::grade(), thesis);
}
func.h
#ifndef GUARD_func_h
#define GUARD_func_h
#include <iostream>
std::istream& read_hw(std::istream&, std::vector<double>&);
#endif
func.cpp
// source file for functions
#include "func.h"
using std::istream; using std::vector;
istream& read_hw(istream& in, vector<double>& hw) {
if (in) {
// get rid of previous contents
hw.clear();
// read homework grades
double x;
while (in >> x)
hw.push_back(x);
// clear the stream so that input will work for the next student
in.clear();
}
return in;
}
main.cpp
#include "Core.h"
#include "Grad.h"
#include <algorithm>
#include <ios>
#include <iomanip>
#include <stdexcept>
using std::string; using std::cout; using std::cin;
using std::endl; using std::vector; using std::max;
using std::streamsize; using std::sort; using std::setprecision;
using std::domain_error;
int main() {
vector<Core*> students;
Core* record;
char ch;
string::size_type maxlen = 0;
while (cin >> ch) {
if (ch == 'U')
record = new Core;
else
record = new Grad;
record->read(cin);
maxlen = max(maxlen, record->name().size());
students.push_back(record);
}
sort(students.begin(), students.end(), compare);
for (vector<Grad>::size_type i = 0; i < students.size(); ++i) {
cout << students[i]->name() << string(maxlen + 1 - students[i]->name().size(), ' ');
try {
double final_grade = students[i]->grade();
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade <<
setprecision(prec) << endl;
} catch (domain_error e) {
cout << e.what() << endl;
}
}
return 0;
}