Project 3
AIM OF THE PROJECT:
To build an object-oriented library which can be used to track automobile maintenance. There can be different car types such as petrol, diesel, gas, electric etc., This library should be able to support at least three of the car types.
PROCEDURE :
The program is written based on the requirements given in the question which has to support at least three cars and sub class electriccar is inherited from the base class vehicle class and diesel class and gas class is derived from the fuelvehicle class and this is derived from the main class vehicle. For each class a separate header file is created and the function to be performed is written in that header file.
SCREENSHOTS OF HEADER FILES :






MAIN .CPP FILE :






CODE :
HEADER FILE OF VEHICLE CLASS:
#ifndef VEHICLE_H
#define VEHICLE_H
#include <string>
#include <iostream>
using namespace std;
enum Type { GAS, DIESEL, ELECTRIC };
class Vehicle {
protected:
string make;
string model;
int year;
int odometer;
public:
Vehicle(string m, string mo, int y, int o) : make(m), model(mo), year(y), odometer(o) {}
virtual ~Vehicle() {}
virtual Type getType() = 0;
string getMake() const { return make; }
string getModel() const { return model; }
int getYear() const { return year; }
int getOdometer() const { return odometer; }
void setMake(string m) { make = m; }
void setModel(string m) { model = m; }
void setYear(int y) { year = y; }
void setOdometer(int o) { odometer = o; }
virtual void checkTireRotation() {
if (odometer % 50000 == 0) {
cout << "Tire rotation is due.\n";
} else {
cout << "Tires are good to go.\n";
}
}
virtual void getCarInformation() {
cout << "Make: " << make << ", Model: " << model
<< ", Year: " << year << ", Odometer: " << odometer << " km\n";
}
};
#endif
HEADER FILE OF CLASS FUELVEHICLE :
#ifndef FUELVEHICLE_H
#define FUELVEHICLE_H
#include "Vehicle.h"
using namespace std;
class FuelVehicle : public Vehicle {
public:
FuelVehicle(string m, string mo, int y, int o) : Vehicle(m, mo, y, o) {}
virtual string getFuelType() = 0;
void checkOil() {
if (odometer % 10000 == 0) {
cout << "Oil change required.\n";
} else {
cout << "Oil is good.\n";
}
}
};
#endif
HEADER FILE OF CLASS GASCAR :
#ifndef GASCAR_H
#define GASCAR_H
#include "FuelVehicle.h"
using namespace std;
class GasCar : public FuelVehicle {
public:
GasCar(string m, string mo, int y, int o) : FuelVehicle(m, mo, y, o) {}
Type getType() override { return GAS; }
string getFuelType() override { return "Gas"; }
};
#endif
HEADER FILE OF CLASS DIESELCAR :
#ifndef DIESELCAR_H
#define DIESELCAR_H
#include "FuelVehicle.h"
using namespace std;
class DieselCar : public FuelVehicle {
public:
DieselCar(string m, string mo, int y, int o) : FuelVehicle(m, mo, y, o) {}
Type getType() override { return DIESEL; }
string getFuelType() override { return "Diesel"; }
};
#endif
HEADER FILE OF CLASS ELECTRICCAR :
#ifndef ELECTRICCAR_H
#define ELECTRICCAR_H
#include "Vehicle.h"
using namespace std ;
class ElectricCar : public Vehicle {
public:
ElectricCar(string m, string mo, int y, int o) : Vehicle(m, mo, y, o) {}
Type getType() override { return ELECTRIC; }
void checkChargerPower() {
if (odometer % 400 == 0) {
cout << "Recharge your battery.\n";
} else {
cout << "vehicle has charge to drive.\n";
}
}
string getFuelType() { return "Electric"; }
};
#endif
MAIN .CPP PROGRAM :
/*
* main.cpp
*
* Created on: May 13, 2025
* Author: venka
*/
#include <iostream>
#include <vector>
#include <limits>
#include "GasCar.h"
#include "DieselCar.h"
#include "ElectricCar.h"
using namespace std;
vector<Vehicle*> inventory;
void listInventory() {
if (inventory.empty()) {
cout << "Inventory list is empty.\n";
return;
}
for (size_t i = 0; i < inventory.size(); ++i) {
cout << i << ":";
inventory[i]->getCarInformation();
}
}
int getValidatedInput(int min, int max) {
int choice;
while (true) {
cin >> choice;
if (cin.fail() || choice < min || choice > max) {
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
cout << "Invalid input. Try again: ";
} else {
cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n' );
break;
}
}
return choice;
}
string getNonEmptyString(const string& prompt) {
string input;
do {
cout << prompt;
getline(cin, input);
} while (input.empty());
return input;
}
int getFourDigitYear() {
int year;
while (true) {
cout << "Enter year (YYYY): ";
cin >> year;
if (year >= 1000 && year <= 9999)
break;
cout << "Invalid year.\n";
}
return year;
}
int getOdometerReading() {
int odo;
while (true) {
cout << "Enter odometer reading: ";
cin >> odo;
if (odo >= 0)
break;
cout << "Invalid reading.\n";
}
return odo;
}
int getTypeInput() {
cout << "Enter fuel type (0: GAS, 1: DIESEL, 2: ELECTRIC): ";
return getValidatedInput(0, 2);
}
Vehicle* createVehicle() {
cin.ignore();
string make = getNonEmptyString("Make: ");
string model = getNonEmptyString("Model: ");
int year = getFourDigitYear();
int odo = getOdometerReading();
int type = getTypeInput();
switch (type) {
case GAS: return new GasCar(make, model, year, odo);
case DIESEL: return new DieselCar(make, model, year, odo);
case ELECTRIC: return new ElectricCar(make, model, year, odo);
default: return nullptr;
}
}
int selectVehicle() {
listInventory();
cout << "Select vehicle index in list: ";
return getValidatedInput(0, inventory.size() - 1);
}
void updateVehicle() {
if (inventory.empty()) return;
int idx = selectVehicle();
int newOdo = getOdometerReading();
inventory[idx]->setOdometer(newOdo);
}
void removeVehicle() {
if (inventory.empty()) return;
int idx = selectVehicle();
delete inventory[idx];
inventory.erase(inventory.begin() + idx);
}
void tireRotation() {
if (inventory.empty()) return;
int idx = selectVehicle();
inventory[idx]->checkTireRotation();
}
void oilChange() {
if (inventory.empty()) return;
int idx = selectVehicle();
FuelVehicle* fuelCar = dynamic_cast<FuelVehicle*>(inventory[idx]);
if (fuelCar)
fuelCar->checkOil();
else
cout << "Not a fuel vehicle.\n";
}
void recharge() {
if (inventory.empty()) return;
int idx = selectVehicle();
ElectricCar* ev = dynamic_cast<ElectricCar*>(inventory[idx]);
if (ev)
ev->checkChargerPower();
else
cout << "Not an electric vehicle.\n";
}
int main() {
while (true) {
cout << "\nVehicle Maintenance System:\n";
cout << "0. Quit\n1. List inventory\n2. Add vehicle\n3. Update vehicle\n"
<< "4. Remove vehicle\n5. Tire Rotation\n6. Oil Change\n7. Recharge\n";
cout << "Choose an option: ";
int choice = getValidatedInput(0, 7);
switch (choice) {
case 1: listInventory(); break;
case 2: inventory.push_back(createVehicle()); break;
case 3: updateVehicle(); break;
case 4: removeVehicle(); break;
case 5: tireRotation(); break;
case 6: oilChange(); break;
case 7: recharge(); break;
}
}
}
RESULT :
Hence the program is written and execute in STM Cube IDE and the result is shown with proper explanation that how the program works with the screenshot.
1. List Inventory

In the above screenshot we can see that the list is empty and after taking the input option 2 it adds the vehicles to the inventory.
2.Add Vehicle



In the above four photos added five vehicles with make model year and odometer reading and the list is displayed by giving option 1 as input
3. Update Vehicle :

Here the odometer reading has changed for the fourth vehicle inventory earlier the reading is 1250 and now the reading is 1270.
4.Removing Vehicle :

The fourth vehicle which the make is hmt and the model is tractor is delete or removed from the data which is in the above screenshot that the now only four vehicles are left.
5. Tire rotation :

Tire rotation due is checked based on the odometer reading of the selected vehicle if the reading value is divides with 50000 and remainder is zero then it shows output as rotation is due which represents that the vehicles should service for every 50000km. Here also for the vehicle creta reading is 100000km driven so the output is showing as tire rotation is due. and for the vehicle punch reading is 1600 so it is shown the tyre condition is good.
6. Oil Change ;

Oil change is required only for the vehicles which runs with the fuel or gas so to avoid error with the electric cars here if condition is used to check whether the selected is fuel vehicle or not, if it is fuel vehicle then the output is displayed else it shows an error message it is not a fuel vehicle. dynamic casting is used to safely convert a pointer from base class to derived class, because we have same vehicles but different features so dynamic casting is used.
7. Recharge :

Here also same concept if and dynamic casting is used because as oil change is not present in electric same as recharge is not necessary in the fuel vehicles as it has dynamo which is connect to engine with the help of belt that recharges the battery. so, here only recharge is required for the electric vehicle so it satisfy the if condition then it will print the output or else it shows an error message.
0. quit :
The quit is used to exit the while loop .