|
We'll have our array stu
of objects of type student, and
we'll use the same old selection sort routine we've always been using. Now, at
some point in selection sort, we'll swap two elements of
stu
and I want to take a brief moment to look at what that
means. The following picture shows how swap(stu[i],stu[j])
affects things. Hopefully you see, once again, that we're not moving the
actual arrays of grades at all, we're simply moving the pointers to
those arrays.
Now, if we're going to sort this array of Student
objects, it's just like sorting anything else!
|
So, the only thing that remains is to produce a
before function that will take two
Student objects and decide whether the first needs
to come before the second. Remember we want our
Student objects in order from lowest to highest
score on homework #4. So, for before(a,b) , I need
to determine whether the homework #4 score for a is
less than the homework #4 score for b .
With this, it's easy to write a program that prints out
students & their HW#4 scores ordered from lowest to highest HW#4
score. Here's a complete program.
|
x
is the assignment number, we'd have to modify
before
to be:
bool before(Student a, Student b)
{
if (a.hw[x] < b.hw[x]) // we should sort based on grade x
return true;
else
return false;
}
Q. There's a problem in the above code. What is it?
A: Where does the function get x from?
The only way it can get
x
is if we pass it in as a parameter. So the
function must look like:
bool before(Student a, Student b, int x) // int x is added to fix the problem
{
if (a.hw[x] < b.hw[x])
return true;
else
return false;
}
Now, this fixes before
, but it necessitates a change
in indexOfMax
, which is the function that calls
before
.
int indexOfMax(Student* A, int N)
{
int imax = 0, i;
for(i = 1; i < N; i++)
if (before(A[imax],A[i],x)) // argument x is added
imax = i;
return imax;
}
Q. There's a problem in the above code. What is it?
A: Again, where does the function get x from?
It seems that another parameter is required for indexOfMax
as
well.
int indexOfMax(Student* A, int N, int x) // int x is added
{
int imax = 0, i;
for(i = 1; i < N; i++)
if (before(A[imax],A[i],x))
imax = i;
return imax;
}
Similarly, sort
is going to require an extra
parameter to pass along to indexOfMax
. Putting it all
together, we get this final program.
Pretty nice, eh?
One thing we're going to do is reuse code. This idea is very dear to those of us who are lazy ... which definitely includes me. A quadrilateral is defined by its four vertices, which are of course points, and we've done points to death already. As a matter of fact, going through the lecture notes, I find at least all these definitions for dealing with points. And we could round this out to include subtraction of points, or I/O, or whatever else we wanted. Instead of reinventing the wheel, let's reuse this code.
Given this, I'll represent a quadrilateral by the four
point
s that are its vertices, and in the context I
have in mind, I'll also give each quadrilateral a character that
acts as a label. The struct for quadrilateral, which I'll call
Quad
, has the following simple definition:
struct Quad
{
char label;
point* vert;
};
Here's a simple main()
using the struct. All it does is
read in a Quad
and print it back out again. Notice
how I create an object of type Quad
. It takes two
steps, one actually creates the Quad
object, and one
allocates the array of four points that stores the vertices.
int main()
{
// Create quadrilateral S
Quad S;
S.vert = new point[4];
// Read label and vertices
cout << "Enter label and 4 vertices: ";
cin >> S.label;
for(int i = 0; i < 4; i++)
read(S.vert[i], cin);
// Write label and vertices
cout << "Your quadrilateral is " << S.label << " ";
for(int j = 0; j < 4; j++)
{
write(S.vert[j], cout);
cout << ' ';
}
cout << endl;
return 0;
}
This gives us a pretty good look at how we've done things so far,
and you can look at the complete program
to make sure you see how all these pieces fit together.
point
stuff, and the new code, which is the
Quad
definition and the main
function.
Furthermore, the point
stuff falls into two obvious
pieces - the struct definitions & function prototypes, and the
function definitions.
point.h -- Prototypes for point stuff |
point.cpp -- Definitions for point -related functions | ||
|
main.cpp -- New code with definition for |
Quad and
main
|
|
point.h
,
main.cpp
, and
point.cpp
.
point
and all of its
related functions, we really only need the function prototypes and struct
definition - the definitions of the functions don't really
concern us as users of point
. We only care about
what's available for us to use, not how it works. So, the file
main.cpp
begins with the
line:
#include "point.h"
which means literally pretend that the entire contents of
point.h
was typed in starting at this point.
Thus, as far as the compiler is concerned, it's like that struct
definition and all those prototypes were right there.
point.cpp
also begins with #include "point.h"
, since those
function definitions won't make sense to the compiler without
the definition of the struct point
and the prototypes.
main.cpp
and
point.cpp
, both of
which use point.h
.
It's perfectly willing to compile point.cpp
, saying
"I believe there is a main
function somewhere
that's going to use these function definitions.
And the compiler is perfectly willing to compile
main.cpp
saying "I believe there are some .cpp
files somewhere that define these functions that
main
uses and whose prototypes are given in the
included file point.h
.
.h
file (or header file) that
gives the outside world all the information it needs to use the module,
and a .cpp
file that contains the source code that implements the
module (i.e. that tells the compiler how all these functions really work).
What you saw up above was a very simple point
module.
One key thing that's missing from my simple point module, however, is documentation. The header file needs a lot of documentation so that the user of the module understands how to use the struct and the various functions the module offers. They don't need to know how it works, but they do need to know what it does!
g++ main.cpp point.cppThe above command will create an executable program
a.out
.
point
struct and a
struct hhmmss
. Break the program up into separate
point
and hhmmss
modules, and of
course a main file. We have the following pieces:
datum
, but it seems less likely to be reused, so
there's a less compelling reason for doing it.
A: struct definition of point, function prototypes, documentation of what functions do
A: #include "point.h"
#include <point.h>Fix:
#include "point.h"
A: g++ main.cpp point.cpp (you don't need to include point.h)