record-manager-solved/README.md
trevon 8c08fb626f
Some checks are pending
grade / grade (push) Waiting to run
push (solved)
2026-08-26 01:12:23 +00:00

100 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Record Manager — Instructor Reference Solution (M1M5)
**PRIVATE — never ships to students.** This is the reference implementation for
the Record Manager cumulative project (`assignments/projects/`), milestone by
milestone, plus the graded-interface contract and grading notes.
## Layout
```
include/record.h M1 record_t + record_new/free + status_t
include/buf.h M2 dynamic string buffer (+ readline)
include/list.h M3 opaque list_t + append/find/remove (+ len/get/sort helpers)
include/store.h M4 store_save / store_load (text file, '|' delimiter)
src/record.c M1 deep-copy record lifecycle
src/buf.c M2 growable buffer: append/appendc/cstr/reset/free/readline
src/list.c M3 singly linked list; remove frees node + record
src/store.c M4 one record per line; load appends + reports count
src/main.c M5 menu (add/list/search/delete/save/load/help/quit)
Makefile builds recman + recman_asan; `make test` runs unit + smoke
tests/unit.c direct tests of buf/list/store (links library sources)
tests/smoke.sh end-to-end CLI session
```
## Build + verify
```bash
make # recman
make asan # recman_asan (ASan+UBSan)
make test # unit + smoke, both under ASan/UBSan
```
Reference must be `-std=c17 -Wall -Wextra -Wpedantic -Werror` clean and report
`0 bytes lost` under Valgrind.
## Graded interface (what hidden tests touch)
`record_new`, `record_free`, `list_new`, `list_free`, `list_append`, `list_find`,
`list_remove`, `store_save`, `store_load` — exact signatures in
`assignments/projects/README.md`. This reference adds three non-graded helpers
(`list_len`, `list_get`, `list_sort`) that the menu and store layer need; they
are extra, not substitutes.
### Contract decisions (documented for graders)
- **`list_remove`**: returns `0` on success, `STATUS_ERR_NOTFOUND` when no record
matches, `STATUS_ERR_ARG` on NULL args. Frees the matching record + node.
- **`store_load`**: returns the **number of records read** (≥ 0) on success;
negative `status_t` on error. "0 on success" from the interface table is
satisfied when the file is empty/blank. It **appends** into the existing list.
- **Delimiter `|`**: none of the three flavors' fields (email/phone, assignment/
score, category/amount) can contain `|`; `name` may contain spaces — the
delimiter is safe across all flavors.
- **Empty fields**: saved as empty strings; loaded back as empty strings
(never NULL from `store_load`).
## Milestone-by-milestone notes
### M2 — dynamic string buffer (week 7)
Hidden tests likely: appends beyond initial capacity, `buf_cstr` NUL-termination
after every append, reset-then-reuse, `buf_readline` on a long line (>256 chars),
EOF/empty-line behavior. Sticky-OOM flag keeps the buffer usable after a failed
realloc. **Common mistake:** forgetting the `+1` for the NUL in `buf_grow`, or
realloc-ing to a shrinking capacity.
### M3 — linked list (week 11)
Hidden tests likely: append to empty list, find across many nodes, remove head /
remove middle / remove missing, `list_free` of a 3-node list under Valgrind
(0 lost), NULL-arg safety. **Common mistakes:** freeing the record and then
walking `next` (order matters — save `next` first); `list_remove` freeing the
node but not the record (double-free later); storing `record_t *` by value
instead of pointer.
### M4 — text file save/load (week 13)
Hidden tests likely: save→load round-trip preserves order + all three fields;
load into a non-empty list appends; file with blank lines; missing file returns
error, not crash; fields containing spaces survive (the `|` delimiter).
**Common mistakes:** assuming `fgets` succeeds; writing with `fprintf` and never
checking `ferror`; not stripping `\n`; `strtok` mangles empty fields (use
`strchr` splitting instead — empty field1/field2 must survive).
### M5 — refactor + search/sort + hardening (week 15)
Hidden tests likely: multi-file build with one `make`; case-insensitive
substring `search` across **all three** fields; `sort` alphabetical by name;
ASan/UBSan-clean; Valgrind 0 lost. **Common mistakes:** search matching only
`name`; sort comparing `record_t*` pointers instead of `->name`; `-Werror`
violations from unused includes after the refactor.
## Grading sanity checks
1. `make` from a clean tree (no build/ artifacts committed).
2. `make asan && ./build/recman_asan` → add 3 records → delete middle → save →
quit → reload → `list` shows the surviving two in order.
3. `valgrind --leak-check=full ./build/recman` with the same session → `0 bytes
lost` (the menu leaks nothing).
4. Feed the `tests/` fixtures: long input line (buf), 10k-record list (list),
save/load with spaces and empties (store).