// Assignment 9 Solution 3/2020 #include #include #include #include #include using namespace std; class Node { string item; int count; Node* next; public: Node(const string& item = "", int cnt = 0, Node* nxt = nullptr); Node(const Node&) = delete; // disable the copy constructor (C++11 feature) string operator*() const; int get_count() const; Node* get_next() const; void set_next( Node* ptr); Node& operator=(const Node&) = delete; // disable the assignment operator (C++11 feature) Node& operator++(); // increment the count in a Node Node& operator--(); // decrement the count in a Node bool operator<(const string& value) const; }; class List { Node* top; public: List(); List(const List&) = delete; // disable the copy constructor (C++11 feature) ~List(); Node* get_top() const; Node* find(const string& value) const; Node* findNodeBefore(const string& value) const; List& operator=(const List&) = delete; // disable the assignment operator (C++11 feature) List& operator+=(const string&); // add to the linked list List& operator-=(const string&); // subtract from the linked list }; // Non-class member function prototypes void processTransactions(const string& filename, List& list); ostream& operator<<(ostream& out, const Node& n); ostream& operator<<(ostream& out, const List& l); int main() { List list; processTransactions("ass9data.txt",list); } ///// Node class member functions ///// void Node::set_next(Node* ptr) { next = ptr; } Node& Node::operator++() { count++; return *this; } Node& Node::operator--() { count--; return *this; } bool Node::operator<(const string& value) const { return item < value; } Node::Node(const string& arg1, int ct, Node* nxt) : item(arg1), count(ct), next(nxt) { } /* string Node::get_item() const { return item; } */ string Node::operator*() const { return item; } int Node::get_count() const { return count; } Node* Node::get_next() const { return next; } ostream& operator<<(ostream& out, const Node& n) { out << left << setw(12) << (*n); out << right << setw(4) << n.get_count(); return out; } ///// List class member functions ///// List::List() : top(nullptr) { } List::~List() { Node* temp = top; while (temp != nullptr) { top = top -> get_next(); delete temp; temp = top; } } Node* List::get_top() const { return top; } Node* List::find(const string& target) const { Node* temp = top; while (temp != nullptr) { if (**temp==target) return temp; temp = temp -> get_next(); } return nullptr; } // Return pointer to Node before the Node that contains target Node* List::findNodeBefore(const string& target) const { if (**top==target) return nullptr; Node* temp = top; while (temp->get_next() != nullptr) { if (**(temp->get_next()) == target) return temp; temp = temp->get_next(); } return nullptr; } List& List::operator+=(const string& value) { // Case 1: insert into an empty list if (!top) { top = new Node(value,1,nullptr); return *this; } // Case 2: Node already exists (increment count) Node* temp = find(value); if (temp) { ++*temp; // increment the count in the Node return *this; } // Case 3: Insert new node at the beginning of the list? if (value < **top) { temp = new Node(value,1,top); top = temp; return *this; } // Case 4: Insert new node after some node already in the list temp = top; // The temp pointer examines the "next" node value while (temp->get_next() && (*temp->get_next()) < value) { temp = temp -> get_next(); } // temp now points to the "target" node after which the new one will be inserted // Create the new node Node* newNode = new Node(value,1,temp->get_next()); // Set the next pointer of the target node to point to the new node temp->set_next(newNode); // return the linked list return *this; } List& List::operator-=(const string& value) { Node* temp = find(value); if (temp) { if (temp->get_count()>1) { --*temp; // decrement the count in the Node } else { if (temp == top) { top = top->get_next(); delete temp; temp = nullptr; return *this; } Node* ptr2Prev = findNodeBefore(value); if (ptr2Prev) { ptr2Prev->set_next(temp->get_next()); delete temp; temp = nullptr; } } } else { cerr << "Unable to remove " << value << endl; } return *this; } ////// Non-class member functions ////// void processTransactions(const string& filename, List& list) { ifstream fin(filename.c_str()); if (!fin) { cerr << "Unable to open file " << filename << endl; exit(1); } string buffer, transactionType, dummy, numberString; string item; int lineNumber = 0; size_t spacePos; // location of blank space in input line while (!fin.eof()) { lineNumber++; getline(fin,buffer); if (fin.eof()) break; // EOF check // A gnu/Mac compiler may store \r in the last byte. If so, discard if (buffer.size() && buffer[buffer.size()-1] == '\r') buffer.resize(buffer.size()-1); if (buffer.size() < 1) continue; // skip over blank line // get the first word of the line spacePos = buffer.find(' '); transactionType = buffer.substr(0,spacePos); if (transactionType == "add") { item = buffer.substr(spacePos+1); list += item; } else if (transactionType == "remove") { item = buffer.substr(spacePos+1); if (!list.find(item)) { cout << "Unable to " << buffer << " in line #" << lineNumber << endl; } else list -= item; } else if (buffer == "print list") { cout << list << endl; } else { cout << "Bad transaction: " << transactionType << " in line #" << lineNumber << endl; } } fin.close(); } ostream& operator<<(ostream& out, const List& l) { Node* temp = l.get_top(); out << endl << "Item Quantity" << endl; out << left; while (temp != nullptr) { out << *temp << endl; temp = temp -> get_next(); } return out; }