0% found this document useful (0 votes)
64 views

OOPs Practical Final

1. The document describes C++ classes for vectors and matrices with static members and methods. It includes a friend function for multiplying matrices and vectors. 2. A Matrix class is implemented with dynamic memory allocation using new/delete. Proper constructor, destructor, copy constructor and overloaded assignment operator are provided. 3. A Complex number class is implemented with operator overloading for arithmetic operations and type conversions from integer/double to complex and complex to double. Stream insertion and extraction operators are also overloaded.

Uploaded by

Rahul Verma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
64 views

OOPs Practical Final

1. The document describes C++ classes for vectors and matrices with static members and methods. It includes a friend function for multiplying matrices and vectors. 2. A Matrix class is implemented with dynamic memory allocation using new/delete. Proper constructor, destructor, copy constructor and overloaded assignment operator are provided. 3. A Complex number class is implemented with operator overloading for arithmetic operations and type conversions from integer/double to complex and complex to double. Stream insertion and extraction operators are also overloaded.

Uploaded by

Rahul Verma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 27

1.

Design C++ classes with static members, methods with default arguments, and friend

functions. (for example, design matrix and vector classes with static allocation, and a

friend function to do matrix-vector multiplication)


#include <iostream>

#include <vector>

class Vector {
private:
std::vector<double> elements;
public:
// Constructors
Vector() = default; // Default constructor
Vector(std::initializer_list<double> init) : elements(init) {}
// Method to get the size of the vector
static size_t size(const Vector& v) {
return v.elements.size();
}
// Friend function for matrix-vector multiplication
friend Vector matrixVectorMultiply(const Matrix& mat, const Vector& vec);
};
class Matrix {
private:
std::vector<std::vector<double>> elements;
public:
// Constructors
Matrix() = default; // Default constructor
Matrix(std::initializer_list<std::initializer_list<double>> init) : elements(init) {}
// Method to get the number of rows of the matrix
static size_t rows(const Matrix& mat) {
return mat.elements.size();
}
// Method to get the number of columns of the matrix
static size_t columns(const Matrix& mat) {
return (mat.elements.size() > 0) ? mat.elements[0].size() : 0;
}
// Friend function for matrix-vector multiplication
friend Vector matrixVectorMultiply(const Matrix& mat, const Vector& vec);
};
// Friend function implementation for matrix-vector multiplication
Vector matrixVectorMultiply(const Matrix& mat, const Vector& vec) {
// Check if the matrix and vector dimensions are compatible
if (Matrix::columns(mat) != Vector::size(vec)) {
std::cerr << "Error: Incompatible dimensions for matrix-vector multiplication." << std::endl;
return Vector(); // Return an empty vector in case of error
}
Vector result;
// Perform matrix-vector multiplication
for (size_t i = 0; i < Matrix::rows(mat); ++i) {
double sum = 0.0;
for (size_t j = 0; j < Matrix::columns(mat); ++j) {
sum += mat.elements[i][j] * vec.elements[j];
}
result.elements.push_back(sum);
}
return result;
}

int main() {
// Example usage
Matrix matrix({{1, 2, 3}, {4, 5, 6}});
Vector vector({2, 3, 4});
// Perform matrix-vector multiplication
Vector result = matrixVectorMultiply(matrix, vector);
// Display the result
std::cout << "Result of matrix-vector multiplication:" << std::endl;
for (double value : result.elements) {
std::cout << value << " ";
}
std::cout << std::endl;

return 0;
}

Output:
2. Implement matrix class with dynamic memory allocation and necessary methods. Give

proper constructor, destructor, copy constructor, and overloading of the assignment

operator.

#include <iostream>
#include <stdexcept>
class Matrix {
private:
size_t rows;
size_t columns;
double** elements;
public:
// Constructors
Matrix(size_t rows, size_t columns) : rows(rows), columns(columns) {
// Allocate memory for the matrix
elements = new double*[rows];
for (size_t i = 0; i < rows; ++i) {
elements[i] = new double[columns];
}

// Initialize elements to 0
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < columns; ++j) {
elements[i][j] = 0.0;
}
}
}

// Destructor
~Matrix() {
// Deallocate memory for the matrix
for (size_t i = 0; i < rows; ++i) {
delete[] elements[i];
}
delete[] elements;
}

// Copy constructor
Matrix(const Matrix& other) : rows(other.rows), columns(other.columns) {
// Allocate memory for the new matrix
elements = new double*[rows];
for (size_t i = 0; i < rows; ++i) {
elements[i] = new double[columns];
}
// Copy elements from the other matrix
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < columns; ++j) {
elements[i][j] = other.elements[i][j];
}
}
}
// Overloading the assignment operator
Matrix& operator=(const Matrix& other) {
if (this != &other) {
// Deallocate existing memory
for (size_t i = 0; i < rows; ++i) {
delete[] elements[i];
}
delete[] elements;
// Copy size
rows = other.rows;
columns = other.columns;
// Allocate new memory
elements = new double*[rows];
for (size_t i = 0; i < rows; ++i) {
elements[i] = new double[columns];
}
// Copy elements from the other matrix
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < columns; ++j) {
elements[i][j] = other.elements[i][j];
}
}
}
return *this;
}
// Method to get the number of rows
size_t getRows() const {
return rows;
}
// Method to get the number of columns
size_t getColumns() const {
return columns;
}
// Method to access elements
double& at(size_t row, size_t col) {
if (row >= rows || col >= columns) {
throw std::out_of_range("Matrix indices out of range");
}
return elements[row][col];
}
// Method to display the matrix
void display() const {
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < columns; ++j) {
std::cout << elements[i][j] << " ";
}
std::cout << std::endl;
}
}
};
int main() {
// Example usage
Matrix mat1(2, 3);
mat1.at(0, 0) = 1.0;
mat1.at(0, 1) = 2.0;
mat1.at(0, 2) = 3.0;
mat1.at(1, 0) = 4.0;
mat1.at(1, 1) = 5.0;
mat1.at(1, 2) = 6.0;
Matrix mat2 = mat1; // Copy constructor
Matrix mat3(3, 2);
mat3 = mat1; // Overloaded assignment operator
// Display matrices
std::cout << "Matrix 1:" << std::endl;
mat1.display();
std::cout << "Matrix 2 (copy of Matrix 1 using copy constructor):" << std::endl;
mat2.display();
std::cout << "Matrix 3 (assigned from Matrix 1 using overloaded assignment operator):" << std::endl;
mat3.display();
return 0;
}

Output:
3. Implement complex number class with necessary operator overloading and type

conversions such as integer to complex , double to complex, complex to double etc.

#include <iostream>
#include <cmath>

class Complex {
private:
double real;
double imag;

public:
// Constructors
Complex() : real(0.0), imag(0.0) {}
Complex(double r, double i) : real(r), imag(i) {}

// Getter functions
double getReal() const { return real; }
double getImag() const { return imag; }

// Operator overloading for basic arithmetic operations


Complex operator+(const Complex& other) const {
return Complex(real + other.real, imag + other.imag);
}

Complex operator-(const Complex& other) const {


return Complex(real - other.real, imag - other.imag);
}

Complex operator*(const Complex& other) const {


return Complex((real * other.real) - (imag * other.imag),
(real * other.imag) + (imag * other.real));
}

Complex operator/(const Complex& other) const {


double denominator = (other.real * other.real) + (other.imag * other.imag);
if (denominator == 0.0) {
// Handle division by zero
throw std::invalid_argument("Division by zero");
}
return Complex(((real * other.real) + (imag * other.imag)) / denominator,
((imag * other.real) - (real * other.imag)) / denominator);
}

// Type conversion from double to complex


Complex(double r) : real(r), imag(0.0) {}
// Type conversion from int to complex
Complex(int r) : real(static_cast<double>(r)), imag(0.0) {}

// Type conversion from complex to double


operator double() const {
return real; // Consideration: You might want to return magnitude or other value.
}

// Stream insertion operator


friend std::ostream& operator<<(std::ostream& os, const Complex& c) {
os << "(" << c.real << " + i" << c.imag << ")";
return os;
}

// Stream extraction operator


friend std::istream& operator>>(std::istream& is, Complex& c) {
char discard;
is >> discard >> c.real >> discard >> c.imag >> discard;
return is;
}
};

int main() {
// Example usage of the Complex class
Complex c1(3.0, 4.0);
Complex c2(1.5, 2.5);

// Arithmetic operations
Complex sum = c1 + c2;
Complex diff = c1 - c2;
Complex product = c1 * c2;
Complex quotient = c1 / c2;

std::cout << "c1: " << c1 << std::endl;


std::cout << "c2: " << c2 << std::endl;
std::cout << "Sum: " << sum << std::endl;
std::cout << "Difference: " << diff << std::endl;
std::cout << "Product: " << product << std::endl;
std::cout << "Quotient: " << quotient << std::endl;

// Type conversions
double c1AsDouble = static_cast<double>(c1);
int c2AsInt = static_cast<int>(c2);

std::cout << "c1 as double: " << c1AsDouble << std::endl;


std::cout << "c2 as int: " << c2AsInt << std::endl;

// Stream extraction and insertion


Complex inputComplex;
std::cout << "Enter a complex number (e.g., (3.0 + i4.0)): ";
std::cin >> inputComplex;
std::cout << "You entered: " << inputComplex << std::endl;

return 0;
}

Output:
4. Overload the new and delete operators to provide a custom dynamic allocation of

memory.

#include <iostream>
#include <new>

class Matrix {
private:
size_t rows;
size_t columns;
double** elements;

public:
// Overloaded new operator for custom memory allocation
void* operator new(std::size_t size) {
std::cout << "Custom new operator called. Size: " << size << std::endl;
return ::operator new(size);
}

// Overloaded delete operator for custom memory deallocation


void operator delete(void* ptr) noexcept {
std::cout << "Custom delete operator called." << std::endl;
::operator delete(ptr);
}

// Constructors, destructor, and other methods remain the same...

// Method to get the number of rows


size_t getRows() const {
return rows;
}

// Method to get the number of columns


size_t getColumns() const {
return columns;
}

// Method to access elements


double& at(size_t row, size_t col) {
if (row >= rows || col >= columns) {
throw std::out_of_range("Matrix indices out of range");
}
return elements[row][col];
}
// Method to display the matrix
void display() const {
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < columns; ++j) {
std::cout << elements[i][j] << " ";
}
std::cout << std::endl;
}
}
};

int main() {
// Example usage
Matrix* mat = new Matrix(2, 3);

// Access and modify elements


mat->at(0, 0) = 1.0;
mat->at(0, 1) = 2.0;
mat->at(0, 2) = 3.0;
mat->at(1, 0) = 4.0;
mat->at(1, 1) = 5.0;
mat->at(1, 2) = 6.0;

// Display the matrix


std::cout << "Matrix:" << std::endl;
mat->display();

// Delete the matrix


delete mat;

return 0;
}

Output:
5. Develop C++ class hierarchy for various types of inheritances.

#include <iostream>
// Base class
class Animal {
public:
void eat() {
std::cout << "Animal is eating." << std::endl;
}
void sleep() {
std::cout << "Animal is sleeping." << std::endl;
}
};
// Single Inheritance
class Dog : public Animal {
public:
void bark() {
std::cout << "Dog is barking." << std::endl;
}
};
// Multiple Inheritance
class Bird {
public:
void fly() {
std::cout << "Bird is flying." << std::endl;
}
};
class FlyingDog : public Dog, public Bird {
public:
// Inherits both bark() from Dog and fly() from Bird
};
// Hierarchical Inheritance
class Cat : public Animal {
public:
void meow() {
std::cout << "Cat is meowing." << std::endl;
}
};
// Multilevel Inheritance
class Kitten : public Cat {
public:
void play() {
std::cout << "Kitten is playing." << std::endl;
}
};
int main() {
// Single Inheritance example
Dog myDog;
myDog.eat(); // Inherited from Animal
myDog.sleep(); // Inherited from Animal
myDog.bark(); // Specific to Dog
// Multiple Inheritance example
FlyingDog flyingDog;
flyingDog.eat(); // Inherited from Animal
flyingDog.sleep(); // Inherited from Animal
flyingDog.bark(); // Inherited from Dog
flyingDog.fly(); // Inherited from Bird

// Hierarchical Inheritance example


Cat myCat;
myCat.eat(); // Inherited from Animal
myCat.sleep(); // Inherited from Animal
myCat.meow(); // Specific to Cat

// Multilevel Inheritance example


Kitten myKitten;
myKitten.eat(); // Inherited from Animal
myKitten.sleep(); // Inherited from Animal
myKitten.meow(); // Inherited from Cat
myKitten.play(); // Specific to Kitten

return 0;
}
Output:
6. Design a simple test application to demonstrate dynamic polymorphism and RTTI

#include <iostream>
#include <vector>
#include <typeinfo>

// Base class
class Shape {
public:
virtual void draw() const {
std::cout << "Drawing a shape." << std::endl;
}

virtual ~Shape() = default; // Virtual destructor for proper cleanup


};

// Derived class: Circle


class Circle : public Shape {
public:
void draw() const override {
std::cout << "Drawing a circle." << std::endl;
}
};

// Derived class: Rectangle


class Rectangle : public Shape {
public:
void draw() const override {
std::cout << "Drawing a rectangle." << std::endl;
}
};

int main() {
// Create a vector of shapes using dynamic polymorphism
std::vector<Shape*> shapes;
shapes.push_back(new Circle());
shapes.push_back(new Rectangle());
shapes.push_back(new Circle());
shapes.push_back(new Rectangle());

// Draw each shape using dynamic polymorphism


for (const Shape* shape : shapes) {
shape->draw();
}

// Demonstrate RTTI (Run-Time Type Information)


for (const Shape* shape : shapes) {
// Check the type using typeid and dynamic_cast
if (typeid(*shape) == typeid(Circle)) {
const Circle* circle = dynamic_cast<const Circle*>(shape);
if (circle != nullptr) {
std::cout << "Type: Circle" << std::endl;
}
} else if (typeid(*shape) == typeid(Rectangle)) {
const Rectangle* rectangle = dynamic_cast<const Rectangle*>(shape);
if (rectangle != nullptr) {
std::cout << "Type: Rectangle" << std::endl;
}
}
}

// Cleanup: Delete dynamically allocated shapes


for (Shape* shape : shapes) {
delete shape;
}

return 0;
}

Output:
7. Develop a template of the linked-list class and its methods.

#include <iostream>

template <typename T>


class LinkedList {
private:
// Node structure for the linked list
struct Node {
T data;
Node* next;
Node(const T& value) : data(value), next(nullptr) {}
};

Node* head; // Pointer to the head of the linked list

public:
// Constructor
LinkedList() : head(nullptr) {}

// Destructor
~LinkedList() {
clear();
}

// Function to insert a new element at the beginning of the list


void insertFront(const T& value) {
Node* newNode = new Node(value);
newNode->next = head;
head = newNode;
}

// Function to insert a new element at the end of the list


void insertEnd(const T& value) {
Node* newNode = new Node(value);
if (head == nullptr) {
head = newNode;
return;
}

Node* current = head;


while (current->next != nullptr) {
current = current->next;
}

current->next = newNode;
}
// Function to delete the first occurrence of a value in the list
void remove(const T& value) {
if (head == nullptr) {
return;
}

if (head->data == value) {
Node* temp = head;
head = head->next;
delete temp;
return;
}

Node* current = head;


while (current->next != nullptr && current->next->data != value) {
current = current->next;
}

if (current->next != nullptr) {
Node* temp = current->next;
current->next = current->next->next;
delete temp;
}
}

// Function to display the elements of the list


void display() const {
Node* current = head;
while (current != nullptr) {
std::cout << current->data << " ";
current = current->next;
}
std::cout << std::endl;
}

// Function to clear the entire list


void clear() {
while (head != nullptr) {
Node* temp = head;
head = head->next;
delete temp;
}
}
};

int main() {
// Example usage of the LinkedList template
LinkedList<int> intList;
intList.insertEnd(1);
intList.insertEnd(2);
intList.insertFront(0);
intList.display(); // Output: 0 1 2

intList.remove(1);
intList.display(); // Output: 0 2

// Example with strings


LinkedList<std::string> stringList;
stringList.insertEnd("Hello");
stringList.insertEnd("World");
stringList.display(); // Output: Hello World

return 0;
}

Output:
8. Develop templates of standard sorting algorithms such as bubble sort, insertion sort and

quick sort.

➢ Bubble Sort

#include <iostream>
#include <vector>

template <typename T>


void bubbleSort(std::vector<T>& arr) {
size_t n = arr.size();
for (size_t i = 0; i < n - 1; ++i) {
for (size_t j = 0; j < n - i - 1; ++j) {
if (arr[j] > arr[j + 1]) {
std::swap(arr[j], arr[j + 1]);
}
}
}
}

int main() {
// Example usage of bubbleSort template
std::vector<int> intArray = {64, 34, 25, 12, 22, 11, 90};
bubbleSort(intArray);
std::cout << "Sorted array: ";
for (const auto& elem : intArray) {
std::cout << elem << " ";
}
std::cout << std::endl;

return 0;
}

Output:
➢ Insertion Sort

#include <iostream>
#include <vector>

template <typename T>


void insertionSort(std::vector<T>& arr) {
size_t n = arr.size();
for (size_t i = 1; i < n; ++i) {
T key = arr[i];
int j = i - 1;

while (j >= 0 && arr[j] > key) {


arr[j + 1] = arr[j];
--j;
}
arr[j + 1] = key;
}
}

int main() {
// Example usage of insertionSort template
std::vector<int> intArray = {64, 34, 25, 12, 22, 11, 90};
insertionSort(intArray);
std::cout << "Sorted array: ";
for (const auto& elem : intArray) {
std::cout << elem << " ";
}
std::cout << std::endl;

return 0;
}

Output:
➢ Quick Sort
#include <iostream>

#include <vector>

template <typename T>


size_t partition(std::vector<T>& arr, size_t low, size_t high) {
T pivot = arr[high];
size_t i = low - 1;

for (size_t j = low; j < high; ++j) {


if (arr[j] <= pivot) {
++i;
std::swap(arr[i], arr[j]);
}
}

std::swap(arr[i + 1], arr[high]);


return i + 1;
}

template <typename T>


void quickSort(std::vector<T>& arr, size_t low, size_t high) {
if (low < high) {
size_t pivotIndex = partition(arr, low, high);

if (pivotIndex > 0) {
quickSort(arr, low, pivotIndex - 1);
}

quickSort(arr, pivotIndex + 1, high);


}
}
int main() {
// Example usage of quickSort template
std::vector<int> intArray = {64, 34, 25, 12, 22, 11, 90};
quickSort(intArray, 0, intArray.size() - 1);
std::cout << "Sorted array: ";
for (const auto& elem : intArray) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
Output:
9. Design stack and queue classes with necessary exception handling.

➢ Stack Class

#include <iostream>
#include <stdexcept>
#include <vector>

template <typename T>


class Stack {
private:
std::vector<T> elements;

public:
// Push an element onto the stack
void push(const T& value) {
elements.push_back(value);
}

// Pop the top element from the stack


void pop() {
if (empty()) {
throw std::underflow_error("Stack is empty. Cannot pop.");
}
elements.pop_back();
}

// Get the top element of the stack


T& top() {
if (empty()) {
throw std::underflow_error("Stack is empty. Cannot get top.");
}
return elements.back();
}

// Check if the stack is empty


bool empty() const {
return elements.empty();
}

// Get the size of the stack


size_t size() const {
return elements.size();
}
};

int main() {
// Example usage of Stack class
Stack<int> intStack;

try {
intStack.push(10);
intStack.push(20);
intStack.push(30);

std::cout << "Top element: " << intStack.top() << std::endl;


intStack.pop();
std::cout << "Top element after pop: " << intStack.top() << std::endl;

while (!intStack.empty()) {
intStack.pop();
}

// Attempting to pop from an empty stack (exception handling)


intStack.pop(); // This should throw an exception
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}

return 0;
}

Output:
➢ Queue Class

#include <iostream>
#include <stdexcept>
#include <queue>

template <typename T>


class Queue {
private:
std::queue<T> elements;

public:
// Enqueue an element into the queue
void enqueue(const T& value) {
elements.push(value);
}

// Dequeue an element from the front of the queue


void dequeue() {
if (empty()) {
throw std::underflow_error("Queue is empty. Cannot dequeue.");
}
elements.pop();
}

// Get the front element of the queue


T& front() {
if (empty()) {
throw std::underflow_error("Queue is empty. Cannot get front.");
}
return elements.front();
}

// Check if the queue is empty


bool empty() const {
return elements.empty();
}

// Get the size of the queue


size_t size() const {
return elements.size();
}
};

int main() {
// Example usage of Queue class
Queue<int> intQueue;
try {
intQueue.enqueue(10);
intQueue.enqueue(20);
intQueue.enqueue(30);

std::cout << "Front element: " << intQueue.front() << std::endl;


intQueue.dequeue();
std::cout << "Front element after dequeue: " << intQueue.front() << std::endl;

while (!intQueue.empty()) {
intQueue.dequeue();
}

// Attempting to dequeue from an empty queue (exception handling)


intQueue.dequeue(); // This should throw an exception
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}

return 0;
}

Output:
10. Write a C++ program that randomly generates complex numbers (use previously

designed complex class ) and write them two per line in a file along with an operator (+,-

,*, or /). The numbers are written to file in the format (a+ib). Write another program to

read one line at a time from this file.

#include <iostream>
#include <fstream>
#include <cstdlib> // for rand() and srand()
#include <ctime> // for time()
#include <sstream>
#include <vector>
#include <string>

// Complex class definition (assuming you have a complex class)


class Complex {
public:
double real;
double imag;

Complex(double r, double i) : real(r), imag(i) {}

// Overloaded stream insertion operator for formatting


friend std::ostream& operator<<(std::ostream& os, const Complex& c) {
return os << "(" << c.real << "+i" << c.imag << ")";
}
};

// Function to generate a random complex number


Complex generateRandomComplex() {
double realPart = static_cast<double>(rand()) / RAND_MAX * 10.0; // Random real part between 0 and
10
double imagPart = static_cast<double>(rand()) / RAND_MAX * 10.0; // Random imag part between 0
and 10
return Complex(realPart, imagPart);
}

// Function to generate a random operator


char generateRandomOperator() {
char operators[] = {'+', '-', '*', '/'};
return operators[rand() % 4];
}

int main() {
// Seed the random number generator
srand(static_cast<unsigned>(time(nullptr)));
// Open a file for writing
std::ofstream outFile("complex_numbers.txt");

// Write two complex numbers and an operator per line to the file
for (int i = 0; i < 5; ++i) {
Complex c1 = generateRandomComplex();
Complex c2 = generateRandomComplex();
char op = generateRandomOperator();

outFile << c1 << " " << op << " " << c2 << std::endl;
}

// Close the file


outFile.close();

std::cout << "Complex numbers written to file." << std::endl;

return 0;
}

// Complex class definition (assuming you have a complex class)


class Complex {
public:
double real;
double imag;

Complex(double r, double i) : real(r), imag(i) {}

// Overloaded stream insertion operator for formatting


friend std::ostream& operator<<(std::ostream& os, const Complex& c) {
return os << "(" << c.real << "+i" << c.imag << ")";
}
};

// Function to parse a line from the file


void parseLine(const std::string& line) {
std::istringstream iss(line);
Complex c1(0.0, 0.0), c2(0.0, 0.0);
char op;
// Parse the complex numbers and operator from the line
iss >> c1 >> op >> c2;
// Display the parsed values
std::cout << "Complex Number 1: " << c1 << std::endl;
std::cout << "Operator: " << op << std::endl;
std::cout << "Complex Number 2: " << c2 << std::endl;
std::cout << "---------------------------" << std::endl;
}
int main() {
// Open the file for reading
std::ifstream inFile("complex_numbers.txt");
if (!inFile) {
std::cerr << "Error opening file." << std::endl;
return 1;
}
// Read one line at a time and process it
std::string line;
while (std::getline(inFile, line)) {
parseLine(line);
}
// Close the file
inFile.close();
return 0;
}

Output:

You might also like