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 &lt;iostream&gt;<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 &lt;&lt;
friend ostream& operator<<(ostream& os, const Book& b) {
    os << "[" << b.getType() << "] "
       &lt;&lt; b.title &lt;&lt; ", "
       &lt;&lt; b.author &lt;&lt; ", "
       &lt;&lt; b.year &lt;&lt; ", "
       &lt;&lt; b.price &lt;&lt; ", "
       &lt;&lt; genreToString(b.genre) &lt;&lt; ", "
       &lt;&lt; (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&lt;Book&gt; b) {
    books[++position] = b;
    cout &lt;&lt; "Inserted at position " &lt;&lt; position &lt;&lt; endl;
}

// Questions 4 & 5: load file with error handling
void loadFromFile(const string&amp; filename) {
    ifstream file(filename);
    if (!file) {
        cerr &lt;&lt; "Error: Library.txt not found. Please create it before running." &lt;&lt; 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&lt;Book&gt; book(new Printed("DefaultPublisher"));
            book-&gt;setAll(title, author, year, price, g, borrowed);

            addBook(book);
        } catch (const exception&amp; e) {
            cerr &lt;&lt; "Error processing record: " &lt;&lt; line &lt;&lt; " (Reason: " &lt;&lt; e.what() &lt;&lt; ")" &lt;&lt; endl;
        } catch (...) {
            cerr &lt;&lt; "Error processing record: " &lt;&lt; line &lt;&lt; endl;
        }
    }
}

// Question 6: Display oldest book
void displayOldestBook() const {
    if (books.empty()) {
        cout &lt;&lt; "Library is empty." &lt;&lt; endl;
        return;
    }
    auto oldest = min_element(
        books.begin(), books.end(),
        [](const pair&lt;const int, shared_ptr&lt;Book&gt; &gt;&amp; a,
           const pair&lt;const int, shared_ptr&lt;Book&gt; &gt;&amp; b) {
            return a.second-&gt;getYear() &lt; b.second-&gt;getYear();
        }
    );
    cout &lt;&lt; "Oldest book: " &lt;&lt; *oldest-&gt;second &lt;&lt; endl;
}

// Question 7: Display by genre
void displayByGenre(Genre g) const {
    cout &lt;&lt; "--- Books in Genre: " &lt;&lt; genreToString(g) &lt;&lt; " ---" &lt;&lt; endl;
    bool found = false;
    for (const auto&amp; pair : books) {
        if (pair.second-&gt;getGenre() == g)
            cout &lt;&lt; *(pair.second) &lt;&lt; endl;
            found = true;
    }
    if (!found) cout &lt;&lt; "No books found for this genre." &lt;&lt; endl;
}

// Question 8: Save borrowed books to file
void saveBorrowed(const string&amp; filename) const {
    ofstream out(filename);
    if (!out) {
        cerr &lt;&lt; "Error: Could not open " &lt;&lt; filename &lt;&lt; " for writing." &lt;&lt; endl;
        return;
    }
    for (const auto&amp; pair : books) {
        if (pair.second-&gt;isBorrowed())
            out &lt;&lt; *(pair.second) &lt;&lt; "\n"; // Use newline character explicitly
    }
    cout &lt;&lt; "Borrowed books saved to " &lt;&lt; filename &lt;&lt; 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 &lt;&lt; "\nSelect genre (Science/Fiction/Poetry): ";
string g;
cin &gt;&gt; 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,No

1984,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 &lt;iostream&gt;<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 types

enum 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 class

class 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&amp; 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&amp; 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 &lt;&lt; operator
friend ostream&amp; operator&lt;&lt;(ostream&amp; os, const Grocery&amp; g) {
    os &lt;&lt; g.name &lt;&lt; " - " &lt;&lt; g.price &lt;&lt; " per unit - "
       &lt;&lt; g.quantity &lt;&lt; " units - Total: " &lt;&lt; g.totalValue();
    return os;
}

};

<h4>Category Conversion and File Loading</h4>
<pre><code>// Convert string to Category enum

Category 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 &lt;&lt; "Error: Invalid number format for " &lt;&lt; name &lt;&lt; endl;
        continue;
    }

    Category category = stringToCategory(categoryStr);
    if (category == InvalidCategory) {
        cout &lt;&lt; "Error: Invalid category for " &lt;&lt; name &lt;&lt; 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 category

void 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&amp; g : groceries) {
    auto it = files.find(g.getCategory());
    if (it != files.end() &amp;&amp; it-&gt;second.is_open()) {
        it-&gt;second &lt;&lt; g.getName() &lt;&lt; "," &lt;&lt; g.getPrice() &lt;&lt; ","
                 &lt;&lt; g.getQuantity() &lt;&lt; "," &lt;&lt; CategoryNames.at(g.getCategory()) &lt;&lt; "\n";
    }
}

// Close all files
for (auto&amp; f : files) f.second.close();
cout &lt;&lt; "Groceries saved to category files." &lt;&lt; endl;

}

<h4>Grocery Main Function</h4>
<pre><code>int main() {
vector&lt;Grocery&gt; groceries;

if (!loadGroceries("Grocery.txt", groceries)) return 1;

cout &lt;&lt; "Total number of items: " &lt;&lt; groceries.size() &lt;&lt; endl;
double totalValue = 0;
for (const auto&amp; g : groceries) totalValue += g.totalValue();
cout &lt;&lt; "Total stock value: " &lt;&lt; totalValue &lt;&lt; endl;

cout &lt;&lt; "\nSelect a category to display (0: Fruit, 1: Vegetable, 2: Dairy): ";
int choice;
cin &gt;&gt; choice;

if (choice &lt; 0 || choice &gt; 2) {
    cout &lt;&lt; "Error: Invalid category selection." &lt;&lt; endl;
} else {
    Category selectedCategory = static_cast&lt;Category&gt;(choice);
    displayGroceriesByCategory(groceries, selectedCategory);
}

saveGroceriesByCategory(groceries);

return 0;

}

<h5>Example <code>Grocery.txt</code> Content</h5>
<pre><code>Apple,2.5,10,Fruit

Banana,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