Question
Problem Statement How would you change the following program to re-implement the PlayerList data structure/data type that stores players using a doubly linked-list. Store the
Problem Statement
How would you change the following program to re-implement the PlayerList data structure/data type that stores players using a doubly linked-list. Store the players in the list in alphabetical order (By lastname, use firstname to further distinguish in the event there is more than 1 player with the same last name). In addition, you will need to add at least two new operations to support the following requirement:
We are going to use our player list as a sort of directory, or white pages of sorts. Prompt the user to look up a player by first and last name. If the player is found in the list, print out only that player's record. If the player is not found, you should print the two nearest players (the 1st one before and the1st one after) to the desired player. Note -in order for this to work, your operations are going to have to have some concept of where the search stops in the list (in the middle, at the end, etc). You can implement the printer operation as a method on the list so it has this information at its disposal.
Some Examples-Suppose I have the following players in my list
Hank Aaron
Andrew Jones
Chipper Jones
John Smith
Josh Thomas
If I search for Hank Aaron, only Hank Aaron should be displayed as found in the list.
If I search for Mark Jones, then Chipper Jones and John Smith should be displayed as two nearest to the desired information(before and after).
If I search for Jack Williams, then John Smith and Josh Thomas should be displayed.
Prompt the user to perform lookups until the user is ready to quit the program (i.e. use a while loop of some sort).
Here is what I have so far.
main.cpp fille
#include
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 PlayerList myList; // use to store the player list int i; // loop counter
// 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.resetToStart(); // get the list ready for iteration while (myList.getNext(currentPlayer)) // as long as getNext 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.find("Chipper", "Jones", currentPlayer)) { cout << "I found this player: "; currentPlayer.Write(cout); cout << endl; } else cout << "I could not find the requested player ";
if (myList.find("Mark", "Jones", currentPlayer)) { cout << "I found this player: "; currentPlayer.Write(cout); cout << endl; } else cout << "I could not find the requested player ";
cout << " End Program 2" << endl;
return 0; }
Player.h file
#include
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; };
Player.cpp file
#include
// 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; }
PlayerList.h file
#include
class Node { public: Player item; // storage space for a Player Node *pNext; // a pointer to the next dynamically allocated 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 } };
class PlayerList { 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 PlayerList(); ~PlayerList();
// 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 bool getNext(Player &); // gets a copy of the next item from the list when iterating 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
bool find(string, string, Player &); // use to find a player by first and last name };
PlayerList.cpp file
#include "PlayerList.h" using namespace std;
//------------------------------------------------------------------------ // Default constructor // NewOrderedPlayerList is created with the length set to 0 to reflect that no // items have been entered. //------------------------------------------------------------------------ PlayerList::PlayerList() { 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 PlayerList::isEmpty() { return pFirst == NULL; // use our List pointer now } //------------------------------------------------------------------------ // isFull: bool // returns true if the List is full to capacity //------------------------------------------------------------------------ bool PlayerList::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 PlayerList::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 pFirst = pNew; // and make our new node the new front of the List } else { q->pNext = pNew; // pNew comes after q pNew->pNext = p; // and p comes after 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 PlayerList::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 Node *q; // previous node right before p to enable us to unlink a node
p = pFirst; q = NULL; 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 { q = p; // save where we are now p = p->pNext; // move p over to the next node }
if (p != NULL) // need to unlink the node p and free it { if (q == 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 q->pNext = p->pNext; // reroute prior node link to the one after p delete p; } found = true; }
m_length--; return found; } //------------------------------------------------------------------------ // getSize: int // return the internal length of the List, ie number of items stored //------------------------------------------------------------------------ int PlayerList::getSize() { return m_length; } //------------------------------------------------------------------------ // resetToStart: void // resets the internal iterator counter to the beginning of the List //------------------------------------------------------------------------ void PlayerList::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 PlayerList::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; }
//------------------------------------------------------------------------ // 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 PlayerList::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; }
//------------------------------------------------------------------------ // find(string, string, Player): returns boolean // Given a first name and last name, this operation will provide a copy // of the player that matches. It will return a true/false status to indicate // success //------------------------------------------------------------------------ bool PlayerList::find(string first, string last, Player &foundPlayer) { bool found = false; Player temp; temp.setFirstName(first); // let's use a temporary player object for comparisons temp.setLastName(last);
Node *p; // use p to search for the player in this list p = pFirst; // start at beginning of list while (!found && p != NULL) { if (temp.equals(p->item)) found = true; else p = p->pNext; } if (found) { foundPlayer = p->item; // make a copy to pass out as parameter }
return found; }
//------------------------------------------------------------------------ // ~PlayerList: Destructor // Clears the MEMORY used up by our List. when theOrderedPlayerList is no // longer in use //------------------------------------------------------------------------ PlayerList::~PlayerList() { 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 PlayerList::dump(ostream &o) //To print the items in the list
{
Node *p, *q;
p = pFirst;// getting the first pointer in the list
int i=0; while (p != NULL) { q = p->pNext; //storing the next pointer
o<<"item no %d"<
o<
o<
o<
o<
o<<" "
i=i+1; p = q; }
}
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started