C++ Railway Reservation System Project
Book train seats, manage waitlists, and cancel with automatic promotion.
What you will build
Trains with fixed seats, passengers booking and cancelling, and a waitlist that promotes the next person the moment a seat frees up. The waitlist logic — a queue with fair promotion — is the beating heart of every booking system on earth.
What you will learn
- Queues (std::queue) for waitlists
- Modelling trains, seats, and bookings as classes
- Cancellation with automatic waitlist promotion
- PNR-style booking references
Feature checklist
- Add trains with route, time, and seat capacity
- Book a seat: confirmed or waitlisted
- Cancel a booking; first waitlisted passenger is promoted
- Booking lookup by reference code
- Chart of a train: confirmed / waitlist counts
- Data persists in files
Starter code
#include <iostream>
#include <queue>
#include <string>
struct Booking { std::string pnr, passenger; bool confirmed; };
class Train {
std::string name_, route_;
int seatsLeft_;
std::queue<Booking> waitlist_;
public:
Train(std::string n, std::string r, int seats)
: name_(std::move(n)), route_(std::move(r)), seatsLeft_(seats) {}
Booking book(const std::string& passenger, const std::string& pnr) {
if (seatsLeft_ > 0) {
--seatsLeft_;
return {pnr, passenger, true};
}
Booking b{pnr, passenger, false};
waitlist_.push(b);
return b;
}
// Returns the promoted passenger's name, or "" if nobody waited.
std::string cancel() {
++seatsLeft_;
if (waitlist_.empty()) return "";
Booking next = waitlist_.front(); waitlist_.pop();
--seatsLeft_;
return next.passenger; // this passenger is now confirmed
}
int seatsLeft() const { return seatsLeft_; }
size_t waiting() const { return waitlist_.size(); }
};Full walkthrough
Step 1: Model Train and Booking separately
struct Train { id, name, from, to, time, capacity } is the static offer; struct Booking { ref, trainId, passenger, status } is one person's claim on it, where status is CONFIRMED or WAITLISTED. class TrainSystem (or the starter's design) owns vectors of both. The reference code — a short unique string like 'BK7F3' — is generated per booking so passengers can look theirs up without an ID number.
Step 2: book(): capacity is counted, never stored
Count existing CONFIRMED bookings for the train: below capacity → the new booking is CONFIRMED; at capacity → it joins the waitlist (a std::queue of booking refs, or the bookings vector filtered by status and order). Deriving the count from the bookings list keeps one source of truth — the recurring theme of this whole level of the catalogue.
Status book(...) {
if (confirmedCount(trainId) < train.capacity)
return Status::Confirmed;
return Status::Waitlisted; // FIFO order preserved
}Step 3: cancel(): where the waitlist earns its keep
Find the booking by ref, mark it cancelled and remove it. If it was CONFIRMED, a seat just freed: promote the FIRST waitlisted booking for that train to CONFIRMED and say who got promoted. FIFO order is a fairness promise — promote out of order and your system is technically correct and socially broken.
Step 4: Look up bookings by reference code
A linear search over bookings by ref prints the passenger, train, route, and live status. Note 'live': a waitlisted booking may have been promoted since it was made, so always report the CURRENT status from the record, never a status cached at booking time.
Step 5: Print the train chart
For one train: capacity, confirmed count, waitlist count, and the passenger list in order. This is the report conductors print — building it forces your derived counts and your promotion logic to agree in public, which is exactly the kind of consistency check you want before calling the project done.
Step 6: Add trains through an admin path
Admins add trains (route, departure time as text, seat capacity) which are saved alongside bookings. Times as strings are fine here — the system never subtracts them, it only displays them (the same type-choice reasoning as the temperature logger's dates).
Step 7: Test the promotion story end-to-end
Create a train with capacity 2. Book three passengers: first two CONFIRMED, third WAITLISTED #1. Cancel the first booking: the third passenger must be promoted automatically and the chart must read 2 confirmed, 0 waitlisted. That single story exercises book, cancel, promotion, and reporting together.
Common mistakes
- Storing a 'seatsLeft' counter that promotions and cancellations must remember to adjust — it will drift; count confirmed bookings instead.
- Promoting the newest waitlisted booking (or a random one) instead of the first — the queue order IS the product.
- Deleting cancelled bookings outright, so reference lookups and audit history lose the record; mark the status instead.
Compile and run
g++ -std=c++17 -o railway railway.cppSample run
$ ./railway
1) Book 2) Cancel 3) My booking 4) Train chart 0) Exit
> 1
Passenger name:
> Ada Lovelace
Booked! Ref BK7F3 — CONFIRMED (T100 Lagos -> Ibadan 07:30, 1 seat left)
> 1
Passenger name:
> Bola Ahmed
Booked! Ref BK7F4 — CONFIRMED (train now full)
> 1
Passenger name:
> Chidi Okafor
Train full — Ref BK7F5 — WAITLISTED #1
> 2
Booking ref to cancel:
> BK7F3
Cancelled BK7F3 (Ada Lovelace).
Seat freed — BK7F5 (Chidi Okafor) promoted from the waitlist to CONFIRMED.
> 4
T100 Lagos -> Ibadan 07:30 — confirmed 2 · waitlist 0
> 0Try it in your browser
No browser demo is included for this project. Build the C++ version below — that is the real program.