Question: You are to develop a program to read Baseball player statistics from an input file. Each player should be stored in a Player object. This
You are to develop a program to read Baseball player statistics from an input file. Each player should be stored in a Player object. This program builds on to the requirements for Program #2 and #3. Please see the earlier assignments for the definition of a Player Object.
This will read in the same type of player data from an input file and write the results to the screen New Requirements You are to implement our collection of baseball players as a binary tree, ordered by the player's name. (Lastname first, then firstname, in the event of people with the same last name). Your Tree class must implement at least the following methods, and any supporting methods you need. Reminder: Because many tree operations are recursive using a node pointer to a root or subroot as input, many operations have a private version that is called with the correct pointer and a public version presented to the user who has no concept of the internal implementation of the tree.
default constructor and destructor
insert - to add a new player to the tree
free - to clean up a tree and free all of the nodes in the tree
count - to return a count of all players in the tree
display - to display the player records, in appropriate order.
updateAvg - to update a particular player's batting average
find - find a player by name As with the prior programs, you must write a main program to adequately test your methods.
Additionally, prompt the user for the name of a player and a new batting average. Find that player in the tree and update his average to the new value. If the player is not found in the tree, indicate that to the user with a message. Prompt the user to perform this operation until the user is ready to quit the program. After the user is finished testing the search and replace for batting averages, print the contents of the tree to the screen in sorted order (ascending) and in reverse order (descending).
Program 3 is:
Main:
#include
#include
#include "OrderedPlayerList.h"
using namespace std;
int main (void)
{ const int FNLENGTH = 100; // use a reasonable size for filenames
char inputFileName[FNLENGTH]; // create buffers to store filenames
char outputFileName[FNLENGTH];
ifstream inFile; // create file objects for our 2 files
ofstream outFile;
Player currentPlayer; // use to store the next player from the file, or a found player from the list
OrderedPlayerList myList; // use to store the player list
int i; // loop counter
cout << "Testing a locate in an empty list to make sure it does not crash or error! ";
myList.locate("Chipper", "Jones", cout); cout << " ";
// Prompt the user and open the input data file
cout << "Please enter the name of your input data file: ";
cin >> inputFileName;
inFile.open(inputFileName);
if (inFile.fail()) { // file open failed cout << " Error opening input file. Cannot process player data. Exiting Program. " << endl;
return 0; // NOTE THIS IS THE ONLY TIME I ALLOW AN EMBEDDED RETURN or BREAK type exit IN A PROGRAM
}
// file opened successfully
while (!inFile.eof()) { // as long as there are lines of data to be read in // read in a player
currentPlayer.Read(inFile);
// store in list
myList.add(currentPlayer);
}
inFile.close();
// Now write the player data to the desired output file
cout << "Please enter the name of your output data file: ";
cin >> outputFileName;
outFile.open(outputFileName); // as long as there is space on disk, this won't fail
outFile << "There were " << myList.getSize() << " players in the input data file: " << endl;
myList.resetToEnd(); // get the list ready for iteration (BACKWARDS JUST TO CHECK MY LINKS!!!
while (myList.getPrev(currentPlayer)) // as long as getPrev returns TRUE for success!
{ currentPlayer.Write(outFile); // write the most recently retrieved player to the output file
outFile << endl;
}
outFile.close();
cout << " Your output is stored in the file named " << outputFileName << endl;
cout << " Let's test your find operation a couple of times! " ;
if(myList.locate("Chipper", "Jones", cout)) cout << " --- was found in the list!";
else
cout << " --- 2 nearest found the list!";
cout <<" ";
// make sure to test where we go off of the end of the list
if(myList.locate("Mark", "Jones", cout)) cout << " --- was found in the list!";
else
cout << " --- 2 nearest found the list!";
cout << " ";
cout << " End Program 3" << endl;
return 0;
}
Ordered List:
OrderedPlayerList::OrderedPlayerList() { m_length = 0;
pFirst = NULL; // reflect the fact that there are no nodes in this List
pCurrent = NULL;
}
//------------------------------------------------------------------------
// isEmpty: bool
// returns true if the List is empty
//------------------------------------------------------------------------
bool OrderedPlayerList::isEmpty() { return pFirst == NULL; // use our List pointer now
}
//------------------------------------------------------------------------
// isFull: bool
// returns true if the List is full to capacity
//------------------------------------------------------------------------
bool OrderedPlayerList::isFull() { return false; // there is no more restriction on the size of the List!
}
//------------------------------------------------------------------------
// add(Player): bool
// attempts to add an item to the List. If the List is full return false,
// if successful, return true (true represents success)
// SORTED VERSION, now we need to find which nodes our new node must go between
//------------------------------------------------------------------------
bool OrderedPlayerList::add(Player newPlayer) // add a new item to the List
{ Node *pNew; // pointer to a new node
Node *p, *q; // our pointers that traverse the List looking for a spot to insert
pNew = new Node(newPlayer);
if (pNew == NULL) // then the allocate did not succeed which would be a critical memory failure!
{ return false; // did not succeed
}
// LOGIC TO STEP THROUGH THE NODES OF A SORTED List TO FIND AN INSERTION-----
// SPOT----------------------------------------------------------------------
p = pFirst;
q = NULL; // q will be 1 node prior to the one we are looking at
while (p != NULL && p->item.lessThan(newPlayer) ) // we are still looking for a spot
{ q = p; // save the node before the spot
p = p->pNext; // move over 1
}
// At this point, q points to the node before and p points to the node that needs to be after
// if q is null, this our new first node
if (q == NULL) { pNew->pNext = pFirst; // put our new node in front of pFirst
if (pFirst != NULL) { // PROG3 MOD: IF THERE IS ACTUALLY A NODE THERE, make it point back to our new node pFirst->pPrev = pNew;
}
pFirst = pNew; // then make our new node the new front of the List
}
else { q->pNext = pNew; // pNew comes after q
pNew->pPrev = q;
pNew->pNext = p; // and p comes after pNew
if (p) p->pPrev = pNew;
}
m_length++; // count it
return true; // add succeeded
}
//------------------------------------------------------------------------
// remove(Player d): bool
// locate and remove the given item from the list. If it is in there,
// we will have to relink the nodes and free the no longer needed node
//-------------------------------------------------------------------------
bool OrderedPlayerList::remove(Player player) // remove an item from the List
{ bool found = false; // return true if successfully removed a node, assume false to begin with
// find a node and remove it
Node *p; // node we are looking at
p = pFirst;
// PROG3 MOD: don't need q to follow. If p finds a node we can look back
found = false;
while (p != NULL && (!p->item.equals(player))) // as long as there is a node and it is not the one we are looking for
{ p = p->pNext; // move p over to the next node
}
if (p != NULL) // need to unlink the node p and free it
{ if (p->pPrev == NULL) { // if the node in front of p is NULL then we are removing the first node from the List pFirst = p->pNext;
delete p;
}
else { // p is not the first node in thie List, so p->pPrev->pNext = p->pNext;
if (p->pNext != NULL) { // PROG3 MOD: ahead to see if there is a node that needs to link back p->pNext->pPrev = p->pPrev;
}
delete p;
}
found = true;
}
m_length--;
return found;
}
//------------------------------------------------------------------------
// getSize: int
// return the internal length of the List, ie number of items stored
//------------------------------------------------------------------------
int OrderedPlayerList::getSize()
{ return m_length;
}
//------------------------------------------------------------------------
// resetToStart: void
// resets the internal iterator counter to the beginning of the List
//------------------------------------------------------------------------
void OrderedPlayerList::resetToStart() // sets the List iterator to the start of the List
{ pCurrent = pFirst; // copy the location of the first node into our iterator
}
//------------------------------------------------------------------------
// getNext: Player
// returns a copy of the next item in the List - as a parameter
// NOTE it is up to the user to check to see if there are more items
// when iterating!
// VERSION 2: MODIFIED to return a success status
//------------------------------------------------------------------------
bool OrderedPlayerList::getNext(Player &item) { bool success;
if (pCurrent != NULL) { // NEVER TRY TO ACCESS A NULL POINTER'S DATA! item = pCurrent->item; // copy the item stored into parameter, to pass back to caller
pCurrent = pCurrent->pNext; // move to next node in the linked List
success = true;
}
else
success = false;
return success;
}
//------------------------------------------------------------------------
// resetToEnd: void
// resets the internal iterator counter to the end of the List
//------------------------------------------------------------------------
void OrderedPlayerList::resetToEnd() // sets the List iterator to the start of the List
{ pCurrent = pFirst; // copy the location of the first node into our iterator
if (pFirst) { // if the list is not empty move to the end while (pCurrent->pNext != NULL) { pCurrent = pCurrent->pNext;
}
}
}
//------------------------------------------------------------------------
// getPrev: Player
// returns a copy of the prior item in the List - as a parameter
// ADDED with program 3 just because I felt like it
//------------------------------------------------------------------------
bool OrderedPlayerList::getPrev(Player &item) { bool success;
if (pCurrent != NULL) { // NEVER TRY TO ACCESS A NULL POINTER'S DATA! item = pCurrent->item; // copy the item stored into parameter, to pass back to caller
pCurrent = pCurrent->pPrev; // move backward in the doubly linked list
success = true;
}
else
success = false;
return success;
}
//------------------------------------------------------------------------
// clear: void
// Clears the MEMORY used up by our List.
// IMPORTANT: When working with dynamic memory allocation, it is ESSENTIAL that
// the user frees memory nodes when done!
// THIS IS A HANDY UTILITY FOR A DESTRUCTOR!
//------------------------------------------------------------------------
void OrderedPlayerList::clear() // sets the List iterator to the start of the List
{ Node *p, *q;
p = pFirst;
while (p != NULL) { q = p->pNext; // don't lose the link!
delete p; // free the node that p points to
p = q; // get ready to move over 1 node
}
pFirst = NULL;
pCurrent = NULL;
}
//------------------------------------------------------------------------
// locate : PROG3 MOD
// add a method to handle the new requirement
//------------------------------------------------------------------------
bool OrderedPlayerList::locate(string first, string last, ostream &out) { bool found = false;
bool notinlist = false;
Player temp;
temp.setFirstName(first); // let's use a temporary player object for comparisons
temp.setLastName(last);
Node *p, *q; // use p, q to search for the player in this list
p = pFirst; // start at beginning of list
q = NULL;
while (!found && p != NULL && !notinlist) { if (temp.equals(p->item))
found = true;
else if (temp.lessThan(p->item)) { // PROG3 MOD: we have gone past the location where our node should be!! notinlist = true;
}
else { q = p; // need this to know if we've gone off the end of a list
p = p->pNext;
}
}
if (found) { // PROG3 MOD p->item.Write(out);
}
else { // not in the list, but we should have stopped at nearest item or gone off the end of the list! if (p) { // make sure not null, print p and either the one before or after if (p->pPrev) { p->pPrev->item.Write(out);
p->item.Write(out);
}
else { p->item.Write(out);
if (p->pNext) p->pNext->item.Write(out);
}
}
else if (q) { // we went off the end of the list, but make sure there is actually at least 1 node there! if (q->pPrev) q->pPrev->item.Write(out);
q->item.Write(out);
}
else { // there appear to be no nodes in this list! out << "There appear to be no Players in your list.";
}
}
return found;
}
//------------------------------------------------------------------------
// ~OrderedPlayerList: Destructor
// Clears the MEMORY used up by our List. when theOrderedPlayerList is no
// longer in use
//------------------------------------------------------------------------
OrderedPlayerList::~OrderedPlayerList() { clear(); // use our utility
}
//------------------------------------------------------------------------
// dump: void
// Write a loop to step through the nodes in the List and print their
// items to the output stream
//------------------------------------------------------------------------
void OrderedPlayerList::dump(ostream &o)
{ // TODO: Exercise left for the student
}
Ordered List 2:
class Node { public:
Player item; // storage space for a Player
Node *pNext; // a pointer to the next dynamically allocated Node in the list
Node *pPrev; // a pointer to the prior node in the list
Node(const Player &player) // used to copy item into newly created nodes for our list
{ item = player;
pNext = NULL; // set link to a valid non-node value
pPrev = NULL;
}
};
class OrderedPlayerList { Node *pFirst; // a pointer that always points to the first item in the list
int m_length; // current length of the list (number of items stored)
Node *pCurrent; // used for iterations through the list
public:
// default constructors and destructor
OrderedPlayerList();
~OrderedPlayerList();
// public member functions
bool isEmpty();
bool isFull();
bool add(Player player); // add a player to the list
bool remove(Player player); // remove a player from the list
int getSize(); // returns the count of items stored in the list
void resetToStart(); // sets the list iterator to the start of the list
void resetToEnd(); // PROG3 MOD: maybe we want to iterate backwards
bool getNext(Player &); // gets a copy of the next item from the list when iterating
bool getPrev(Player &); // gets prev player when iterating backwards
void dump(ostream &); // dumps a list to an output stream, handy for printing everything, or debugging
void clear(); // utility to clear out a list and make it ready for new data
// PROG3: NEW FUNCTION
bool locate(string, string, ostream &); // use to find and print a player by first and last name or nearest 2
};
Player:
#include
#include
#include
#include "Player.h"
using namespace std;
// Default constructor - set player to predefined values
Player::Player() { // use the Initialize method since we have one
Initialize("unknown", "unknown", "tbd", 0.0); }
// copies data into the object with some simple formatting and
// data checking
void Player::Initialize(string first, string last, string pos, double avg)
{ m_firstName = first;
m_lastName = last;
m_position = pos;
if (avg < 0) avg = -avg; // at least try to correct
m_battingAverage = avg;
}
// define methods to read and write simple versions of player data
// to/from streams
// Read assumes the player's data is in the input stream in the format:
// firstname lastname position average with only spaces between the data
// no other separator characters are used. This will not work if a player's
// name has embedded spaces!
void Player::Read(istream &input) { char temp[100]; // using a temporary buffer to read input from stream
input >> temp;
m_firstName = temp;
input >> temp;
m_lastName = temp;
input >> temp;
m_position = temp;
input >> m_battingAverage;
}
// Write the Player data to an output stream with simple formatting
void Player::Write(ostream &out) { out << m_lastName << ", " << m_firstName << ": " << m_position;
out << fixed;
out << setprecision(3);
out << " (" << m_battingAverage << ") "; }
// define get/sets as needed
double Player::getBattingAverage() { return m_battingAverage; } string Player::getFirstName() { return m_firstName; } string Player::getLastName() { return m_lastName; } string Player::getFullName() { return m_firstName + " " + m_lastName; } string Player::getPosition() { return m_position; } void Player::setFirstName(string name) { m_firstName = name; } void Player::setLastName(string name) { m_lastName = name; } // lessThan function returns true if this Player is less than the one
// passed in (comparison done lastname, firstname)
// TBD - modify these to handle case-insensitive comparisons!
bool Player::lessThan(const Player &player) const
{ bool less;
if (m_lastName.compare(player.m_lastName) < 0) // less than is true
less = true;
else if (m_lastName.compare(player.m_lastName) == 0 && m_firstName.compare(player.m_firstName) < 0)
less = true;
else
less = false;
return less;
}
bool Player::equals(const Player &player) const
{ if (m_lastName.compare(player.m_lastName) == 0 && m_firstName.compare(player.m_firstName) == 0)
return true;
else
return false;
}
Player2:
#include
using namespace std;
class Player { string m_firstName; // player's first name
string m_lastName; // player's last name
string m_position; // player's primary position
double m_battingAverage; // batting average
public:
// Default Constructor
Player();
// copies data into the object with some simple formatting and
// data checking
void Initialize(string, string, string, double);
// define methods to read and write simple versions of player data
// to/from streams
void Read(istream&);
void Write(ostream&);
// define get/sets as needed
double getBattingAverage();
string getFirstName();
string getLastName();
string getFullName();
string getPosition();
void setFirstName(string);
void setLastName(string);
// added for maintaining ordered list by name
bool lessThan(const Player &player) const;
bool equals(const Player &player) const;
};
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
