A comprehensive C++14 vending machine simulator demonstrating advanced software engineering principles including design patterns, custom data structures, and robust memory management.
This project implements a fully functional vending machine system from the ground up. Users can browse products, make purchases, and receive correct change, while the system manages stock, coins, and file persistence. The implementation emphasizes clean architecture through the Command Pattern, custom-built data structures (doubly-linked lists), comprehensive exception handling, and thorough testing.
- Browse Products - View all available items with prices
- Purchase Items - Select and buy items with automatic change calculation
- Dynamic Display Modes - View inventory in ascending/descending order (enhancement feature)
- Stock Management - Add, remove, and restock items
- Coin Management - Reset coin supplies and view current coin counts
- Persistence - All data saved to files for session continuity
- Safe Shutdown - Graceful exit with data preservation
- Custom Data Structures - Singly and doubly-linked lists built from scratch (not STL)
- Command Pattern Architecture - 8 command classes for operation encapsulation
- Modular Design - Easy to extend and maintain
- Exception Handling - 4 custom exception types for robust error management
- Memory Safe - Verified with Valgrind (zero leaks)
- 16+ Test Suites - Comprehensive automated testing with edge case coverage
The system uses the Command Pattern to encapsulate all user operations:
- Invoker:
Menuclass - Receives commands and executes them - Commands:
DisplayItem,PurchaseItem,Save,AddItem,RemoveItem,DisplayCoins,ResetStock,ResetCoins,Abort,ToggleEnhancement - Receiver:
VendingMachineclass - Performs the actual operations
This separation allows operations to be:
- Queued and executed
- Logged easily
- Undone/modified with minimal changes
- Tested independently
Data Structures:
LinkedList- Abstract base class defining interfaceLinkedListSingle- Singly-linked implementationLinkedListDouble- Doubly-linked implementation with reverse traversalNode/NodeD- Node types for single and double lists
System Management:
VendingMachine- Core system orchestratorMenu- Command invoker (handles user selections)Command- Abstract command base with 10 derived command classesCoin- Currency denomination managementHelper- Utility functions (file I/O, parsing, validation)ColorOutPut- Terminal color support for enhanced display
Data Models:
Stock- Represents a product (id, name, description, price, quantity)Price- Represents currency accurately (dollars + cents, not float)
Users can toggle between singly and doubly-linked list implementations at runtime:
- Singly-linked: Simpler, uses less memory
- Doubly-linked: Allows reverse traversal Both maintain identical data and behavior.
| Component | Requirement |
|---|---|
| Language | C++14 |
| Compiler | G++ (11.0+) or compatible |
| Build Tool | Makefile |
| Testing | Custom test suites |
| Memory Verification | Valgrind |
| Standard Library | STL (limited use) |
- G++ compiler (C++14 support)
- Make (optional but recommended)
- WSL/Linux environment or Windows with MinGW
Navigate to the startup_code directory:
cd startup_code
makeOr compile directly:
g++ -std=c++14 -o ppd ppd.cpp VendingMachine.cpp LinkedListDouble.cpp LinkedListSingle.cpp \
LinkedList.cpp Node.cpp Coin.cpp Command.cpp Menu.cpp Helper.cpp -Wall -WextraBasic usage with provided test data:
./ppd stock.dat coins.datWith custom data files (must follow same format):
./ppd [stock_file] [coins_file]stock.dat format:
I001,Donut,Glazed donut,199,15
I002,Coffee,Hot coffee,250,20
coins.dat format:
5,50
10,30
20,25
...
Check for memory leaks with Valgrind:
valgrind --leak-check=full ./ppd stock.dat coins.datExpected output: "definitely lost: 0 bytes"
The project includes 16+ automated test suites covering:
- Stock operations (add, remove, display)
- Purchase transactions (valid, invalid, exact change)
- Coin management (display, reset)
- Change calculation accuracy
- Edge cases (empty stock, insufficient funds, invalid input)
Located in: testFunctionality/ and testing/ directories
The interactive menu allows testing all features:
- Display items in ascending/descending order
- Attempt purchases with various coin amounts
- Admin operations (add/remove stock, reset)
- Toggle enhancement and verify list behavior
Uses a greedy algorithm with 8 coin denominations (1¢, 5¢, 10¢, 20¢, 50¢, $1, $2, $5) to return minimum coin count while ensuring exact change.
- stock.dat: Loaded on startup, updated on save
- coins.dat: Tracks coin inventory for change-making
- Both files validated on load with exception handling
Custom exceptions for:
- Invalid stock/coin files
- Insufficient coins for change
- Invalid user input
- Operation failures
Enhanced terminal display with color support (toggle with enhancement option) for better user experience.
startup_code/
├── ppd.cpp # Main entry point, command orchestration
├── VendingMachine.h/cpp # Core system logic
├── LinkedList.h/cpp # Abstract linked list interface
├── LinkedListSingle.h/cpp # Singly-linked implementation
├── LinkedListDouble.h/cpp # Doubly-linked implementation with reverse
├── Node.h/cpp # Node data structures
├── Command.h/cpp # Command pattern implementation (10 commands)
├── Menu.h/cpp # Command invoker
├── Coin.h/cpp # Coin denomination management
├── Helper.h/cpp # Utility functions
├── ColorOutPut.h # Terminal color support
├── stock.dat # Sample stock data
├── coins.dat # Sample coin data
├── Makefile # Build configuration
└── testing/ # Automated test suites (16+)
- Display Items → View all products with current stock
- Purchase Item → Select item ID and provide payment
- Receive Change → Automatic change calculation
- Add Item → Add new product to inventory
- Remove Item → Remove product by ID
- Display Coins → View coin supply
- Reset Stock → Restore stock to default levels
- Reset Coins → Restore coin supply to default levels
- Toggle Enhancement → Switch between list implementations
- Exit → Save and shutdown gracefully
- All dynamically allocated objects properly destructed
- No memory leaks (verified with Valgrind)
- Smart use of pointers for polymorphism (LinkedList* implementations)
- Clear separation of concerns
- Consistent naming conventions
- Comprehensive inline documentation
- Exception safety throughout
- Persistent transaction history
- Discount/promotion system
- Multiple currency support
- Networked vending capabilities
- GUI interface
Implementation: Ivan Tran
Testing: Andrew Djaja, Ivan Tran
Date: May 2023
Course: Advanced Programming Techniques, RMIT University
Academic use only - Part of RMIT University coursework