CS 311 Fall 2024  >  Assignment 3


CS 311 Fall 2024
Assignment 3

Assignment 3 is due at 5 pm Thursday, September 26. It is worth 65 points.

Procedures

This assignment is to be done individually.

Turn in answers to the exercises below on the UA Canvas site, under Assignment 3 for this class.

Exercises (65 pts total)

General

This assignment is to be done individually.

In each of the following exercises, you are to write a function or function template. All functions & function templates are to be in the files da3.hpp and da3.cpp. The templates must be implemented entirely in the header file. The non-templates must be prototyped in the header and implemented in the source, as usual.

Be sure to follow the coding standards. Standards 4A, 4B, and 4C now apply. You do not yet need to follow standards 4D or 4E.

In the files da3.hpp and da3.cpp, you may include any other functions or classes that you wish. These will not be tested; however, they must follow the coding standards. Also, use of the C++ Standard Library is legal in this assignment.

Skeleton Files

I have provided incomplete “skeleton” files da3.hpp and da3.cpp; these are in the Git repository. You may use these as the basis for your own work, if you wish.

Your project files will also include llnode.hpp, which is in the Git repository. File llnode.hpp must not be modified!

Test Program

A single test program for all of the exercises is available: da3_test.cpp. If you compile and run the test program (unmodified!) with your code, then it will test whether your code works properly.

Note that your code will not compile with the test program unless all required functions exist. Therefore, you must write dummy versions of all functions—at least—or your work will not be graded. (The skeleton files make this easy; see above.)

The test program requires doctest.h, the header for the doctest unit-testing framework, version 2.

Do not turn in the test program, file llnode.hpp, or the doctest framework.

Exercise A — Linked List Lookup

Purpose

In this exercise you will write code to deal with a Singly Linked List. The code will signal an error condition—if one occurs—by throwing an exception.

Instructions

Write a function template lookup, prototyped as follows.

[C++]

template <typename ValueType>
ValueType lookup(const LLNode<ValueType> * head,
                 std::size_t index);

The definition of LLNode must be obtained by including file llnode.hpp, which is in the Git repository.

Exercise B — Did It Throw?

Purpose

This exercise is all about calling code that may throw an exception, and catching the exception appropriately.

Instructions

Write a function (not a template) didItThrow, prototyped as

void didItThrow(const std::function<void()> & ff,
                bool & threw);

std::function is declared in the standard header <functional>.

Function didItThrow is given either a function pointer, or an object that acts like a function (that is, which has operator() defined). It then calls this function with no parameters. If the function throws, then it sets parameter threw to true, and passes the exception on to the caller. If the function does not throw, then it sets paramete threw to false, and returns normally.

Example usage:

void myFunc()
{ throw std::exception("Oh no!"); }

bool result;
try {
    didItThrow(myFunc, result);
{
catch (std::exception & e) {
    if (result)
        std::cout << "SUCCESS" << std::endl;
    else
        std::cout << "FAILURE" << std::endl;
}

The above will print “SUCCESS

Other requirements:

Exercise C — Check Sorted

Purpose

In this exercise you will write a function that takes iterators as parameters and processes a range of data.

Instructions

Write a function template checkSorted, prototyped as

[C++]

template <typename FDIter>
bool checkSorted(FDIter first,
                 FDIter last);

Parameters first and last are two forward iterators specifying a range in the standard manner. Function checkSorted returns true if the range is sorted in ascending order by “<”, and false otherwise.

Example usage:

[C++]

vector<string> v {
    "aardvark",
    "dog",
    "dog",
    "llama"
};
bool result = checkSorted(v.begin(), v.end());

The above sets the variable result to true, since the given vector is in ascending order.

You may not modify the values in the range.

Exercise D — Recursive GCD

Purpose

In this exercise, you will implement a simple recursive algorithm.

Background

If \(a\) and \(b\) are two nonnegative integers, not both zero, then the greatest common divisor (GCD) of \(a\) and \(b\) is the greatest integer that evenly divides both \(a\) and \(b\).

For example, the GCD of \(910\) and \(42\) is \(14\), since both \(910\) and \(42\) are divisible by \(14\), and this is not true of any integer greater than \(14\). We write \(\gcd(910, 42) = 14\).

The GCD can be computed quickly based on the following rules.

  1. If \(a = 0\), then \(\gcd(a,b) = b\).
  2. Otherwise, if \(a > b\), then \(\gcd(a,b) = \gcd(b,a)\).
  3. Otherwise, \(\gcd(a,b) = \gcd(b \bmod a, a)\).

Above, \(b \bmod a\) is the remainder when \(b\) is divided by \(a\).

Here is how we would apply the above rules to compute \(\gcd(910, 42)\).

\[ \begin{align*} \gcd(910, 42) &= \gcd(42, 910) &&\text{by Rule 2}\\ &= \gcd(28, 42) &&\text{by Rule 3 [\(910 \bmod 42 = 28\)]}\\ &= \gcd(14, 28) &&\text{by Rule 3 [\(42 \bmod 28 = 14\)]}\\ &= \gcd(0, 14) &&\text{by Rule 3 [\(28 \bmod 14 = 0\)]}\\ &= 14 &&\text{by Rule 1} \end{align*} \]

The above method is a version of the Euclidean Algorithm, so called because it appeared in a text by the ancient Greek mathematician Euclid, written around 300 BC. It is thus among the oldest algorithms known.

Instructions

Write a function (NOT a template) gcd, prototyped as

int gcd(int a,
        int b);

Note that, in C++, \(b \bmod a\) is computed using the % operator: b % a.