C++硬币钱包程序作业指导:Coin结构体与Purse类设计需求
Got it, let's walk through how to approach this design—since you're asking for guidance rather than a full copy-paste solution, I'll break down the key pieces you need to focus on.
Coin Struct First, your Coin needs two core pieces of data: a name (like "US Quarter" or "Euro Cent") and a monetary value. Since we're dealing with currency, use decimal instead of float/double—floating-point types have precision issues that can mess up money calculations.
Key Requirements for Coin:
- A constructor to initialize the name and value (add validation here! Don't allow empty names or negative values).
- A way to check if two
Coins are equal (both name and value must match).
Guidance on Equality Check:
Instead of just writing a custom method, implement the IEquatable<Coin> interface—it's type-safe and avoids unnecessary boxing. Don't forget to override GetHashCode() too, since equal objects must have the same hash code (critical if you use Coin as a key in a dictionary later).
Here's a skeleton to build on:
public struct Coin : IEquatable<Coin> { public string Name { get; } public decimal Value { get; } public Coin(string name, decimal value) { // Add validation: name can't be null/empty, value can't be negative if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Coin name can't be empty.", nameof(name)); if (value <= 0) throw new ArgumentOutOfRangeException(nameof(value), "Coin value must be positive."); Name = name; Value = value; } // Type-safe equality check public bool Equals(Coin other) { // Compare both name and value for equality return string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase) && Value == other.Value; // Note: Use OrdinalIgnoreCase if you want "Quarter" and "quarter" to be the same—adjust based on your needs } // Override base Equals to handle non-Coin objects public override bool Equals(object obj) { return obj is Coin coin && Equals(coin); } // Override GetHashCode to match Equals logic public override int GetHashCode() { return HashCode.Combine(Name, Value); } // Optional: Overload == and != operators for cleaner code public static bool operator ==(Coin left, Coin right) { return left.Equals(right); } public static bool operator !=(Coin left, Coin right) { return !left.Equals(right); } }
Purse Class Your Purse needs to store a collection of Coins along with their quantities. The best choice here is a Dictionary<Coin, int>—it lets you quickly look up if a Coin already exists in the purse, so you can either add a new entry or increment the quantity.
Core Requirements for Purse:
- An empty constructor to initialize the internal storage.
- A method to add a specified number of a given
Coin.
Guidance on the Add Method:
- Validate the input quantity: it must be a positive integer (no adding zero or negative coins!).
- Check if the
Coinis already in the dictionary: if yes, add the quantity to the existing count; if no, create a new entry.
Here's a skeleton for the Purse:
public class Purse { // Internal storage: key = Coin, value = number of that coin in the purse private readonly Dictionary<Coin, int> _coinInventory; // Empty purse constructor public Purse() { _coinInventory = new Dictionary<Coin, int>(); } // Method A: Add specified quantity of a Coin public void AddCoins(Coin coin, int quantity) { // Validate quantity first if (quantity <= 0) throw new ArgumentOutOfRangeException(nameof(quantity), "You must add a positive number of coins."); // Check if the coin is already in the purse if (_coinInventory.ContainsKey(coin)) { _coinInventory[coin] += quantity; } else { _coinInventory.Add(coin, quantity); } } // Optional: Add helper methods to extend functionality public decimal GetTotalValue() { decimal total = 0; foreach (var (coin, count) in _coinInventory) { total += coin.Value * count; } return total; } public int GetCoinCount(Coin coin) { _coinInventory.TryGetValue(coin, out int count); return count; } }
Extra Tips to Consider:
- Thread Safety: If your
Pursewill be used in multi-threaded code, add locks around dictionary operations to prevent race conditions. - Serialization: If you need to save/load the purse state, mark the
Coinstruct andPurseclass as serializable (or use JSON serialization libraries like Newtonsoft.Json). - Error Handling: Add more specific exceptions or validation as needed (e.g., what if someone tries to add a null
Coin?).
内容的提问来源于stack exchange,提问作者anon001

