Unexpected Result

J

John J

Thankyou to those people in this newsgroup that have answered my questions
and helped me to learn whilst developing my yacht race classes.

I have now completed the three classes (Yacht, Race and Entry) and created
..cpp to test the classes. Everything compiles without fault; however, when I
run the program the first part of the expected output is not displayed. I
thought there may have been a buffer setting in my compiler so I tried
compiling and directing the output into another file, then when I viewed the
output file the results were the same. As I remove calls to functions from
my test .cpp more information is displayed. It seems to behaving exactly
like a buffer that flushes the initial input upon saturation.

All the code is below. Can I please ask someone to have a look at it and
advise where I'm going wrong (if I'm going wrong). If it is a buffer issue
does anyone no of a workaround? my compiler is vc++.

Thanks for any help


//Race.h

#ifndef RACE_H
#define RACE_H

#include <iostream> // for standard i/o
#include <string> // for string manipulation
using std::eek:stream;
using std::cout;

#include "Entry.h"
#include "Yacht.h"

const int MAX_ENTRIES = 50;

//Details of races
class Race
{
friend ostream& operator<< (ostream&, const Race&);

public:

//constructor
Race ( int n=0, string d="");

void enter_race (Yacht*,int, string);
void Show (ostream& out=cout) const;
void display_entries (ostream& out=cout) const;
void winner (ostream& out=cout) const;

//member function prototypes
int getNumber() const;
string getDate() const;

private:

//Attributes of races
int number;
string date;

//Attributes for association
Entry* entries[MAX_ENTRIES];
int nEntries;

};

ostream& operator<< (ostream&, const Race&);
#endif


//Race.cpp

#include <string>
#include "Race.h"
#include "Entry.h"
#include "Yacht.h"

using namespace std;

//Construct a race
Race::Race (int n, string d)
{
number = n;
date = d;
nEntries = 0;
for (int j=0; j<MAX_ENTRIES; j++)
entries[j] = NULL;
}

//Enter a race
void Race::enter_race (Yacht* y, int pl, string ti)
{
if (nEntries<MAX_ENTRIES)
{
Entry* e = new Entry (this,y,pl,ti);
entries[nEntries++] = e;
y->add_entry (e);
}
else cout << "Too many entries" << endl;
}

//Find an entry object(s)
void Race::display_entries (ostream& out) const
{
if (nEntries == 0)
out << "No entries" << endl;
else
{
cout << "Details of Yachts entered into the requested race:" <<endl <<
endl;
for (int i=0; i<nEntries; i++)
out << *(entries);
}
}

//Find the winner
void Race::winner (ostream& out) const
{
Entry* e = NULL;
if (nEntries == 0)
{
out << "No entries" << endl;
}
else
{
bool found_a_winner = false; // no winner found yet
for (int i=0; i<nEntries; i++)
{
e = entries;
if (e->getPlace() == 1)
{
out << "The winner is: " << endl;
out << *e;
found_a_winner = true; // a winner has been found
}
}
if (!found_a_winner) // if no winner
{
out << "No winner was found in this race" << endl;
}
}
}

//Access functions
int Race::getNumber (void) const
{
return number;
}

string Race::getDate (void) const
{
return date;
}

//Output functions

//Print Race info
void Race::Show (ostream& out) const
{
out << "Race Number : " << number << endl
<< "Race Date : " << date << endl;
}

ostream& operator<< (ostream& out, const Race& r)
{
r.Show (out);
if (r.nEntries == 0)
out << "No entries" << endl;
else
{
for (int i=0; i<r.nEntries; i++)
out << *(r.entries);
}
return out;
}


//Entry.h

#ifndef ENTRY_H
#define ENTRY_H

#include <iostream> // for standard i/o
#include <string> // for string manipulation
using std::eek:stream;
using std::string;

class Yacht;
class Race;

//Details of race entries
class Entry
{
friend ostream& operator<< (ostream&, const Entry&);

public:
//constructor
Entry (Race* r=NULL, Yacht* y=NULL, int pl=0, string ti="");

//access functions
int getPlace () const; //Yacht placing
string getTime () const; //Yacht finish time
Race* getRace () const; //Related race object
Yacht* getYacht () const; //Related yacht object

private:

//Attributes to implement the relationship
Race* which; //Which race
Yacht* what; //What yacht

//Attributes of the association
int place;
string time;

};

ostream& operator<< (ostream&, const Entry&);
#endif


//Entry.cpp

#include <iostream>
#include <string>
#include "Entry.h"
#include "Race.h"
#include "Yacht.h"

using namespace std;

//Construct an Entry
Entry::Entry (Race* r, Yacht* y, int pl, string ti)
{
which = r;
what = y;
place = pl;
time = ti;
}

//Access functions
int Entry::getPlace () const
{
return place;
}

string Entry::getTime () const
{
return time;
}

Race* Entry::getRace () const
{
return which;
}

Yacht* Entry::getYacht () const
{
return what;
}

//Overload of operator<< for output of an Entry
ostream& operator<< (ostream& out, const Entry& e)
{
Yacht* y = e.what;
Race* r = e.which;

out << endl << "Yacht : " << *y << endl
<< "Race : " ; r->Show();
out << "Finish Place : " << e.place << endl
<< "Finish Time : " << e.time << endl << endl;

return out;
}

//Yacht.h

#ifndef YACHT_H
#define YACHT_H

#include <iostream> // for standard i/o
#include <string> // for string manipulation
using std::eek:stream;
using std::string;

#include "Entry.h"
#include "Race.h"

const int MAX_Y_ENTRIES = 50;

//Details of yachts
class Yacht
{
friend ostream& operator<< (ostream&, const Yacht&);

public:
//constructor
Yacht (string n="", string c="");

void add_entry (Entry*);
void display_races (ostream& out=cout) const;
void best_result (ostream& out=cout) const;

//member function prototypes
string getName() const;
string getCaptain() const;

private:

//Attributes of yachts
string name;
string captain;

//Attributes of association
Entry* yacht_entries[MAX_Y_ENTRIES];
int nYEntries;

};

ostream& operator<< (ostream&, const Yacht&);
#endif


//Yacht.cpp

#include <iostream>
#include <string>
#include "Yacht.h"
#include "Entry.h"
#include "Race.h"

using namespace std;

//Construct a yacht
Yacht::Yacht (string n, string c)
{
name = n;
captain = c;
nYEntries = 0;
for (int j=0; j<MAX_Y_ENTRIES; j++)
yacht_entries[j] = NULL;

}

//Enter a race
void Yacht::add_entry (Entry* e)
{
if (nYEntries<MAX_Y_ENTRIES)
{
yacht_entries[nYEntries++] = e;
}
else cout << "Too many entries" << endl;
}

//Find races a Yacht entered
void Yacht::display_races (ostream& out) const
{
if (nYEntries == 0)
out << "No entries for this Yacht" << endl << endl;
else
{
cout << "Details of races a Yacht entered:" <<endl << endl;
for (int i=0; i<nYEntries; i++)
out << *(yacht_entries);
}
}

//Display the best result of a Yacht in all entered races
void Yacht::best_result (ostream& out) const
{
Entry* e =NULL;
out << "A search of races for this Yacht shows the following results: " <<
endl << endl;
if (nYEntries == 0)
{
out << "This Yacht has entered no races: " << endl;
}
else
{
Entry* best_result = yacht_entries[0];
for( int i = 1; i < nYEntries; i++ )
{
if (yacht_entries->getPlace() < best_result->getPlace())
best_result = yacht_entries;
}
cout << "Best result was " << endl << *best_result;
}
}

//Access functions
string Yacht::getName (void) const
{
return name;
}

string Yacht::getCaptain (void) const
{
return captain;
}

//Overload of operator<< for output of a yacht
ostream& operator<< (ostream& out, const Yacht& y)
{
out << y.name << " (Captain: " << y.captain << ")";
return out;
}

//Test.cpp

#include <iostream>
#include <string>
#include "Entry.h"
#include "Race.h"
#include "Yacht.h"
using namespace std;

int main ()
{
Race r1(1, "23/12/03");
Race r2(2, "24/12/03");
Race r3(3, "25/12/03");
Race r4(4, "26/12/03");
Race r5(5, "27/12/03");

Yacht y1("The Bounty", "William Bligh");
Yacht y2("The Hilda", "Some bloke");
Yacht y3("The Mary Celeste", "Benjamin Briggs");
Yacht y4("Speedy", "Some other bloke");
Yacht y5("Fishing Boat", "Me");
Yacht y6("No hoper", "Not me");
Yacht y7("Can't catch a fish", "Some dood");
Yacht y8("Wanta geta fish", "Andrew Maden");
Yacht y9("The endeavour", "James Cook");
Yacht y10("Cignet", "William Dampier");
Yacht y11("Nippon", "Peter Gilmour");

r1.enter_race (&y1,3, "22:30");
r1.enter_race (&y2,2, "22:00");
r1.enter_race (&y3,1, "21:00");
r1.enter_race (&y4,4, "23:00");
r1.enter_race (&y5,5, "24:00");
r1.enter_race (&y6,6, "25:00");

r2.enter_race (&y4,1, "15:00");
r2.enter_race (&y1,2, "15:30");
r3.enter_race (&y5,3, "17:00");

r3.enter_race (&y3,1, "10:00");
r3.enter_race (&y3,2, "11:00");
r3.enter_race (&y4,3, "12:00");

r4.enter_race (&y6,1, "15:00");
r4.enter_race (&y7,2, "15:30");
r4.enter_race (&y8,3, "17:00");

r5.enter_race (&y8,1, "10:00");
r5.enter_race (&y9,2, "11:00");
r5.enter_race (&y10,3, "12:00");

cout << r1 << endl;
r1.winner();

cout << r2 << endl;
r2.winner();

cout << r3 << endl;
r3.winner();

cout << r4 << endl;
r4.winner();

cout << r5 << endl;
r5.winner();

cout << "Yacht 1 : " << endl;
y1.display_races();
y1.best_result();

cout << "Yacht 2 : " << endl;
y2.display_races();
y2.best_result();

cout << "Yacht 3 : " << endl;
y3.display_races();
y3.best_result();

cout << "Yacht 4 : " << endl;
y4.display_races();
y4.best_result();

cout << "Yacht 5 : " << endl;
y5.display_races();
y5.best_result();

cout << "Yacht 6 : " << endl;
y6.display_races();
y6.best_result();

cout << "Yacht 11 : " << endl;
y11.display_races();
y11.best_result();



return 0;
}
 
J

John Harrison

John J said:
Thankyou to those people in this newsgroup that have answered my questions
and helped me to learn whilst developing my yacht race classes.

I have now completed the three classes (Yacht, Race and Entry) and created
.cpp to test the classes. Everything compiles without fault; however, when I
run the program the first part of the expected output is not displayed. I
thought there may have been a buffer setting in my compiler so I tried
compiling and directing the output into another file, then when I viewed the
output file the results were the same. As I remove calls to functions from
my test .cpp more information is displayed. It seems to behaving exactly
like a buffer that flushes the initial input upon saturation.

All the code is below. Can I please ask someone to have a look at it and
advise where I'm going wrong (if I'm going wrong). If it is a buffer issue
does anyone no of a workaround? my compiler is vc++.

Thanks for any help

It's not a buffer issue, it's bug in your code (I don't know this but I'd be
prepared to bet a pound to a penny). Just to help everyone along could you
explain which part of the output is missing? You say the first part, but
which part is that exactly?

john
 
A

Alf P. Steinbach

* "John J said:
Thankyou to those people in this newsgroup that have answered my questions
and helped me to learn whilst developing my yacht race classes.

I have now completed the three classes (Yacht, Race and Entry) and created
.cpp to test the classes. Everything compiles without fault; however, when I
run the program the first part of the expected output is not displayed. I
thought there may have been a buffer setting in my compiler so I tried
compiling and directing the output into another file, then when I viewed the
output file the results were the same. As I remove calls to functions from
my test .cpp more information is displayed. It seems to behaving exactly
like a buffer that flushes the initial input upon saturation.

All the code is below. Can I please ask someone to have a look at it and
advise where I'm going wrong (if I'm going wrong). If it is a buffer issue
does anyone no of a workaround? my compiler is vc++.

Thanks for any help


//Race.h

#ifndef RACE_H
#define RACE_H

#include <iostream> // for standard i/o

Use only the forwarding header, not the full header, if you absolutely
must.

But better redesign so as to remove i/o from the classes.


#include <string> // for string manipulation
OK.


using std::eek:stream;
using std::cout;

DO NOT do this in a header file.


#include "Entry.h"
#include "Yacht.h"

const int MAX_ENTRIES = 50;

DO NOT use all uppercase letters for anything else than macros.


//Details of races
class Race
{
friend ostream& operator<< (ostream&, const Race&);

public:

//constructor
Race ( int n=0, string d="");

void enter_race (Yacht*,int, string);
void Show (ostream& out=cout) const;
void display_entries (ostream& out=cout) const;
void winner (ostream& out=cout) const;

//member function prototypes
int getNumber() const;
string getDate() const;

private:

//Attributes of races
int number;
string date;

Consider using some convention to indicate that these are member
variables. Personally I prefer the prefix "my" (in general), because
that is readable and also used in e.g. Java. Some people prefer a
suffix "_", but underscores are used so much that I don't think it's
good -- rather, ungood.


//Attributes for association
Entry* entries[MAX_ENTRIES];

Use a std::vector.

Not a raw array.

int nEntries;

};

ostream& operator<< (ostream&, const Race&);
#endif


//Race.cpp

#include <string>
#include "Race.h"
#include "Entry.h"
#include "Yacht.h"

using namespace std;

//Construct a race
Race::Race (int n, string d)
{
number = n;
date = d;
nEntries = 0;
for (int j=0; j<MAX_ENTRIES; j++)
entries[j] = NULL;

This is undefined behavior.

You have not allocated 'entries' at this point.

Also, use ++j, not j++... ;-)



[Much more but I'm too lazy. Fix the above, then come back.]
 
J

John Harrison

//Attributes for association
Entry* entries[MAX_ENTRIES];

Use a std::vector.

Not a raw array.

int nEntries;

};

ostream& operator<< (ostream&, const Race&);
#endif


//Race.cpp

#include <string>
#include "Race.h"
#include "Entry.h"
#include "Yacht.h"

using namespace std;

//Construct a race
Race::Race (int n, string d)
{
number = n;
date = d;
nEntries = 0;
for (int j=0; j<MAX_ENTRIES; j++)
entries[j] = NULL;

This is undefined behavior.

You have not allocated 'entries' at this point.

Also, use ++j, not j++... ;-)

Look again Alf, entries is an array of size MAX_ENTRIES declared in the Race
object.

john
 
A

Alf P. Steinbach

* "John Harrison said:
//Attributes for association
Entry* entries[MAX_ENTRIES];

Use a std::vector.

Not a raw array.

int nEntries;

};

ostream& operator<< (ostream&, const Race&);
#endif


//Race.cpp

#include <string>
#include "Race.h"
#include "Entry.h"
#include "Yacht.h"

using namespace std;

//Construct a race
Race::Race (int n, string d)
{
number = n;
date = d;
nEntries = 0;
for (int j=0; j<MAX_ENTRIES; j++)
entries[j] = NULL;

This is undefined behavior.

You have not allocated 'entries' at this point.

Also, use ++j, not j++... ;-)

Look again Alf, entries is an array of size MAX_ENTRIES declared in the Race
object.

Urgh, grumble, spit, hark, darn.
 
J

John J

It's strange but if I start to remove calls to functions at the end of the
Test.cpp file, the expected data outputs begin to appear.

For example, the first ouput I would expect would be from the call:

cout << r1 << endl;
r1.winner();

and I'm able to get this output if I start to strip away the functions from
the end of the Test.cpp file.

That's why I've compared the problem to a buffer in behavior.

I've looked through the code, but nothing stands out as an obvious error.

Thanks
 
J

John Harrison

John J said:
It's strange but if I start to remove calls to functions at the end of the
Test.cpp file, the expected data outputs begin to appear.

For example, the first ouput I would expect would be from the call:

cout << r1 << endl;
r1.winner();

and I'm able to get this output if I start to strip away the functions from
the end of the Test.cpp file.

That's why I've compared the problem to a buffer in behavior.

I've looked through the code, but nothing stands out as an obvious error.

Thanks

As far as I can tell it produces the correct output for me.

Race Number : 1
Race Date : 23/12/03

etc. etc

john
 
K

Karl Heinz Buchegger

John said:
All the code is below. Can I please ask someone to have a look at it and
advise where I'm going wrong (if I'm going wrong). If it is a buffer issue
does anyone no of a workaround?

Hmm. It is some sort of buffer issue. But it is not your program
or VC++ doing that.

The output of your program goes to a console window. But this console
window store only some x lines for scrolling. When your program
outputs more lines, the first lines will simply scroll out of
the console windows buffer.

Reorganize your output such that it takes less lines
on the screen. Eg. putting the 'Race Number' and the 'Race Date'
on the same line as well as putting 'Finish Place' and 'Finish Time'
did the trick for your example, but I agree: that is not a general
solution.

Formatting output can be a tricky business. You could eg. try
if something more table-like would do a better job, Eg.


Race: 1 Date: 23/12/03

Yacht Skipper Place Finish Time
**************************************************************
The Bounty William Bligh 3 22:30
The Hilda Some bloke 2 22:00
The Mary Celeste Benjamin Briggs 1 21:00
Speedy Some other bloke 4 23:00
Fishing Boat Me 5 24:00
No hoper Not me 6 25:00

Winner: The Mary Celeste with Skipper Benjamin Briggs


It contains the same information for Race 1 as your output. But instead
of 52 lines, it takes only 12 lines of output.
 
J

John J

Thanks for the feedback. I'm just happy to know it's not my code. I'll
adjust the output as suggested.

Thanks again for help
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Associated classes 3
Class search function 1
Search function 3
best result function 15
Chatbot 0
Search function 0
Calling a function in another class 2
Character operations in C++ 2

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top