#include <cstddef>
#include <iostream>
#include <string>
// ------ Grocery.hpp ------
struct Grocery
{
std::string name;
std::size_t quantity;
Grocery* next;
Grocery(std::string name, std::size_t quantity)
: name(name)
, quantity(quantity)
{}
};
namespace
{
std::ostream& operator<<(std::ostream& out, Grocery const& obj)
{
return out << obj.name << ", " << obj.quantity;
}
}
// ------ GroceryList.hpp ------
class LinkedGroceryList
{
private:
Grocery* head;
Grocery* tail;
std::size_t numGroceries;
std::size_t quantitySum;
public:
LinkedGroceryList();
~LinkedGroceryList();
void addGrocery(Grocery const& grocery);
void removeGrocery(Grocery const& grocery);
std::size_t different() const { return numGroceries; }
std::size_t total() const { return quantitySum; }
bool empty() const { return quantitySum == 0; }
friend std::ostream& operator<<(std::ostream& out, LinkedGroceryList const& obj);
};
// ------ GroceryList.cpp ------
LinkedGroceryList::LinkedGroceryList()
: head(nullptr)
, tail(nullptr)
, numGroceries(0)
, quantitySum(0)
{}
LinkedGroceryList::~LinkedGroceryList()
{
Grocery *predPtr = head;
Grocery *nextGrocery;
while (predPtr)
{
nextGrocery = predPtr->next;
delete predPtr;
predPtr = nextGrocery;
}
}
void LinkedGroceryList::addGrocery(Grocery const& grocery)
{
Grocery* newGrocery = new Grocery(grocery.name, grocery.quantity);
newGrocery->next = nullptr;
if (empty())
{
head = tail = newGrocery;
}
else
{
tail->next = newGrocery;
tail = newGrocery;
}
numGroceries++;
quantitySum += grocery.quantity;
}
void LinkedGroceryList::removeGrocery(Grocery const& grocery)
{
if (!head) return;
Grocery* groceryPtr;
if (head->name == grocery.name)
{
groceryPtr = head;
head = groceryPtr->next;
quantitySum -= grocery.quantity;
if (grocery.quantity == groceryPtr->quantity)
numGroceries--;
else
{
groceryPtr->quantity -= grocery.quantity;
return;
}
delete groceryPtr;
}
else
{
Grocery* predPtr = nullptr;
groceryPtr = head;
while (groceryPtr && groceryPtr->name != grocery.name)
{
predPtr = groceryPtr;
groceryPtr = groceryPtr->next;
}
if (groceryPtr)
{
quantitySum -= grocery.quantity;
if (grocery.quantity == groceryPtr->quantity)
numGroceries--;
else
{
groceryPtr->quantity -= grocery.quantity;
return;
}
predPtr->next = groceryPtr->next;
delete groceryPtr;
}
}
}
std::ostream& operator<<(std::ostream& out, LinkedGroceryList const& obj)
{
for (Grocery* grocery = obj.head; grocery; grocery = grocery->next)
{
out << *grocery << "\n";
}
return out;
}
// ------ Driver ------
int main()
{
LinkedGroceryList meats;
meats.addGrocery(Grocery("steak", 5));
meats.addGrocery(Grocery("chicken", 3));
meats.addGrocery(Grocery("pork", 2));
std::cout << meats;
std::cout << "\nDifferent items: " << meats.different() << "\n";
std::cout << "Total items: " << meats.total();
std::cout << "\n\nRemoving 1 pork...\n\n";
meats.removeGrocery(Grocery("pork", 1));
std::cout << meats;
std::cout << "\nDifferent items: " << meats.different() << "\n";
std::cout << "Total items: " << meats.total();
}