Google Answers Logo
View Question
 
Q: C++ Programming question. ( No Answer,   1 Comment )
Question  
Subject: C++ Programming question.
Category: Computers > Programming
Asked by: purplepit-ga
List Price: $35.00
Posted: 03 Jun 2003 06:12 PDT
Expires: 03 Jul 2003 06:12 PDT
Question ID: 212399
Hi there, can you help with the following questions, this looks more
than it is, as the question is a rather rambling one:-

Given the scenario of a bike ride to raise money for charity, whereby
entrants are allocated
 a unique entry number, and to record their start time(hours minutes
and seconds)
for the start of the ride, and finish time(hours minutes and
seconds)for when they finish.
and the amount of money raised.

The data will then be ordered(sorted) by journey time and seperatly by
amount raised.

Given the above, I've defined two structs, to represent:

 1) a start or finish time.

  
    Struct Time {
    int hr; int min; int sec;
    };

 2) To represent the entrant.

    Struct Entrant{
    int number;
    Time Start;
    Time Finish;
    Float amount;
    };

 The following sort() algorithm from the STL will be used to sort the
data:
 
 void sort (random_it, random_it pred);

 where random_it stands for "random access iterator" and pred stands
for "predicate function" with 2
 arguments of data type Entrant, and returns a boolean result to
indicate the order of predcedence
 of 2 entrants in a sort operation.(The same type of predicate is used
to for controlling the order
 of all items in a priority_queue)

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 QUESTIONS:

 1) I need to declare variable entrants as a vector<> to store the
data for all the cyclists
  
 2) write a suitable predicate called by_amount which will, when used
with the sort()function
    sorts the data into decending order of money raised.

 3) write a suitable predicate called by_time which when used with the
sort()function
    sorts the data into ascending order of time taken.

 4) Write a function display_entrant(), having a single argument of an
entrant, displaying the data as follows:

    999  07:30:45  11:05:55  325.50 (entry no,start time,finish time,
amount raised)

 5) Show how the display_entrant() function can be used to the
for_each() algorithm to display data for all entrants.

   ALL NUMBERED AND COMMENTS OF EXPLANATION IF POSSIBLE!!!!

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Thanks very much.......

Clarification of Question by purplepit-ga on 04 Jun 2003 06:32 PDT
Hi snipr-

And thanks for the answer,

This doesn't actually physically need to be compiled and run as a
program, as it's just a question example from a past exam paper, so
all I need really is the sections of code in relation to the question
numbers!!
So for clarification purposes, could you please just simplify your
answer into the relevent pieces of code n accordance with the question
numbers?

Thanks also for all the links, which I'm sure will be of great help in
the future.

Thanks ever so much

Purplepit-ga
Answer  
There is no answer at this time.

Comments  
Subject: Re: C++ Programming question.
From: snipr-ga on 03 Jun 2003 15:55 PDT
 
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

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy