Manuscript Database
Apologetic question: "Is the Bible reliable?"
Project 6 — Manuscript Database
“All Scripture is breathed out by God and profitable for teaching, for reproof, for correction, and for training in righteousness.” — 2 Timothy 3:16
Chapter: 6 — Collections: Arrays and Strings
Due: End of Week 6
Submit: A link to your code — an OnlineGDB project URL or a public GitHub repo URL — with manuscripts.cpp as the main source file. See Appendix D for the full workflow.
Allowed tools: Everything through Chapter 6 — types, conditionals, loops, functions, fixed-size arrays, strings, parallel arrays.
Not yet allowed: Structs (next week), classes, dynamic memory, vector.
The Setup
There is a question Christians your age are asked, sometimes politely and sometimes not: “Is the Bible reliable?” The answer has many layers — historical reliability of the events described, doctrinal coherence, the canon, manuscript transmission — but one of them is the question of textual transmission: do we have a credible record of what was originally written?
The empirical answer to that part of the question is unusual. For the New Testament, we have roughly 5,800 known Greek manuscripts, plus tens of thousands in Latin, Coptic, Syriac, Armenian, and Ge’ez. The earliest fragments (like Papyrus 52, John 18 — early-to-mid second century; the traditional dating is ca. AD 125, and more recent palaeographers like Nongbri argue the evidence supports anywhere in AD 125–225) sit within a handful of generations of the autographs. By comparison: Homer’s Iliad, the next-best-attested classical work, has about 1,700 manuscripts, the earliest more than 400 years after composition. After Homer, the manuscript counts drop into the hundreds. The data is real and the data is striking, regardless of what you make of it.
This project asks you to hold a small piece of that dataset in code. You will build a manuscript database — about a dozen real manuscripts, by name, with their approximate centuries and types — and operate on it: search, sort, filter, add, remove.
You’re not arguing the apologetic case in this program; you’re making the dataset legible to a human running your binary. That is enough.
Learning Targets
By completing this project, you will demonstrate that you can:
- Declare and use fixed-size arrays of strings and integers.
- Maintain a “count” variable that tracks how much of an array is in use.
- Implement add, remove, and linear search by hand.
- Sort an array of integers (or in parallel) with selection sort.
- Iterate with proper bounds (no off-by-one bugs).
- Parse and compare strings, including case-insensitive comparison.
Normal Tier
Goal: A menu-driven database of up to 20 manuscript names that supports adding, removing, listing, searching (case-insensitive), and exiting.
Required features
-
Storage: A fixed-size array
string manuscripts[MAX]withMAX = 20, plus anint count = 0tracking the number in use. -
Seed data: At program start, pre-populate the database with at least 5 real manuscripts. Recommended starter set (all real, look them up if curious):
P52(a fragment of John 18, early-to-mid 2nd century)Codex Sinaiticus(4th century, complete NT and most OT)Codex Vaticanus(4th century, most of the Bible)Codex Bezae(5th century, Gospels + Acts)Bodmer Papyri(3rd–4th century, several papyri)
-
Menu loop with at least these options:
1. Add a manuscript— prompts for name, adds if there’s room.2. Remove a manuscript— prompts for name, removes by shifting later entries down.3. List all manuscripts— prints all current entries, numbered.4. Search by name— prompts for a search term, prints all matches. Search must be case-insensitive.5. Exit— ends the program.
-
Bounds checking. Trying to add when full prints “Database full.” Trying to remove a non-existent entry prints “Not found.” Listing an empty database prints “(empty)”.
-
Functions, not inline code. Each operation (
add_manuscript,remove_manuscript,list_manuscripts,search_manuscripts) is its own function.mainis just the menu loop and dispatcher, like Project 5. -
Compiles cleanly with
-Wall -Wextraenabled in OnlineGDB compiler settings (org++ -Wall -Wextraif you build locally). No warnings, no errors.
Example interaction
=== Manuscript Database (5 entries) ===
1. Add a manuscript
2. Remove a manuscript
3. List all manuscripts
4. Search by name
5. Exit
Choice: 4
Search term: codex
Matches (3):
Codex Sinaiticus
Codex Vaticanus
Codex Bezae
Grading rubric — Normal (out of 100)
| Criterion | Points |
|---|---|
Compiles cleanly with -Wall -Wextra | 10 |
| Seeded with at least 5 real manuscripts | 10 |
add_manuscript works, rejects when full | 10 |
remove_manuscript works with shift-down, handles “not found” | 15 |
list_manuscripts prints numbered list | 10 |
search_manuscripts is case-insensitive and works | 15 |
| Menu loop dispatches correctly | 10 |
main is just menu + I/O — operations live in functions | 10 |
| No off-by-one bugs on bounds | 5 |
| OnlineGDB/GitHub link + reflection comment block | 5 |
Medium Tier (+up to 25% extra credit)
M1. Centuries (parallel arrays)
Add a parallel int centuries[MAX] array that holds the approximate century for each manuscript. Modify add_manuscript to also prompt for century. Modify list_manuscripts to print century alongside name. Modify remove_manuscript to shift the century array in lockstep with the name array.
Update the seed data with real centuries: P52 = 2, Sinaiticus = 4, Vaticanus = 4, Bezae = 5, Bodmer = 3.
M2. Search by century
Add a new menu option Search by century. Prompts for a century (int) and prints every manuscript matching that century.
M3. Sort by century (selection sort)
Add a menu option Sort by century. Implements selection sort, manually, on the centuries array — but swap in lockstep so the manuscripts array stays aligned.
Coach’s Note — Sorting two parallel arrays “together” is exactly the situation that proves parallel arrays are clunky. You have to remember to swap both whenever you swap either. Forget once and the two arrays drift apart and your data is now garbage. Next week we replace parallel arrays with a struct that bundles both fields, and this whole problem disappears.
M4. Reject duplicates
Modify add_manuscript to refuse duplicates. Case-insensitive: adding "codex sinaiticus" when "Codex Sinaiticus" already exists should be rejected with a clear message.
Hard Tier (+up to 25% additional extra credit)
The Hard tier introduces a third parallel array and a citation-builder.
H1. Manuscript type (third parallel array)
Add a third array — string types[MAX] — holding the manuscript’s type. Use these standard types (you don’t have to validate input, but use them in seed data):
papyrusuncialminusculelectionary
Update seed data: P52 = papyrus, Sinaiticus = uncial, Vaticanus = uncial, Bezae = uncial, Bodmer = papyrus.
Add a menu option Filter by type. Prompts for a type string, prints all matching manuscripts.
Update all your other operations (add, remove, sort) to keep all three arrays in lockstep.
H2. Citation builder
Add a menu option Generate citations. For each manuscript, print a canonical citation. Use these rules:
- If the name starts with
Pfollowed by a number (likeP52), print asPapyrus 52. - If the name starts with
Codex, print as the name itself:Codex Sinaiticus. - If the name is something else, print as the name itself.
You’ll need string parsing — .substr(), .find(), character comparison. Don’t use <algorithm> shortcuts; do the work by hand. The point is the string-manipulation rep.
H3. The flex move
Find one C++ feature for working with arrays or strings that we haven’t covered. Strong candidates:
std::sortfrom<algorithm>(and a custom comparator if you want extra credit on top of extra credit).std::vector<string>— the dynamic-size array we’ve been avoiding.getline(cin, line)for full-line input (so manuscript names can have spaces, which the current input scheme breaks).
The last one (getline) is actually quite useful here, since cin >> name chokes on multi-word names like “Codex Sinaiticus”. Look it up and add it.
Document per Project 1 H4 rules.
Submission
Submit one URL via the course portal:
- OnlineGDB project link (recommended for Coding 1 and Coding 2). Create your project at onlinegdb.com, set compiler flags to
-Wall -Wextrain the project settings, build your solution, and share the link. See Appendix D for the full workflow. - GitHub repo link (optional). If you’ve set up local development on your own, push the source to a public repo and submit that URL. You’re responsible for making sure the code compiles when the grader checks it out.
What the linked project must contain
- The main source file —
manuscripts.cpp— containing your full solution. - A reflection comment block at the very top of that file:
/*
* Tier targeted: Normal / Medium / Hard
* Features done: list each feature you completed
* What I learned: one short paragraph (no bullets)
* What I'd change: one sentence
* AI usage: where and how, if any. Be honest.
*/
- The program left in a “demonstrable” state — when the grader presses Run, the features for your targeted tier should be exercised. Hard-code inputs at the top of
main()(or pre-fill OnlineGDB’s Stdin panel) so the grader doesn’t have to guess what to type.
That’s it. No separate demo.txt. No screenshots. The instructor will open your link, read the comment block, run the program, and grade against the rubric.
Coach’s Note — Coding 1 and Coding 2 focus on writing code, not managing development environments. If something behaves oddly, you and the grader are looking at the exact same browser-hosted environment — there are no “works on my machine” defenses by design. Coding 3 will introduce a local toolchain properly.
Hints
- “My remove function leaves a hole in the array.” That’s correct until you shift everything down. After finding the target at index
i, dofor (int j = i; j < count - 1; j++) { arr[j] = arr[j + 1]; }. Then decrementcount. The hole gets filled by shifting. - “My search returns the wrong matches when the user types in different case.” Implement and use
to_lower(s)— see Chapter 6 §6.4 and Rep 7. Compare lowered versions. - “My multi-word manuscript names break input.”
cin >> namereads up to whitespace. For the project’s main flow, instruct the user to use underscores or quotation marks, or usegetline(cin, name). (If you mixcin >>andgetline, you may need a leadingcin.ignore();— see §6.4’s note oncin.ignore().) - “My parallel arrays got out of sync after I forgot to update one in
remove.” That’s the bug. That’s exactly the pain. Welcome to Chapter 6. Chapter 7 fixes it. - “How long should this take me?” Normal: 3–5 hours. Medium: 5–8 hours. Hard: 8–12 hours (the citation-builder and getline integration take real time).
What Mastery Looks Like
A great Project 6 has bounds-checked arrays. The add_manuscript function refuses to write past the end of the array. The remove_manuscript function fails gracefully on not-found. The grader can trigger every edge case without crashing your program.
A great Project 6 uses real data. Open the program, list the manuscripts, and a knowledgeable reader could verify every entry against a textbook or Wikipedia article. No "Cool Manuscript Tom Made Up". Names, centuries, types — all real.
A great Project 6 has a main function under 50 lines. The work happens in named functions. The dispatch in main is short, readable, and could be re-read by you in six months without confusion.
A great Project 6 prepares you for Chapter 7. The pain of keeping three parallel arrays in lockstep should be palpable in your code. Your README’s reflection should mention it. That’s the motivation that makes structs feel like a gift.
When You’re Done
- Read your
manuscripts.cppaloud. Each function does one thing. The names are verbs. The arrays are private to operations that should touch them. - Run a stress test: add 5 manuscripts, remove from the middle, add 3 more, sort by century, filter by type. Anything break?
- Update README.
- Submit.
- Read Chapter 7. Structs eliminate parallel arrays in one move.
Coach’s Note — Manuscript abundance is one of the most legible lines of evidence in any apologetic conversation, because the numbers don’t depend on disputed interpretive moves — they’re just counts and dates. The conversation immediately turns to “what’s the variant rate? what’s textually disputed?” — and the textual scholarship’s honest answer (lots of variants, none that change any doctrine) is its own story. But that conversation only begins after the data is on the table. You just put it on the table.
See you on Monday.