Kelick Tech Hub

Build, learn & keep up — tech, Linux & sports news included.

C++ Expense Tracker Project

Intermediate•1–2 days•structs, aggregation, file I/O

Log spending by category and see where the money actually goes.

Share on X

What you will build

Record expenses with amounts and categories, then summarise: totals per category, biggest single expense, spending this month vs last. It's a data-aggregation exercise — grouping, summing, and presenting numbers so they change behaviour.

What you will learn

Feature checklist

Starter code

#include <iostream>
#include <fstream>
#include <map>
#include <string>

struct Expense { std::string date, category, note; double amount; };

int main() {
    std::map<std::string, double> byCategory;
    double total = 0, biggest = 0;
    std::string biggestWhat;

    std::ifstream in("expenses.txt");
    Expense e;
    while (in >> e.date >> e.category >> e.amount) {
        std::getline(in, e.note);
        byCategory[e.category] += e.amount;
        total += e.amount;
        if (e.amount > biggest) { biggest = e.amount; biggestWhat = e.category; }
    }

    std::cout << "Total spent: $" << total << "\nBy category:\n";
    for (const auto& [cat, sum] : byCategory)
        std::cout << "  " << cat << ": $" << sum
                  << " (" << (total ? 100.0 * sum / total : 0) << "%)\n";
    std::cout << "Biggest category splurge: " << biggestWhat
              << " $" << biggest << "\n";
}

Full walkthrough

Step 1: Model an expense as one struct

struct Expense { std::string date, category, note; double amount; } — one row of spending. All expenses live in a std::vector<Expense>. Dates stay text (YYYY-MM-DD) like the temperature logger, because the monthly view will slice them by prefix.

Step 2: Add entries with validation

Prompt for date, category, amount, note. Refuse amount <= 0 (a negative expense is a refund feature you did not design) and an empty category. Push to the vector and append to expenses.txt immediately — the now-familiar save-on-change rule.

Step 3: Total per category with a map

std::map<std::string, double> byCat; then for each expense, byCat[e.category] += e.amount. operator[] default-creates a 0.0 for a new category, which is exactly right here (contrast with the currency converter, where the same behaviour was a trap — context decides whether [] is a tool or a bug). The map prints categories alphabetically for free.

Step 4: Build the monthly summary by date prefix

A month is date.substr(0, 7). Filter expenses whose prefix matches the requested month, total them overall and per category with the same map trick. Because YYYY-MM-DD sorts lexicographically, string comparison IS chronological comparison — the format earns its keep again.

std::string month = e.date.substr(0, 7);
if (month == wanted) { total += e.amount; byCat[e.category] += e.amount; }

Step 5: Call out the largest expense

One pass tracking the maximum-amount Expense (store the whole record, not just the amount, so you can print its date, category, and note). Initialize from the first element and guard the empty list — same lesson as the temperature logger's highest reading.

Step 6: Delete a mistaken entry by number

List expenses with numbers, read the number, erase(begin + n - 1), then rewrite the whole file (append-mode cannot remove lines, so deletion switches the save strategy to full rewrite — a real design consequence worth noticing).

Step 7: Test against hand-added numbers

Enter Food 2500, Transport 1200, Food 800 for one month: overall 4500, Food 3300, Transport 1200, largest 'Food 2500'. Restart and confirm the same report — then delete the 800 entry and confirm Food drops to 2500 and the file agrees after another restart.

Common mistakes

Compile and run

g++ -std=c++17 -o expenses expenses.cpp

Sample run

$ ./expenses
Loaded 0 expenses.
1) Add  2) Totals  3) Monthly summary  4) Delete  0) Quit
> 1
Date, category, amount, note:
> 2026-10-21, Food, 2500, Market run
Saved.
1) Add  2) Totals  3) Monthly summary  4) Delete  0) Quit
> 1
Date, category, amount, note:
> 2026-10-22, Transport, 1200, Bus fares
Saved.
> 2026-10-22, Food, 800, Snacks
> 3
Month (YYYY-MM):
> 2026-10
Food: 3300.00 · Transport: 1200.00 · TOTAL: 4500.00
Largest expense: Food 2500.00 (Market run, 2026-10-21)
> 0

Try it in your browser

No browser demo is included for this project. Build the C++ version below — that is the real program.

Related Intermediate projects

← All 60 projects · Classic site (Learn & Sandbox)

Download Fake GPS