Design A Parking Lot System In C++

Introduction

Parking these days is an imperative element of development, especially in urban-versatile buildings and structures. Even though airports, cities, and shopping complexes have plenty of common space for parking, managing them efficiently can be a nightmare. An efficient and effective parking lot system maintains traffic movement, monitors parking space occupancy, and assures efficient parking operations. In this article, we will discuss how to implement a simple parking lot design using C++ . We will edit the problem, mention all components required, and build a simple solution to this problem.

Problem Statement:

We need to create a parking lot system that can accommodate more than one vehicle at a time and keep a record of how many parking spaces are still open. The system in consideration should have the capacity for the following functions:

  • Park a vehicle: Site availability management - whenever the car is taken to the site, the relevant host will always invite the observer to at least one empty site.
  • Remove a vehicle: If there is any vehicle parked, the system should mark that the parking space is now free.
  • Track available spots: In the operations of such a system a considerable number of spots available at a particular time will be accurately mentioned.

It is clear that this parking lot does not have an unlimited number of spots, and we shall also assume that it will be possible to park various kinds of vehicle types within a single parking lot (for example, cars, motorcycles, and buses) and parking space will differ per vehicle type.

Program 1:

Example

Example

#include <iostream>
#include <vector>
#include <string>

using namespace std;

// Enum to define vehicle sizes
enum VehicleSize { MOTORCYCLE, COMPACT, LARGE };

// Abstract class for a vehicle
class Vehicle {
protected:
    VehicleSize size;
    int spotsNeeded;
public:
    virtual VehicleSize getSize() = 0;
    virtual int getSpotsNeeded() = 0;
};

class Motorcycle : public Vehicle {
public:
    Motorcycle() {
        size = MOTORCYCLE;
        spotsNeeded = 1;
    }
    VehicleSize getSize() override {
        return MOTORCYCLE;
    }
    int getSpotsNeeded() override {
        return 1;
    }
};

class Car : public Vehicle {
public:
    Car() {
        size = COMPACT;
        spotsNeeded = 1;
    }
    VehicleSize getSize() override {
        return COMPACT;
    }
    int getSpotsNeeded() override {
        return 1;
    }
};

class Bus : public Vehicle {
public:
    Bus() {
        size = LARGE;
        spotsNeeded = 5;
    }
    VehicleSize getSize() override {
        return LARGE;
    }
    int getSpotsNeeded() override {
        return 5;
    }
};

// Class to represent a parking spot
class ParkingSpot {
private:
    VehicleSize spotSize;
    Vehicle* currentVehicle;
    int spotNumber;
public:
    ParkingSpot(VehicleSize size, int num) : spotSize(size), spotNumber(num), currentVehicle(nullptr) {}

    bool isAvailable() {
        return currentVehicle == nullptr;
    }

    bool canFitVehicle(Vehicle* vehicle) {
        return isAvailable() && vehicle->getSize() <= spotSize;
    }

    void parkVehicle(Vehicle* vehicle) {
        currentVehicle = vehicle;
    }

    void removeVehicle() {
        currentVehicle = nullptr;
    }

    int getSpotNumber() const {
        return spotNumber;
    }
};

// Class to represent a parking level
class ParkingLevel {
private:
    int floorNumber;
    vector<ParkingSpot> spots;
    int availableSpots;
public:
    ParkingLevel(int floor, int numberOfSpots) : floorNumber(floor), availableSpots(numberOfSpots) {
        for (int i = 0; i < numberOfSpots; ++i) {
            spots.push_back(ParkingSpot(COMPACT, i));
        }
    }

    bool parkVehicle(Vehicle* vehicle) {
        int spotsNeeded = vehicle->getSpotsNeeded();
        for (int i = 0; i < spots.size(); ++i) {
            if (spots[i].canFitVehicle(vehicle)) {
                spots[i].parkVehicle(vehicle);
                availableSpots--;
                return true;
            }
        }
        return false;
    }

    void removeVehicle(int spotNumber) {
        spots[spotNumber].removeVehicle();
        availableSpots++;
    }

    int getAvailableSpots() {
        return availableSpots;
    }
};

// Class to represent the parking lot
class ParkingLot {
private:
    vector<ParkingLevel> levels;
public:
    ParkingLot(int numLevels, int spotsPerLevel) {
        for (int i = 0; i < numLevels; ++i) {
            levels.push_back(ParkingLevel(i, spotsPerLevel));
        }
    }

    bool parkVehicle(Vehicle* vehicle) {
        for (auto& level : levels) {
            if (level.parkVehicle(vehicle)) {
                return true;
            }
        }
        return false;
    }

    void removeVehicle(int levelNumber, int spotNumber) {
        levels[levelNumber].removeVehicle(spotNumber);
    }

    void displayAvailableSpots() {
        for (int i = 0; i < levels.size(); ++i) {
            cout << "Level " << i << ": " << levels[i].getAvailableSpots() << " spots available." << endl;
        }
    }
};

int main() {
    // Create a parking lot with 3 levels and 10 spots per level
    ParkingLot parkingLot(3, 10);

    Vehicle* car = new Car();
    Vehicle* motorcycle = new Motorcycle();
    Vehicle* bus = new Bus();

    // Park vehicles
    parkingLot.parkVehicle(car);
    parkingLot.parkVehicle(motorcycle);
    parkingLot.parkVehicle(bus);

    // Display available spots
    parkingLot.displayAvailableSpots();

    return 0;
}

Output:

Output

Level 0: 8 spots available.
Level 1: 10 spots available.
Level 2: 10 spots available.

Explanation of code:

  • Vehicle Class Vehicle is an abstract class containing subclasses such as Motorcycle, Car, and Bus, which implement the required number of spots in the structure.
  • ParkingSpot Class: This class gives the individual dimensioned parking space, also known as a parking spot. It is capable of verifying whether the spot is taken and if the vehicle can be accommodated.
  • ParkingLevel Class: It contains several parking spots and is responsible for the proper placement of the vehicle in the parking area. The vehicle can be parked only if there is an empty parking spot. When a vehicle is driven out of the parking zone, it becomes possible to remove a vehicle from this level.
  • ParkingLot Class: It controls multiple levels within the area of many parking lots. It is particularly optimized for cases where one or more vehicles have to be parked within the available space and then removed whenever desired.
  • Program 2:

    Example

    Example
    
    #include <iostream>
    #include <vector>
    #include <chrono>
    #include <string>
    
    using namespace std;
    
    // Enum to define vehicle sizes
    enum VehicleSize { MOTORCYCLE, COMPACT, LARGE };
    
    // Abstract class for a vehicle
    class Vehicle {
    protected:
        string licensePlate;
        VehicleSize size;
        int spotsNeeded;
    public:
        Vehicle(string plate) : licensePlate(plate) {}
    
        string getLicensePlate() const {
            return licensePlate;
        }
    
        virtual VehicleSize getSize() = 0;
        virtual int getSpotsNeeded() = 0;
    };
    
    class Motorcycle : public Vehicle {
    public:
        Motorcycle(string plate) : Vehicle(plate) {
            size = MOTORCYCLE;
            spotsNeeded = 1;
        }
        VehicleSize getSize() override {
            return MOTORCYCLE;
        }
        int getSpotsNeeded() override {
            return 1;
        }
    };
    
    class Car : public Vehicle {
    public:
        Car(string plate) : Vehicle(plate) {
            size = COMPACT;
            spotsNeeded = 1;
        }
        VehicleSize getSize() override {
            return COMPACT;
        }
        int getSpotsNeeded() override {
            return 1;
        }
    };
    
    class Bus : public Vehicle {
    public:
        Bus(string plate) : Vehicle(plate) {
            size = LARGE;
            spotsNeeded = 5;
        }
        VehicleSize getSize() override {
            return LARGE;
        }
        int getSpotsNeeded() override {
            return 5;
        }
    };
    
    // Class to represent a parking spot
    class ParkingSpot {
    private:
        VehicleSize spotSize;
        Vehicle* currentVehicle;
        int spotNumber;
        bool isReserved;  // Reserved spot feature
    
    public:
        ParkingSpot(VehicleSize size, int num) : spotSize(size), spotNumber(num), currentVehicle(nullptr), isReserved(false) {}
    
        bool isAvailable() {
            return currentVehicle == nullptr && !isReserved;
        }
    
        bool canFitVehicle(Vehicle* vehicle) {
            return isAvailable() && vehicle->getSize() <= spotSize;
        }
    
        void parkVehicle(Vehicle* vehicle) {
            currentVehicle = vehicle;
        }
    
        void removeVehicle() {
            currentVehicle = nullptr;
        }
    
        int getSpotNumber() const {
            return spotNumber;
        }
    
        bool reserveSpot() {
            if (!isReserved && isAvailable()) {
                isReserved = true;
                return true;
            }
            return false;
        }
    
        void unreserveSpot() {
            isReserved = false;
        }
    
        bool isReservedSpot() {
            return isReserved;
        }
    };
    
    // Class to track parking duration and fee calculation
    class ParkingTicket {
    private:
        chrono::time_point<chrono::system_clock> entryTime;
        chrono::time_point<chrono::system_clock> exitTime;
        double hourlyRate;
    
    public:
        ParkingTicket(double rate = 5.0) : hourlyRate(rate) {
            entryTime = chrono::system_clock::now();
        }
    
        void setExitTime() {
            exitTime = chrono::system_clock::now();
        }
    
        double calculateFee() {
            chrono::duration<double> duration = exitTime - entryTime;
            return duration.count() * hourlyRate;
        }
    };
    
    // Class to represent a parking level
    class ParkingLevel {
    private:
        int floorNumber;
        vector<ParkingSpot> spots;
        int availableSpots;
        int totalSpots;
    
    public:
        ParkingLevel(int floor, int numberOfSpots) : floorNumber(floor), availableSpots(numberOfSpots), totalSpots(numberOfSpots) {
            for (int i = 0; i < numberOfSpots; ++i) {
                spots.push_back(ParkingSpot(COMPACT, i));
            }
        }
    
        bool parkVehicle(Vehicle* vehicle) {
            int spotsNeeded = vehicle->getSpotsNeeded();
            for (int i = 0; i < spots.size(); ++i) {
                if (spots[i].canFitVehicle(vehicle)) {
                    spots[i].parkVehicle(vehicle);
                    availableSpots--;
                    return true;
                }
            }
            return false;
        }
    
        void removeVehicle(int spotNumber) {
            spots[spotNumber].removeVehicle();
            availableSpots++;
        }
    
        int getAvailableSpots() const {
            return availableSpots;
        }
    
        int getTotalSpots() const {
            return totalSpots;
        }
    
        bool reserveSpot(int spotNumber) {
            if (spots[spotNumber].isAvailable()) {
                spots[spotNumber].reserveSpot();
                availableSpots--;
                return true;
            }
            return false;
        }
    
        void unreserveSpot(int spotNumber) {
            if (spots[spotNumber].isReservedSpot()) {
                spots[spotNumber].unreserveSpot();
                availableSpots++;
            }
        }
    };
    
    // Class to represent the parking lot
    class ParkingLot {
    private:
        vector<ParkingLevel> levels;
    
    public:
        ParkingLot(int numLevels, int spotsPerLevel) {
            for (int i = 0; i < numLevels; ++i) {
                levels.push_back(ParkingLevel(i, spotsPerLevel));
            }
        }
    
        bool parkVehicle(Vehicle* vehicle) {
            for (auto& level : levels) {
                if (level.parkVehicle(vehicle)) {
                    return true;
                }
            }
            return false;
        }
    
        void removeVehicle(int levelNumber, int spotNumber) {
            levels[levelNumber].removeVehicle(spotNumber);
        }
    
        void displayAvailableSpots() {
            for (int i = 0; i < levels.size(); ++i) {
                cout << "Level " << i << ": " << levels[i].getAvailableSpots() << " spots available." << endl;
            }
        }
    
        bool reserveSpot(int levelNumber, int spotNumber) {
            return levels[levelNumber].reserveSpot(spotNumber);
        }
    
        void unreserveSpot(int levelNumber, int spotNumber) {
            levels[levelNumber].unreserveSpot(spotNumber);
        }
    };
    
    // Main function to test the system
    int main() {
        // Create a parking lot with 3 levels and 10 spots per level
        ParkingLot parkingLot(3, 10);
    
        // Create vehicles
        Vehicle* car = new Car("CAR123");
        Vehicle* motorcycle = new Motorcycle("MOTO456");
        Vehicle* bus = new Bus("BUS789");
    
        // Park vehicles
        parkingLot.parkVehicle(car);
        parkingLot.parkVehicle(motorcycle);
        parkingLot.parkVehicle(bus);
    
        // Display available spots
        parkingLot.displayAvailableSpots();
    
        // Reserve a spot
        if (parkingLot.reserveSpot(0, 2)) {
            cout << "Spot 2 on Level 0 reserved successfully." << endl;
        } else {
            cout << "Failed to reserve spot 2 on Level 0." << endl;
        }
    
        // Unreserve a spot
        parkingLot.unreserveSpot(0, 2);
    
        // Display available spots again
        parkingLot.displayAvailableSpots();
    
        return 0;
    }
    

Output:

Output

Level 0: 8 spots available.
Level 1: 10 spots available.
Level 2: 10 spots available.
Spot 2 on Level 0 reserved successfully.
Level 0: 8 spots available.
Level 1: 10 spots available.
Level 2: 10 spots available.

Explanation:

  • Vehicle Registration and Identification: The Vehicle class now includes a licensePlate attribute, which tracks the registration number of each vehicle.
  • Parking Charges: The ParkingTicket class calculates parking fees based on the entry and exit time using a simple hourly rate.
  • Dynamic Spot Allocation: Vehicles are parked based on their size (MOTORCYCLE, COMPACT, LARGE), and different types of vehicles can fit into other spots.
  • Reservation System: Users can reserve parking spots. The system prevents vehicles from occupying reserved spots, and reservations can be cancelled to free up space.
  • Displaying Available Spots: The system displays the number of available parking spots on each level.
  • Conclusion:

In conclusion, this simple parking lot system developed in C++ shows how to organize vehicles and manage their available spaces on several levels. The design can be enhanced to include more sophisticated functionalities such as payment options handling, mobile dynamic spot taking, and updated information in real-time. This design can be used as the basis for any sophisticated parking system solution.

Input Required

This code uses input(). Please provide values below: