Lecture 27: Final exam review | CMSC 240 Software Systems Development - Fall 2023

Lecture 27: Final exam review

Objective

Review the course topics and content that will be assessed on the final exam.

Lecture Topics

Exam Details

if (course_evaluation_response_rate == 100%)
{
    students_allowed_one_sheet_of_notes = true
}

Section 2 10:30 - 11:45am
https://p3.courseval.net/etw/ets/et.asp?nxappid=0E2&nxmid=GetSurveyForm&wsedrq=W0PMDH7373

Section 1 1:30 - 2:45pm
https://p3.courseval.net/etw/ets/et.asp?nxappid=0E2&nxmid=GetSurveyForm&wsedrq=W0PMDH6372

What to Study

Practice Questions

Makefiles

Consider the following C++ code.

main.cpp

// main.cpp - Main function for the Library Management System

#include "Library.h"

int main() 
{
    Library library;
    library.addBook(Book("1984"));
    library.addBook(Book("Brave New World"));

    library.showBooks();
    return 0;
}

Book.h

// Book.h - Header file for the Book class

#ifndef BOOK_H
#define BOOK_H

#include <string>

class Book 
{
public:
    Book(const std::string& title);
    std::string getTitle() const;
private:
    std::string title;
};

#endif // BOOK_H

Book.cpp

// Book.cpp - Implementation of the Book class

#include "Book.h"

Book::Book(const std::string& title) : title(title) {}

std::string Book::getTitle() const 
{
    return title;
}

Library.h

// Library.h - Header file for the Library class

#ifndef LIBRARY_H
#define LIBRARY_H

#include <vector>
#include "Book.h"

class Library 
{
public:
    void addBook(const Book& book);
    void showBooks() const;
private:
    std::vector<Book> books;
};

#endif // LIBRARY_H

Library.cpp

// Library.cpp - Implementation of the Library class

#include <iostream>
#include "Library.h"

using namespace std;

void Library::addBook(const Book& book) 
{
    books.push_back(book);
}

void Library::showBooks() const 
{
    for (Book& book : books) 
    {
        cout << book.getTitle() << endl;
    }
}

C++ Exception handling with try/catch

Consider the following C++ code.

main.cpp

// Will throw an exception on bad input.
int area(int length, int width)     
{
    // Validate the inputs.
    if(length <= 0 || width <= 0)
    { 
        // Throw an invalid argument exception.
        throw invalid_argument{"Bad argument to area()"};
    }

    int result = length * width;

    // Check for an overflow in the result.
    if (result / length != width)
    {
        // Throw an overflow error exception.
        throw overflow_error{"Overflow occurred in area()"};
    }

    return result;
}


int main()
{
    int l;
    int w;
    cout << "Enter values for length and width:" << endl;
    cin >> l >> w;
    
    int result = area(l, w);
    cout << "Area == " << result << endl;

    return 0;
}

C++ Smart pointers

Consider the following C++ code.

main.cpp

#include <iostream>
#include <memory>
using namespace std;

class Item 
{
public:
    Item() { cout << "Item constructed" << endl; }
    ~Item() { cout << "Item destroyed" << endl; }
};

void process(shared_ptr<Item>& sharedItem) 
{
    shared_ptr<Item> localShared = sharedItem;

    cout << "Reference count inside function = " << localShared.use_count() << endl;
}

int main() 
{
    shared_ptr<Item> myItem{new Item()};

    cout << "Reference count in main, before function call = " << myItem.use_count() << endl;

    process(myItem);

    cout << "Reference count in main, after function call = " << myItem.use_count() << endl;

    return 0;
}

C++ Templates

Consider the following C++ code.

main.cpp

#include <iostream>
#include <vector>
using namespace std;

double averageVector(vector<double> vec) 
{
    if (vec.empty()) 
    {
        // Return 0 for empty vector
        return 0.0; 
    }

    double sum = 0.0;

    for (double num : vec) 
    {
        sum += num;
    }

    return sum / vec.size();
}

int main() 
{
    vector<double> vec = {1.5, 2.5, 3.5, 4.5, 5.5};
    cout << "Average of vector elements is " << averageVector(vec) << endl;
    return 0;
}

Regular Expressions

Consider the following C++ code.

main.cpp

/*
    Phone Number Rules:

    For this exercise, we'll consider North American phone numbers, 
    which typically follow the format (NPA) NXX-XXXX, where:

        NPA (Numbering Plan Area) is the area code.
        NXX is the central office code, and it must not start with 0 or 1.
        XXXX is the line number.

    Add a regex pattern that will match the phone number rules above as valid.
*/

#include <iostream>
#include <regex>
#include <string>
using namespace std;

int main() 
{
    string phone;
    cout << "Enter a phone number: ";
    getline(cin, phone);

    // Define a regular expression pattern for phone number validation
    regex pattern{R"( ...REGULAR EXPRESSION HERE... )"};

    if (regex_match(phone, pattern)) 
    {
        cout << "Valid phone number!" << endl;
    } 
    else
    {
        cout << "Invalid phone number." << endl;
    }

    return 0;
}

Unit Testing

Consider the following C++ code.

test.cpp

#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN

#include <stdexcept>
#include <vector>
#include "doctest.h"


using namespace std;

// Function prototype
int maxElement(vector<int> nums); 

TEST_CASE("Testing the maxElement function") 
{
    CHECK(maxElement({1, 2, 3, 4, 5}) == 5);
    CHECK(maxElement({-10, -20, -30, -40, -5}) == -5);
    CHECK(maxElement({100, 200, 300, 400, 500}) == 500);
    CHECK(maxElement({42}) == 42);
    CHECK_THROWS_AS(maxElement({}), invalid_argument);
}

Unit Testing

Consider the following C++ code.

test.cpp

#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN

#include <stdexcept>
#include "doctest.h"

using namespace std;

string numberClassifier(int number) 
{
    if (number == 0) 
    {
        throw invalid_argument("Number must not be zero");
    } 
    else if (number > 0) 
    {
        if (number % 2 == 0) 
        {
            return "Even Positive";
        } 
        else 
        {
            return "Odd Positive";
        }
    } 
    else 
    { 
        if (number % 2 == 0) 
        {
            return "Even Negative";
        } 
        else 
        {
            return "Odd Negative";
        }
    }
}

In the space below write a unit test that will provide 100% statement coverage of the numberClassifier function.

Git

Consider the following Git commands.

$ git init
$ git branch -m main
$ echo "Line One of Readme File" > README.md 
$ git add README.md
$ git commit -m "Initial Commit"
$ echo "Line Two of Readme File" >> README.md 
$ git add README.md
$ git commit -m "Second Commit"
$ git branch my_feature_branch
$ git checkout my_feature_branch
$ echo "Line Three of Readme File" >> README.md
$ git add README.md
$ git commit -m "Initial Feature Branch Commit"
$ git checkout main
$ echo "New file" > anotherfile.txt
$ git add anotherfile.txt
$ git commit -m "Third Commit"
$ git merge my_feature_branch -m "Merging Feature"

Object-oriented programming: Inheritance

Consider the following C++ code.

main.cpp

#include <iostream>

using namespace std;

class Square 
{
public:
    Square(double s) : side(s) { }

    double getArea() 
    {
        return side * side;
    }

private:
    double side;
};


class Box : public Square 
{
public:
    Box(double s, double h) : Square(s), height(h) { }

    double getVolume()
    {
        // Base square area * height
        return getArea() * height; 
    }

private:
    double height;
};


int main() 
{
    // Example: Box with side 5 and height 10
    Box myBox(5, 10); 
    cout << "Area of the base square: " << myBox.getArea() << endl;
    cout << "Volume of the box: " << myBox.getVolume() << endl;
    return 0;
}

Object-oriented programming

What are the four most important concepts in object-oriented programming? Describe them in detail.