I am working from a book called Accelerated C++ to learn the language. I am currently in the section which talks about how programs are structured to enable separate compilation. The book is confusing me at this point. We left off with this program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <ios>
#include <string>
#include <vector>
#include <stdexcept>
using namespace std;
struct Student_info
{
string name;
double midterm, final;
vector<double> homework;
};
bool compare(const Student_info& x, const Student_info& y)
{
return x.name < y.name;
}
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];
}
double grade(double midterm, double final, double homework)
{
return 0.2 * midterm + 0.4 * final + 0.4 * homework;
}
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));
}
double grade(const Student_info& s)
{
return grade(s.midterm, s.final, s.homework);
}
istream& read_hw(istream& in, vector<double>& hw)
{
if(in)
{
hw.clear();
double x;
while(in >> x)
{
hw.push_back(x);
}
in.clear();
}
return in;
}
istream& read(istream& is, Student_info& s)
{
is >> s.name >> s.midterm >> s.final;
read_hw(is, s.homework);
return is;
}
int main()
{
vector<Student_info> students;
Student_info record;
string::size_type maxlen = 0;
while(read(cin, record))
{
maxlen = max(maxlen, record.name.size());
students.push_back(record);
}
sort(students.begin(), students.end(), compare);
for(vector<Student_info>::size_type i = 0; i != students.size(); ++i)
{
cout << students[i].name << string(maxlen + 1 - students[i].name.size(), ' ');
try
{
double final_grade = grade(students[i]);
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade << setprecision(prec);
} catch (domain_error &e)
{
cout << e.what();
}
}
return 0;
}
|
Now, it seems to be suggesting that I should pull out functions such as median and place them into separate files such as median.cpp: "Most implementations require the names of C++ source files to end in .cpp, .C or .c, so we might put the median function in a file named median.cpp, median.C or median.c, depending on the implementation."
However, it then goes on to say: "The next step is to make the median function available to other users. Analogous with the standard library, which puts the names it defines into headers, we can write our own header file that will..."
So is the book trying to say that I should pull out functions like median and put them into their own source files, then, create header files for those functions, then, include those header files in the actual program? For instance:
median.cpp includes median.h
StudentGrades.cpp includes StudentGrades.h
StudentGrades.h includes median.h
is that the correct structure? Or should I just include median.h in StudentGrades.cpp and if that's what I am supposed to do then what's the point on StudentGrades.h?