CASE STUDY 02 · C PROGRAMMING

Advanced Linked-list application

Inventory & Reorder Management

Build a store inventory that manages stock transactions, prevents impossible sales, calculates asset value and identifies products requiring replenishment.

01 · PROBLEM DEFINITION

Turn stock data into useful decisions

A small store must know what it owns, what can be sold and what must be reordered. A simple quantity variable is insufficient because every product has its own identity, price and safe-stock threshold. This case study models each product as a dynamically allocated node and derives operational reports from the current list.

Transaction

Receive or sell a positive number of units.

Control

Reject duplicate IDs, negative values and sales above available stock.

Decision

Flag quantity ≤ reorder level and calculate inventory value.

Engineering question: How do we keep an ordered collection whose size is unknown until runtime?
02 · BUSINESS RULES

Convert real-world policy into conditions

RuleConditionSystem response
Unique identityNo existing node has the same product IDReject duplicate Add
Valid master dataID > 0; text not empty; numeric fields ≥ 0Do not allocate a node
Valid transactionUnits > 0Reject zero/negative movement
No negative stocksale units ≤ current quantityReject impossible sale
Reorder alertquantity ≤ reorderLevelShow REORDER REQUIRED
Valuationvalue = quantity × unitPriceSum across displayed products
Boundary insight: Reordering starts at equality, not only below the threshold. If quantity is exactly the reorder level, procurement should act.
03 · DATA MODEL

A self-referential Product structure

Product = { id, name, quantity, reorderLevel, unitPrice, *next }

The first five members describe the product. next connects one dynamically allocated record to another. The variable inventory stores only the address of the first node.

head
inventory
101 · Keyboard
qty 12
205 · Mouse
qty 4
310 · Monitor
qty 8
NULL

Why keep IDs sorted?

Sorted insertion gives reports a stable, readable order without calling a separate sort. Search remains O(n), but deterministic output helps testing and auditing.

04 · POINTER & MEMORY DESIGN

Ownership rules prevent leaks

Allocation ownership

newProduct allocates one node. After successful insertion, the list owns it. If insertion fails, the caller frees it.

Shutdown ownership

freeInventory walks the list, remembers next, frees current, then advances.

Pointer-to-pointer insertion

Product **current represents “the link that must change”. It may be the head pointer or a node’s next field. This removes the usual special case for insertion at the beginning.

while (*current != NULL && (*current)->id < item->id)
    current = &(*current)->next;
item->next = *current;
*current = item;
After insertion, the invariants are: every node is reachable from head, IDs remain ascending, and the final next pointer is NULL.
05 · ALGORITHMS

Operations and state transitions

Record a sale

  1. Read product ID and positive unit count.
  2. Traverse until the ID matches or the list ends.
  3. Reject if the product is absent or requested units exceed quantity.
  4. Subtract units and calculate transaction value.
  5. Compare new quantity with the reorder threshold.

Generate reorder report

  1. Begin at head and initialise displayed count to zero.
  2. For each node, test quantity <= reorderLevel.
  3. Print matching nodes and accumulate their current stock value.
  4. Report “No products need reordering” if count remains zero.

Persistence cycle

Program starts
Parse inventory.txt
Operate on linked list
Write all nodes
Free memory
06 · COMPLETE IMPLEMENTATION

Compiler-ready C11 program

This implementation uses a human-readable pipe-delimited text file. Names may contain spaces, but the pipe character is reserved as the field separator.

programs/inventory-reorder-system.c
Open Compiler
Loading source…
Online compiler note: The text file exists only for the current running process/environment. Use Download to keep your source code; a production deployment needs durable storage.
07 · INTERACTIVE PROGRAM TRACING

Trace: add two products and sell stock

  1. Program begins with an empty list.
  2. First product data passes validation.
  3. Product 205 is allocated.
  4. 205 becomes the head.
  5. Second product is created.
  6. Sorted insertion changes the head.
  7. Sale targets Mouse.
  8. Stock is safely reduced.
  9. Boundary threshold triggers alert.
  10. Exit persists and cleans memory.
Current state

Press Next to begin.

08 · TEST STRATEGY

Protect every business rule

Test 1 — Sorted insertion
Add IDs 205, 101 and 310. Full report must display 101, 205, 310 regardless of insertion order.
Test 2 — Duplicate product
Add ID 205 twice. The second operation must not allocate or insert another node.
Test 3 — Exact-stock sale
With quantity 7, sell 7. Expected new quantity is zero, sale succeeds and reorder alert appears.
Test 4 — Insufficient stock
With quantity 4, request sale of 5. Expected rejection and quantity remains 4.
Test 5 — Threshold boundary
Set reorder level 4 and reduce quantity to exactly 4. The item must appear in the reorder report.
Test 6 — Persistence round trip
Save, restart and generate full report. IDs, names, quantities, levels and prices must match the saved state.
09 · COMPLEXITY & TRADE-OFFS

Performance of the linked-list design

OperationTimeExtra RAMTrade-off
Find productO(n)O(1)No random access
Sorted insertionO(n)O(1)Reports stay ordered
Receive/sell stockO(n)O(1)Search dominates
Full/reorder reportO(n)O(1)Every node may be checked
Load or saveO(n)O(n)All nodes live in memory
Free listO(n)O(1)Every allocation released once
Alternative: An array gives cache-friendly access but needs capacity management and O(n) movement for sorted insertion. A hash table improves average lookup but does not naturally preserve report order.
10 · PRACTICE & EXTENSIONS

Test your reasoning

Why does addProduct receive Product **head?

Which condition correctly triggers reordering?

Build the next version

  1. Add product removal and prove that head/middle/tail deletion all work.
  2. Record every stock movement in a separate transaction log.
  3. Add category and supplier fields and generate category-wise value.
  4. Calculate recommended order quantity from maximum stock and current quantity.
  5. Replace linear lookup with a hash index while retaining the ordered list for reports.
11 · INTERVIEW PREPARATION

Questions your project should answer

Why choose a linked list?

The number of products is unknown at compile time. Nodes can be added without resizing a contiguous array, and pointer relinking supports insertion/removal without shifting records.

What causes a memory leak here?

Losing the only pointer to an allocated node or exiting without traversing and freeing the list. The ownership rules and freeInventory prevent both.

Why is fscanf with unrestricted %s unsafe?

It can overflow an array and stops at spaces. The program reads bounded lines and uses a width-limited scanset while loading the delimiter-based file.

How do you preserve list order?

insertSorted walks pointer links until the first larger ID, connects the new node to that position and then redirects the preceding link to the new node.

How would two cashiers use this safely?

This version cannot safely handle concurrent writers. A real system needs transactions, file/database locking and conflict handling, preferably through a database service.

12 · KEY TAKEAWAY

Data structures become valuable through business rules

The linked list is not the final goal. It is the mechanism that supports unknown inventory size. The real system emerges when pointer correctness is combined with validation, stock invariants, reports, persistence and complete memory cleanup.