Start learning free

LESSON 556 OF 568 · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

Inventory Item in C++: Private Stock and Validated Methods

Practice O(1) Read the full explanation

A shop keeps track of how many pieces of each item it has: the item's stock. The stock can never go below 0, and it changes only when pieces are sold or new ones arrive. So the stock is a private field, changed only through two methods that check the rules. The item's name has no rules to protect, so it stays a field any code can read.

Implement the class InventoryItem:

  • InventoryItem(name, stock) creates an item with that name and that many pieces in stock. The name is kept in a field name that other code can read.
  • sell(n) sells n pieces. If n is at least 1 and at most the stock, it lowers the stock by n and returns true. Otherwise it changes nothing and returns false: selling 0 pieces, a negative number of pieces, or more pieces than there are in stock is refused.
  • restock(n) adds n pieces to the stock when n is at least 1, and ignores n otherwise. It returns nothing.
  • getStock() returns the stock. It is the only way for other code to read it.

Keep the stock private the way the Access Modifiers lesson does in your language: self._stock in Python (private by convention), a #stock field in JavaScript, and the private keyword in Java, C++, C#, TypeScript, Kotlin, Scala and Swift. In Kotlin and Scala the constructor's second parameter is named initialStock, and the private stock starts at its value.

Each test case creates one item, then applies a list of operations to it, in order. The output has one line per test case: the item's name and a colon, then what each sell and getStock call returns, separated by spaces, with sell's answer printed as True or False. The starter code spells these names the way your language does: get_stock in Python, Sell, Restock and GetStock in C#.

 

Example 1:

Input:
    InventoryItem("Pencil", 5)
    sell(3)
    getStock()
    sell(5)
    getStock()
    restock(10)
    getStock()
Output: Pencil: True 2 False 2 12
Explanation: Selling 3 of the 5 pencils works and leaves 2. Selling 5 more is refused, because only 2 are left,
and the stock stays 2. restock(10) brings it to 12.

Example 2:

Input:
    InventoryItem("Mug", 4)
    sell(4)
    getStock()
    sell(1)
    getStock()
Output: Mug: True 0 False 0
Explanation: Selling all 4 mugs is allowed and leaves 0. With nothing left, even one mug can't be sold.

Example 3:

Input:
    InventoryItem("Lamp", 2)
    sell(0)
    sell(-3)
    restock(0)
    restock(-5)
    getStock()
    restock(1)
    sell(3)
    getStock()
Output: Lamp: False False 2 True 0
Explanation: Selling 0 or -3 lamps is refused, and restocking 0 or -5 lamps is ignored, so the stock is still 2.
After restock(1) there are 3 lamps, and selling all 3 works.

 

Constraints:

  • A name is one word of English letters. 0 <= stock <= 104 when the item is created.
  • -104 <= n <= 104 in every sell and restock.
  • A test case has from 1 to 1000 operations, and at least one of them is a sell or a getStock.
STEP 1 OF 7
    Ctrl + Enter to check

    C++ · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

    Inventory Item in C++, explained

    Problem overview

    A shop keeps track of how many pieces of each item it has: the item's stock. The stock can never go below 0, and it changes only when pieces are sold or new ones arrive. So the stock is a private field, changed only through two methods that check the rules. The item's name has no rules to protect, so it stays a public field any code can read.

    The class InventoryItem has these members:

    • InventoryItem(name, stock) creates an item with that name and that many pieces in stock.
    • sell(n) sells n pieces. If n is at least 1 and at most the stock, it lowers the stock by n and returns true. Otherwise it changes nothing and returns false: selling 0 pieces, a negative number or more than the stock is refused.
    • restock(n) adds n pieces when n is at least 1 and ignores n otherwise. It returns nothing.
    • getStock() returns the stock, the only way for other code to read it.

    For a pencil item with stock 5, sell(3) returns true and leaves 2. Then sell(5) is refused because only 2 are left, and the stock stays 2. After restock(10) it is 12.

    Approach

    Each method protects the rule "the stock is never negative" by checking its input before changing anything. In sell, the invalid cases are n below 1 and n above the stock; everything else is a valid sale. Checking first and returning early means a refused sale leaves the stock exactly as it was. Note that n equal to the stock is valid: the shop may sell everything it has. In restock, a delivery of 0 or a negative number isn't a delivery, so it is ignored.

    Because stock is private, no other code can skip these checks. Every method is a few comparisons, so each runs in constant time.

    Step by step

    1. Declare the stock as int stock; in the private: section. Only the class's own methods can change it.
    2. Declare the name as string name; in the public: section. It has no rule to protect, so other code may read it directly.
    3. Store both parameters in the constructor with this->name = name; and this->stock = stock;. The parameters share the fields' names, so this-> picks the fields.
    4. In sell, refuse what can't be sold. Write an if for n < 1 || n > stock whose body returns false. The check comes before any change.
    5. Complete the sale. After the if, subtract n from stock and return true. Only a sale that passed the check gets here, so the stock never goes below 0.
    6. In restock, add n to stock only when n >= 1.
    7. getStock() returns stock. Other code can see the number but can never set it.

    The solution in C++

    class InventoryItem {
    private:
        int stock;
    public:
        string name;
    
        InventoryItem(string name, int stock) {
            this->name = name;
            this->stock = stock;
        }
    
        bool sell(int n) {
            if (n < 1 || n > stock) {
                return false;
            }
            stock -= n;
            return true;
        }
    
        void restock(int n) {
            if (n >= 1) {
                stock += n;
            }
        }
    
        int getStock() {
            return stock;
        }
    };

    A run

    This runs the first and third examples. A bool prints as 1 or 0 unless boolalpha is set, so the program turns it on to print true and false.

    #include <iostream>
    #include <string>
    using namespace std;
    
    // the class above goes here
    int main() {
        cout << boolalpha;
    
        InventoryItem pencil("Pencil", 5);
        cout << pencil.name << ": " << pencil.sell(3) << " " << pencil.getStock() << " ";
        cout << pencil.sell(5) << " " << pencil.getStock() << " ";
        pencil.restock(10);
        cout << pencil.getStock() << endl;
    
        InventoryItem lamp("Lamp", 2);
        cout << lamp.name << ": " << lamp.sell(0) << " " << lamp.sell(-3) << " ";
        lamp.restock(0);
        lamp.restock(-5);
        cout << lamp.getStock() << " ";
        lamp.restock(1);
        cout << lamp.sell(3) << " " << lamp.getStock() << endl;
    }

    It prints:

    Pencil: true 2 false 2 12
    Lamp: false false 2 true 0

    The first line shows a normal sale, then a refused one because only 2 pencils are left, and the stock stays 2 after it. The second line shows the lamps: selling 0, selling -3 and selling 3 of 2 are all refused. The stock is still 2 after restock(0) and restock(-5), which are ignored. Then restock(1) makes it 3, and selling all 3 works and leaves 0.

    Details worth knowing

    • The order of the two conditions. n < 1 || n > stock is true if either part is true, so one if covers all three refused cases. The || stops as soon as the left side is true, which doesn't matter here but is the usual behaviour.
    • Private and public together. Members after private: are hidden and members after public: are open. Here stock is hidden and name is open. Writing item.stock = -5 from outside the class is a compile error, while item.name reads fine.
    • The return value of sell tells the caller whether the sale happened. Without it the caller would have to compare the stock before and after.
    • restock returns nothing (void): there is no failure to report, since an invalid delivery is simply ignored.

    Common mistakes

    • Using n >= stock as the refusal test. That would refuse selling exactly all the pieces, which the rules allow.
    • Forgetting the n < 1 part, so selling a negative number would add to the stock.
    • Subtracting first and checking afterwards. A refused sale must leave the stock unchanged.
    • Using && instead of || in the refusal test. No number is both below 1 and above the stock, so nothing would ever be refused.
    • Putting the stock under public:, which lets other code skip the checks.
    Keep going with C++500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free