Hello purplepit, I believe I can be of some assistance here. Sorry if
I go too deep into explanation, I can't assume how much you do/don't
know. If I don't explain anything too clearly, feel free to request
more information. BTW, anything between double dashes is a code
excerpt:
============================================================ 1
You are asked to use the STL vector<> template class to hold a
variable number of cyclists along with their data:
First, you should
--
#include <vector>
using namespace std;
--
This will properly include the STL vector template class for usage.
The second line is used to tell the compiler that from here on out,
you will be using the std namespace. This way, if there are any other
vector classes declared elsewhere, the compiler will know to use the
std::vector class over the other one (if it even exists). A good
tutorial of namespaces can be found at
http://www.cplusplus.com/doc/tutorial/tut5-2.html
Now you can declare the cyclists vector
--
vector<Entrant> cyclist;
--
Since vector is a templated class, it can handle any arbitrary data
type, not just Entrant, and there is the beauty and power of
templates. There are plenty of template tutorials to be found, one
such would be http://www.parashift.com/c++-faq-lite/containers-and-templates.html
============================================================ 2
Templates help abstract the data type you are working on while
predicates help to abstract the functionality of the algorithms used.
The STL sort() funciton is easily customizable by using a function
object (also known as functor). A function object is really just a
class with a public operator() defined.
So, the first predicate you want is a by_amount predicate to sort by
descending order of money raised. sort() uses predicates by saying
that if, given 2 objects, if the predicate evaluates to true, the 1st
object should come before the 2nd object in the list (or vector).
--
class by_amount
{
public:
bool operator()(const Entrant& e1, const Entrant& e2) const
{
return (e1.amount > e2.amount);
}
};
--
The class by_amount has effectively become the predicate we will use
to sort our data. As you can see, it declares operator() taking 2
constant references to Entrants and returning a true or false. Both
references are constant because we do not need to modify them and the
entire function is constant because the predicate itself is not
modified. This functor returns true if and only if the first entrants
amount raised is greater than the second entrants amount raised. The
STL sort() function will use this object to determine if one Entrant
should be swapped higher than another Entrant, which is defined by our
operator().
Now, to use this with the sort() function, given that our vector of
Entrants has been declared as 'cyclist'
--
sort(cyclist.begin(), cyclist.end(), by_amount());
--
This will effectively sort the entire cyclist list by amount raised,
descending. A decent text on functors, etc can be found at
http://www.mochima.com/tutorials/STL_algorithms.html
============================================================ 3
The same idea will be used here...we will create a predicate for use
in sort(), this time to sort ascending by time taken to complete the
race. First code, then explanation
--
class by_time
{
public:
bool operator()(const Entrant& e1, const Entrant& e2) const
{
Time e1total;
e1total.hr = e1.Finish.hr - e1.Start.hr;
e1total.min = e1.Finish.min - e1.Start.min;
e1total.sec = e1.Finish.sec - e1.Start.sec;
Time e2total;
e2total.hr = e2.Finish.hr - e2.Start.hr;
e2total.min = e2.Finish.min - e2.Start.min;
e2total.sec = e2.Finish.sec - e2.Start.sec;
if (e1total.hr != e2total.hr)
return (e1total.hr < e2total.hr);
if (e1total.min != e2total.min)
return (e1total.min < e2total.min);
return (e1total.sec < e2total.sec);
}
};
--
This is a little more complicated, but still manageable. First, we
need to figure out the total times for both of the Entrants (e1 and
e2). So, we declare 'total' times for both of the Entrants (e1total,
e2total, respectively). Then, we subtract the Start hour/min/sec from
the Finish hour/min/sec to obtain the final overall time. It is
possible that they finished with the same hour elapsed. If they
didn't, we should return whoever's hour is less because they finished
faster. The same goes for min. If both min and hr are the same, we
should unconditionally return whose sec is less. If they tie (they
have the exact same hr/min/sec), then the order in the sorting won't
matter anyways.
Again, you can sort the cyclist list by doing
--
sort(cyclist.begin(), cyclist.end(), by_time());
--
============================================================ 4
Assuming you're using cout instead of printf to do printing, you must
first include this stuff at the top of your source file (along with
the other #include's)
--
#include <iostream>
#include <iomanip>
--
We can now display a single entrant's data like this
--
void display_entrant(const Entrant& e)
{
cout << e.number << " ";
// print start hour (leading 0 if necessary)
if (e.Start.hr < 10)
cout << "0";
cout << e.Start.hr << ":";
// print start min (leading 0 if necessary)
if (e.Start.min < 10)
cout << "0";
cout << e.Start.min << ":";
// print start sec (leading 0 if necessary)
if (e.Start.sec < 10)
cout << "0";
cout << e.Start.sec << " ";
// print finish hour (leading 0 if necessary)
if (e.Finish.hr < 10)
cout << "0";
cout << e.Finish.hr << ":";
// print finish min (leading 0 if necessary)
if (e.Finish.min < 10)
cout << "0";
cout << e.Finish.min << ":";
// print finish sec (leading 0 if necessary)
if (e.Finish.sec < 10)
cout << "0";
cout << e.Finish.sec << " ";
// print amount raised with 2 digit cent precision
cout << setprecision(2) << e.amount << endl;
}
--
Again, this function takes a constant reference to an Entrant since we
have no desired to modify it in any way.
We said '#include <iomanip>' to allow us to manipulate the precision
of cout used on the last line of the function. 'cout <<
setprecision(2)' will print '0.50' even if the float value is '0.5'.
If we said 'cout << setprecision(5)', the value '0.5' would print out
as '0.50000'. The printing before the amount consists of printing a
leading zero if the value was less than ten, so 9 becomes '09', etc,
and then printing the value. For a reference on manipulating cout and
streams, see http://www.tacc.utexas.edu/resources/user_guides/pgi/pgC++_lib/stdlibcr/cou_4514.htm
============================================================ 5
Now we want to iterate over all of the entrants and print each one of
them. First we must include another STL header to allow us to use
for_each
--
#include <algorithm>
--
Using iterators, we can go from the beginning to the end of the list
and use display_entrant() to display each of the entrants, assuming
that 'cyclist' is still the globally defined vector of Entrant
--
for_each(cyclist.begin(), cyclist.end(), display_entrant);
--
for_each takes a beginning iterator and an ending iterator, much like
many of the STL functions. It also takes a function explaining what
we should do with each of the entries in the array. All we want to do
is call display_entrant() on each of the Entrants, so we go from
begin() to end() of cyclist (which again is our globally defined
vector<Entrant>). If you wanted, you could also move the iterators
around using find() and whatever else and then only print out a subset
of the list. A quick and dirty iterator run down can be found at
http://www.msoe.edu/eecs/ce/courseinfo/stl/iterator.htm
=============================================================
I hope this helps...if you need anything else, I'd be more than happy
to help, or if you need a more complete version (code written
together), I'd be happy to do that as well. Hope this helps!
-snipr |