C++ Tutorial
C++ Project: Library Catalog
A catalog of books with title, author, and year. Search by author and list every match.
What you will build
A catalog is a vector of books. Each book has a title, an author, and a year. You print the full shelf, then search by author and list every match. Search uses string::find so a last name can match inside a longer author field.
The shelf is hardcoded. Compile with Try it in C++ at /cpp/try. This is C++17, not a Python script and not an HTML page.
A Book struct
Three fields travel together. Title and author are strings. Year is an int. Printing one book is a single function so the catalog loop stays short.
Example
#include <iostream>
#include <string>
using namespace std;
struct Book {
string title;
string author;
int year;
};
void printBook(const Book& b) {
cout << b.title << " — " << b.author << " (" << b.year << ")" << endl;
}
int main() {
Book b;
b.title = "The C++ Programming Language";
b.author = "Bjarne Stroustrup";
b.year = 2013;
printBook(b);
return 0;
}Fill a catalog
vector<Book> grows with push_back. A range-for prints every row. Pass the catalog by const reference into the print helper.
Example
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Book {
string title;
string author;
int year;
};
void printBook(const Book& b) {
cout << b.title << " — " << b.author << " (" << b.year << ")" << endl;
}
void printCatalog(const vector<Book>& shelf) {
cout << "Catalog (" << shelf.size() << " books)" << endl;
for (const Book& b : shelf) {
printBook(b);
}
}
int main() {
vector<Book> shelf;
shelf.push_back({"The C++ Programming Language", "Bjarne Stroustrup", 2013});
shelf.push_back({"Effective Modern C++", "Scott Meyers", 2014});
shelf.push_back({"A Tour of C++", "Bjarne Stroustrup", 2022});
printCatalog(shelf);
return 0;
}Run the catalog at /cpp/try via Try it in C++. Two titles share an author. That pair is what the search in the next sections must return.
Search with find
author.find(query) returns the index of the first match, or string::npos if the query is not a substring. A query of Stroustrup matches Bjarne Stroustrup. An empty query matching every book is possible with find; this project treats an empty query as no hits so a blank search does not dump the shelf.
Example
#include <iostream>
#include <string>
using namespace std;
int main() {
string author = "Bjarne Stroustrup";
string query = "Stroustrup";
if (author.find(query) != string::npos) {
cout << "match" << endl;
} else {
cout << "no match" << endl;
}
return 0;
}Complete catalog program
Walk the vector. When the author field contains the query, print that book and count it. After the loop, print how many matches you found. Two searches run in main: one that hits twice, one that hits none.
Example
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Book {
string title;
string author;
int year;
};
void printBook(const Book& b) {
cout << b.title << " — " << b.author << " (" << b.year << ")" << endl;
}
void searchByAuthor(const vector<Book>& shelf, const string& query) {
cout << "Search author: " << query << endl;
if (query.empty()) {
cout << "Empty query, 0 matches" << endl;
return;
}
int hits = 0;
for (const Book& b : shelf) {
if (b.author.find(query) != string::npos) {
printBook(b);
hits = hits + 1;
}
}
cout << hits << " match(es)" << endl;
}
int main() {
vector<Book> shelf;
shelf.push_back({"The C++ Programming Language", "Bjarne Stroustrup", 2013});
shelf.push_back({"Effective Modern C++", "Scott Meyers", 2014});
shelf.push_back({"A Tour of C++", "Bjarne Stroustrup", 2022});
shelf.push_back({"C++ Primer", "Stanley Lippman", 2012});
cout << "All books" << endl;
for (const Book& b : shelf) {
printBook(b);
}
cout << endl;
searchByAuthor(shelf, "Stroustrup");
cout << endl;
searchByAuthor(shelf, "Ada");
return 0;
}The Stroustrup search prints two titles and 2 match(es). The Ada search prints0 match(es). Search is case-sensitive: stroustrup would miss these rows.
Common mistakes
- Comparing authors with
==only. ThenStroustrupfails againstBjarne Stroustrup. Usefindwhen you want a substring. - Testing
findagainst0. A match at the start of the string is index 0, which is a hit. The miss value isstring::npos. - Forgetting to count hits. Printing books without a total makes an empty result look like a crashed loop.
- Storing year as a string. Numeric year lets you add a filter such as “after 2015” later without parsing.
Practice
- Add a search-by-title function that also uses
find. - Print only books with
year >= 2014. - If two books share a title, print both; do not stop at the first hit.
Next project: convert Celsius, Fahrenheit, and Kelvin with formatted output.