C++ Resume Builder (text-based) Project
Answer questions, get a cleanly formatted resume as a text file.
What you will build
The program interviews you — name, contact, education, jobs, skills — then typesets a tidy plain-text resume to a file. The work is in presentation: wrapping long text, aligning sections, and making fixed-width output look professionally composed.
What you will learn
- Collecting structured data section by section
- Writing formatted output to a file
- Text wrapping to a fixed width
- Reusable section rendering
Feature checklist
- Sections: contact, summary, education, experience, skills
- Multiple jobs/degrees with bullets
- Output: nicely formatted .txt resume
- Word-wrapped paragraphs at 80 columns
- Save the raw data so it can be edited and re-rendered
- Preview in console before saving
Starter code
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
struct Job { std::string title, company, dates; std::vector<std::string> bullets; };
struct Resume {
std::string name, email, phone, summary;
std::vector<Job> jobs;
std::vector<std::string> skills;
};
std::string wrap(const std::string& text, size_t width = 76) {
std::string out, line;
std::istringstream words(text); std::string w;
while (words >> w) {
if (line.size() + w.size() + 1 > width) { out += line + "\n"; line = w; }
else line += (line.empty() ? "" : " ") + w;
}
return out + line;
}
void render(const Resume& r, std::ostream& os) {
os << r.name << "\n" << r.email << " | " << r.phone << "\n";
os << std::string(60, '=') << "\nSUMMARY\n" << wrap(r.summary) << "\n\n";
os << "EXPERIENCE\n";
for (const auto& j : r.jobs) {
os << j.title << " — " << j.company << " (" << j.dates << ")\n";
for (const auto& b : j.bullets) os << " • " << wrap(b) << "\n";
}
os << "\nSKILLS\n";
for (size_t i = 0; i < r.skills.size(); ++i)
os << r.skills[i] << (i + 1 < r.skills.size() ? ", " : "\n");
}Full walkthrough
Step 1: Model the resume as nested data
struct Job { title, company, period, std::vector<std::string> bullets } and struct Resume { name, contact line, summary, education entries, std::vector<Job> jobs, std::vector<std::string> skills }. The resume is a tree of data; the builder collects it, render() prints it. Separating collection from rendering is what lets you re-render after an edit without re-typing everything.
Step 2: Collect input section by section
Prompt in document order — contact, summary, then loops for education and jobs ('Add a job, or press Enter on an empty title to finish'), bullets per job the same way, skills last. Empty-line-to-finish loops are the friendliest console pattern for variable-length input; learn it here and reuse it everywhere.
Step 3: Write wrap(): the one real algorithm
wrap(text, width = 80) breaks a paragraph into lines no longer than 80 chars, splitting at the LAST space before the limit — never mid-word. Walk a position pointer: if the remaining text fits, take it all; else find the last space within the window and cut there. Every 'nicely formatted text output' feature you will ever build contains this function.
std::vector<std::string> wrap(const std::string& s, int w) {
std::vector<std::string> lines;
size_t pos = 0;
while (pos < s.size()) {
if (pos + w >= s.size()) { lines.push_back(s.substr(pos)); break; }
size_t cut = s.rfind(' ', pos + w);
lines.push_back(s.substr(pos, cut - pos));
pos = cut + 1;
}
return lines;
}Step 4: render(): produce the document
render() writes to an std::ofstream: the name in caps, a rule line of '=' characters, section headings, wrapped summary paragraphs, jobs with indented wrapped bullets (' - ' prefix, continuation lines aligned). Fixed 80-column output is a deliberate retro constraint — it prints identically everywhere, including the preview.
Step 5: Preview before saving
Print render()'s output to the console first (render to a string or write to cout in a dry run), let the user look, then save to resume.txt on confirmation. Preview-then-commit is the same pattern as the library's fine check or the ATM's confirmations: never let the first time a user sees output be after it is permanent.
Step 6: Save the raw data, not just the render
Write the Resume fields to a data file (one field per line, jobs and bullets counted) so the user can reload, fix a typo, and re-render. Saving only the pretty .txt makes every edit a full retype — the checklist explicitly asks for editable data, and this is why.
Step 7: Test the wrap and the round-trip
Feed wrap() a paragraph with a word longer than 80 characters (a URL) and confirm nothing crashes (the fallback is a hard cut). Build a small resume, save, reload, re-render, and diff against the first render — they must be identical.
Common mistakes
- Wrapping by cutting at exactly 80 characters regardless of spaces, shredding words mid-syllable.
- Saving only the formatted .txt, so fixing one typo means re-entering the entire resume.
- Reading multi-word fields with std::cin >>, which stops at the first space and turns 'Software Engineer' into 'Software'.
Compile and run
g++ -std=c++17 -o resume resume.cppSample run
$ ./resume
Full name:
> Adaeze Obi
Contact line (email · phone · city):
> adaeze@example.com · 0803 555 0142 · Lagos
Summary:
> Computer Science graduate who builds small, honest tools in C++ and Python.
Job (title — company, period; empty to finish):
> Graphic Designer — Freelance, 2023 - present
Bullet (empty to finish):
> Designed brand kits for 12 small businesses
Skills (comma separated):
> C++, Python, Photoshop, Illustrator
ADAEZE OBI
SUMMARY
Computer Science graduate who builds small, honest tools in C++ and
Python.
EXPERIENCE
Graphic Designer — Freelance (2023 - present)
- Designed brand kits for 12 small businesses
Saved resume.txt (and resume_data.txt, so you can edit and re-render).Try it in your browser
No browser demo is included for this project. Build the C++ version below — that is the real program.