C++ Formative Exam Code Refinement
Formative Exam Code Review and Correction
<p>******************************************************<br>
FORMATIVE EXAM<br>
******************************************************</p>
<h3>Library Management System Code (Questions 1-8)</h3>
<p><code>#include <iostream><br>include <fstream>
include <sstream>
include <string>
include <map>
include <memory>
include <algorithm>
<p><code>using namespace std;</code></p>
<h4>Question 3: Enum for Genre</h4>
<p>The <code>Genre</code> enumeration defines book categories:</p>
<pre><code>enum class Genre {
Science,
Fiction,
Poetry,
Unknown};
<p>Helper functions for genre conversion:</p>
<pre><code>string genreToString(Genre g) {
switch (g) {
case Genre::Science: return "Science";
case Genre::Fiction: return "Fiction";
case Genre::Poetry: return "Poetry";
default: return "Unknown";
}}
Genre stringToGenre(const string& s) { if (s == “Science”) return Genre::Science; if (s == “Fiction”) return Genre::Fiction; if (s == “Poetry”) return Genre::Poetry; return Genre::Unknown; }
<h4>Question 9: Abstract Book Class</h4>
<p>The abstract base class <code>Book</code>:</p>
<pre><code>class Book {protected: string title; string author; int year; double price; Genre genre; bool borrowed;
public: virtual ~Book() {} // Virtual destructor is crucial
// Individual setters (Q3)
void setTitle(string t) { title = t; }
void setAuthor(string a) { author = a; }
void setYear(int y) { year = y; }
void setPrice(double p) { price = p; }
void setGenre(Genre g) { genre = g; }
void setBorrowed(bool b) { borrowed = b; }
// Global setter using individual setters
void setAll(string t, string a, int y, double p, Genre g, bool b) {
setTitle(t);
setAuthor(a);
setYear(y);
setPrice(p);
setGenre(g);
setBorrowed(b);
}
int getYear() const { return year; }
Genre getGenre() const { return genre; }
bool isBorrowed() const { return borrowed; }
// Pure virtual function → makes Book abstract
virtual string getType() const = 0;
// Operator overloading <<
friend ostream& operator<<(ostream& os, const Book& b) {
os << "[" << b.getType() << "] "
<< b.title << ", "
<< b.author << ", "
<< b.year << ", "
<< b.price << ", "
<< genreToString(b.genre) << ", "
<< (b.borrowed ? "Yes" : "No");
return os;
}};
<h4>Question 9: Derived Class</h4>
<p>The derived class <code>Printed</code>:</p>
<pre><code>class Printed : public Book {private: string publisher; public: Printed(string p) : publisher(p) {} string getType() const { return “Printed”; } };
<h3>Questions 4–8: Library Class Implementation</h3>
<pre><code>class Library {private: map<int, shared_ptr<Book> > books; int position; public: Library() : position(0) {}
// Question 4: add book
void addBook(shared_ptr<Book> b) {
books[++position] = b;
cout << "Inserted at position " << position << endl;
}
// Questions 4 & 5: load file with error handling
void loadFromFile(const string& filename) {
ifstream file(filename);
if (!file) {
cerr << "Error: Library.txt not found. Please create it before running." << endl;
return;
}
string line;
while (getline(file, line)) {
stringstream ss(line);
string title, author, yearStr, priceStr, genreStr, borrowedStr;
getline(ss, title, ',');
getline(ss, author, ',');
getline(ss, yearStr, ',');
getline(ss, priceStr, ',');
getline(ss, genreStr, ',');
getline(ss, borrowedStr, ',');
try {
int year = stoi(yearStr);
double price = stod(priceStr);
Genre g = stringToGenre(genreStr);
if (g == Genre::Unknown) throw runtime_error("Invalid genre");
bool borrowed = (borrowedStr == "Yes");
// Assuming all loaded books are 'Printed' for this example structure
shared_ptr<Book> book(new Printed("DefaultPublisher"));
book->setAll(title, author, year, price, g, borrowed);
addBook(book);
} catch (const exception& e) {
cerr << "Error processing record: " << line << " (Reason: " << e.what() << ")" << endl;
} catch (...) {
cerr << "Error processing record: " << line << endl;
}
}
}
// Question 6: Display oldest book
void displayOldestBook() const {
if (books.empty()) {
cout << "Library is empty." << endl;
return;
}
auto oldest = min_element(
books.begin(), books.end(),
[](const pair<const int, shared_ptr<Book> >& a,
const pair<const int, shared_ptr<Book> >& b) {
return a.second->getYear() < b.second->getYear();
}
);
cout << "Oldest book: " << *oldest->second << endl;
}
// Question 7: Display by genre
void displayByGenre(Genre g) const {
cout << "--- Books in Genre: " << genreToString(g) << " ---" << endl;
bool found = false;
for (const auto& pair : books) {
if (pair.second->getGenre() == g)
cout << *(pair.second) << endl;
found = true;
}
if (!found) cout << "No books found for this genre." << endl;
}
// Question 8: Save borrowed books to file
void saveBorrowed(const string& filename) const {
ofstream out(filename);
if (!out) {
cerr << "Error: Could not open " << filename << " for writing." << endl;
return;
}
for (const auto& pair : books) {
if (pair.second->isBorrowed())
out << *(pair.second) << "\n"; // Use newline character explicitly
}
cout << "Borrowed books saved to " << filename << endl;
}};
<h4>Main Function Execution</h4>
<pre><code>int main() {
Library library;
// Q1: Library.txt must be manually created
// Q4 & Q5: Load file
library.loadFromFile("Library.txt");
// Q6: Display oldest book
library.displayOldestBook();
// Q7: Display by genre
cout << "\nSelect genre (Science/Fiction/Poetry): ";
string g;
cin >> g;
library.displayByGenre(stringToGenre(g));
// Q8: Save borrowed books
library.saveBorrowed("Borrowed.txt");
return 0;}
<h5>Example <code>Library.txt</code> Content</h5>
<p>Note: Commas separate fields. The last field is the borrowed status.</p>
<pre><code>The Art of Computer Programming,Donald Knuth,1988,23.3,Science,No1984,George Orwell,1948,6.66,Fiction,Yes Masnavi,Rumi,1258,15.3,Poetry,Yes Introduction to Algorithms,CLRS,1990,45.0,Science,No Animal Farm,George Orwell,1945,5.0,Fiction,No Divan-e-Hafez,Hafez,1300,12.5,Poetry,Yes
<hr>
<h3>Grocery Inventory System Code</h3>
<p>This section contains code for a separate grocery inventory management system.</p>
<h4>Includes and Setup</h4>
<p><code>#include <iostream><br>include <fstream>
include <sstream>
include <vector>
include <string>
include <map>
<p><code>using namespace std;</code></p>
<h4>Grocery Category Enum and Map</h4>
<p>Enum for category types and corresponding name map:</p>
<pre><code>// Enum for category typesenum Category { Fruit, Vegetable, Dairy, InvalidCategory };
// Map to convert Category enum to string const map<Category, string> CategoryNames = { {Fruit, “Fruit”}, {Vegetable, “Vegetable”}, {Dairy, “Dairy”}, {InvalidCategory, “Invalid”} };
<h4>Grocery Class Definition</h4>
<pre><code>// Grocery classclass Grocery { private: string name; double price; int quantity; Category category;
public: Grocery() : name(“”), price(0.0), quantity(0), category(InvalidCategory) {} Grocery(const string& n, double p, int q, Category c) : name(n), price(p), quantity(q), category(c) {}
// Individual setters
void setName(const string& n) { name = n; }
void setPrice(double p) { price = p; }
void setQuantity(int q) { quantity = q; }
void setCategory(Category c) { category = c; }
// Global setter
void setAll(const string& n, double p, int q, Category c) {
setName(n);
setPrice(p);
setQuantity(q);
setCategory(c);
}
// Getters
string getName() const { return name; }
double getPrice() const { return price; }
int getQuantity() const { return quantity; }
Category getCategory() const { return category; }
double totalValue() const { return price * quantity; }
// Overloaded << operator
friend ostream& operator<<(ostream& os, const Grocery& g) {
os << g.name << " - " << g.price << " per unit - "
<< g.quantity << " units - Total: " << g.totalValue();
return os;
}};
<h4>Category Conversion and File Loading</h4>
<pre><code>// Convert string to Category enumCategory stringToCategory(const string& str) { for (const auto& pair : CategoryNames) { if (pair.second == str) return pair.first; } return InvalidCategory; }
// Load groceries from file bool loadGroceries(const string& filename, vector<Grocery>& groceries) { ifstream file(filename); if (!file.is_open()) { cout << “Error: Cannot open file ” << filename << endl; return false; }
string line;
while (getline(file, line)) {
stringstream ss(line);
string name, categoryStr;
double price;
int quantity;
if (!getline(ss, name, ',')) continue;
string priceStr, quantityStr;
if (!getline(ss, priceStr, ',')) continue;
if (!getline(ss, quantityStr, ',')) continue;
if (!getline(ss, categoryStr)) continue;
// Convert to proper types
try {
price = stod(priceStr);
quantity = stoi(quantityStr);
} catch (...) {
cout << "Error: Invalid number format for " << name << endl;
continue;
}
Category category = stringToCategory(categoryStr);
if (category == InvalidCategory) {
cout << "Error: Invalid category for " << name << endl;
continue;
}
Grocery g;
g.setAll(name, price, quantity, category);
groceries.push_back(g);
}
file.close();
return true;}
<h4>Display and Saving Functions</h4>
<pre><code>// Display groceries by categoryvoid displayGroceriesByCategory(const vector<Grocery>& groceries, Category category) { bool found = false; cout << “— Items in Category: ” << CategoryNames.at(category) << ” —” << endl; for (const auto& g : groceries) { if (g.getCategory() == category) { cout << g << endl; found = true; } } if (!found) cout << “No items found for this category.” << endl; }
// Save groceries to separate files using map void saveGroceriesByCategory(const vector<Grocery>& groceries) { map<Category, ofstream> files; files[Fruit].open(“Fruit.txt”); files[Vegetable].open(“Vegetable.txt”); files[Dairy].open(“Dairy.txt”);
for (const auto& g : groceries) {
auto it = files.find(g.getCategory());
if (it != files.end() && it->second.is_open()) {
it->second << g.getName() << "," << g.getPrice() << ","
<< g.getQuantity() << "," << CategoryNames.at(g.getCategory()) << "\n";
}
}
// Close all files
for (auto& f : files) f.second.close();
cout << "Groceries saved to category files." << endl;}
<h4>Grocery Main Function</h4>
<pre><code>int main() {
vector<Grocery> groceries;
if (!loadGroceries("Grocery.txt", groceries)) return 1;
cout << "Total number of items: " << groceries.size() << endl;
double totalValue = 0;
for (const auto& g : groceries) totalValue += g.totalValue();
cout << "Total stock value: " << totalValue << endl;
cout << "\nSelect a category to display (0: Fruit, 1: Vegetable, 2: Dairy): ";
int choice;
cin >> choice;
if (choice < 0 || choice > 2) {
cout << "Error: Invalid category selection." << endl;
} else {
Category selectedCategory = static_cast<Category>(choice);
displayGroceriesByCategory(groceries, selectedCategory);
}
saveGroceriesByCategory(groceries);
return 0;}
<h5>Example <code>Grocery.txt</code> Content</h5>
<pre><code>Apple,2.5,10,FruitBanana,2.0,7,Fruit Carrot,1.5,5,Vegetable Broccoli,2.0,4,Vegetable Milk,3.0,8,Dairy Cheese,5.0,3,Dairy Orange,1.8,12,Fruit
