CS 311 Fall 2020  >  Project 3


CS 311 Fall 2020
Project 3

Project 3 is due at 5 pm Thursday, September 24. It is worth 60 points.

Procedures

This project is to be done individually.

Turn in answers to the exercises below on the UA Blackboard Learn site, under Project 3 for this class.

Exercises (60 pts total)

General

This project 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 dp3.h and dp3.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. The following standards from part 4 now apply.

Standard 4A
Requirements on template parameter types must be documented.
Standard 4B
If a function is not a template and not a member of a class template, then the exceptions it throws must be documented.

You do not need to follow standards 4C or 4D.

In the files dp3.h and dp3.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 project.

Skeleton Files

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

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

Test Program

A single test program for all of the exercises is available: dp3_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.h, 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 should be obtained by including file llnode.h, 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 should 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 should return 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 should set 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.