Hello,
I have a programming assignment that should be done in C++ programming language.
Please find the attached files.
Calculator List
COP 4530 Programming Project 1
Instructions
For Programming Project 1, the student will implement a linked list based arithmetic calculator.
The calculator will be able to perform addition, subtraction, multiplication, and division. The
calculator will keep a running total of the operations completed, the number of operations
completed, and what those operations were. The calculator will also have an “undo” function
for removing the last operation. The calculator will also be able to output a string of the
operations completed so far with fixed precision.
The calculator (which must be called “CalcList”) has to be implemented using a singly, doubly, or
circularly linked list. Any projects that use the C++ Standard Library Lists or other sources to
implement the linked list will receive a zero. The calculator has to implement at least four
methods:
double total() const
This method returns the current total of the CalcList. Total should run as a constant time
operation. The program should not have to iterate through the entire list each time the total is
needed.
void newOperation(const FUNCTIONS func, const double operand)
Adds an operation to the CalcList and creates a new total. The operation alters total by using
the function with the operand. Example: newOperation(ADDITION, 10) => adds 10 to the
total.
void removeLastOperation()
Removes the last operation from the calc list and restores the previous total.
std::string toString(unsigned short precision) const
Returns a string of the list of operations completed so far formatted with a fixed point precision.
The form of the string should strictly be: “(step): (totalAtStep)(Function)(operand) = (newTotal)
\n”.
Example: toString(2) => “3: 30.00*1.00=30.00\n2: 10.00+20.00=30.00\n1:
0.00+10.00=10.00\n”
This project includes an abstract class for the CalcList from which to inherit. This abstract class
(CalcListInterface) contains the pure virtual version of all the required methods. This file also
includes a typedef of an enum used for the four arithmetic functions called FUNCTIONS.
This project will be tested using the Catch2 (https://github.com/catchorg/Catch2) test framework.
This framework only requires that a program include the header to run the test file. The test file
that will be used to grade the project is included and can be used to test your code before
submitting. For your convenience, this project contains the Catch2 header. The course
documents include a quick tutorial on how to use Catch2 and test files.
Examples
Below are some examples of how your code should run. The test file can also be used to get an
idea of how the code should run.
CalcList calc;
// Total == 0
calc.newOperation(ADDITION, 10);
// Total == 10
calc.newOperation(MULTIPLICATION, 5); // Total == 50
calc.newOperation(SUBTRACTION, 15);
// Total == 35
calc.newOperation(DIVISION, 7);
// Total == 5
calc.removeLastOperation();
// Total == 35
calc.newOperation(SUBTRACTION, 30);
// Total == 5
calc.newOperation(ADDITION, 5);
// Total == 10
calc.removeLastOperation();
// Total == 5
// Should Return:
// 4: 35.00-30.00=5.00
// 3: 50.00-15.00=35.00
// 2: 10.00*5.00=50.00
// 1: 0.00+10.00=10.00
std::cout
struct StringMaker {
static std::string convert(char const* str) {
return ::Catch::Detail::stringify(std::string{ str });
}
};
template
struct StringMaker {
static std::string convert(signed char const* str) {
return ::Catch::Detail::stringify(std::string{ reinterpret_cast(str) });
}
};
template
struct StringMaker {
static std::string convert(unsigned char const* str) {
return ::Catch::Detail::stringify(std::string{ reinterpret_cast(str) });
}
};
template
struct StringMaker {
static std::string convert(int value);
};
template
struct StringMaker {
static std::string convert(long value);
};
template
struct StringMaker {
static std::string convert(long long value);
};
template
struct StringMaker {
static std::string convert(unsigned int value);
};
template
struct StringMaker {
static std::string convert(unsigned long value);
};
template
struct StringMaker {
static std::string convert(unsigned long long value);
};
template
struct StringMaker {
static std::string convert(bool b);
};
template
struct StringMaker {
static std::string convert(char c);
};
template
struct StringMaker {
static std::string convert(signed char c);
};
template
struct StringMaker {
static std::string convert(unsigned char c);
};
template
struct StringMaker {
static std::string convert(std::nullptr_t);
};
template
struct StringMaker {
static std::string convert(float value);
};
template
struct StringMaker {
static std::string convert(double value);
};
template
struct StringMaker {
template
static std::string convert(U* p) {
if (p) {
return ::Catch::Detail::rawMemoryToString(p);
} else {
return “nullptr”;
}
}
};
template
struct StringMaker {
static std::string convert(R C::* p) {
if (p) {
return ::Catch::Detail::rawMemoryToString(p);
} else {
return “nullptr”;
}
}
};
#if defined(_MANAGED)
template
struct StringMaker {
static std::string convert( T^ ref ) {
return ::Catch::Detail::clrReferenceToString(ref);
}
};
#endif
namespace Detail {
template
std::string rangeToString(InputIterator first, InputIterator last) {
ReusableStringStream rss;
rss bool;
} // end namespace Catch
#define BENCHMARK( name ) \
for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() )
// end catch_benchmark.h
// start catch_interfaces_exception.h
// start catch_interfaces_registry_hub.h
#include
#include
namespace Catch {
class TestCase;
struct ITestCaseRegistry;
struct IExceptionTranslatorRegistry;
struct IExceptionTranslator;
struct IReporterRegistry;
struct IReporterFactory;
struct ITagAliasRegistry;
class StartupExceptionRegistry;
using IReporterFactoryPtr = std::shared_ptr;
struct IRegistryHub {
virtual ~IRegistryHub();
virtual IReporterRegistry const& getReporterRegistry() const = 0;
virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
};
virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
struct IMutableRegistryHub {
virtual ~IMutableRegistryHub();
virtual void registerReporter( std::string const& name, IReporterFactoryPtr const&
factory ) = 0;
virtual void registerListener( IReporterFactoryPtr const& factory ) = 0;
virtual void registerTest( TestCase const& testInfo ) = 0;
virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
virtual void registerTagAlias( std::string const& alias, std::string const& tag,
SourceLineInfo const& lineInfo ) = 0;
virtual void registerStartupException() noexcept = 0;
};
IRegistryHub& getRegistryHub();
IMutableRegistryHub& getMutableRegistryHub();
void cleanUp();
std::string translateActiveException();
}
// end catch_interfaces_registry_hub.h
#if defined(CATCH_CONFIG_DISABLE)
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName,
signature) \
static std::string translatorName( signature )
#endif
#include
#include
#include
namespace Catch {
using exceptionTranslateFunction = std::string(*)();
struct IExceptionTranslator;
using ExceptionTranslators = std::vector;
struct IExceptionTranslator {
virtual ~IExceptionTranslator();
virtual std::string translate( ExceptionTranslators::const_iterator it,
ExceptionTranslators::const_iterator itEnd ) const = 0;
};
struct IExceptionTranslatorRegistry {
virtual ~IExceptionTranslatorRegistry();
};
virtual std::string translateActiveException() const = 0;
class ExceptionTranslatorRegistrar {
template
class ExceptionTranslator : public IExceptionTranslator {
public:
ExceptionTranslator( std::string(*translateFunction)( T& ) )
: m_translateFunction( translateFunction )
{}
std::string translate( ExceptionTranslators::const_iterator it,
ExceptionTranslators::const_iterator itEnd ) const override {
try {
if( it == itEnd )
std::rethrow_exception(std::current_exception());
else
return (*it)->translate( it+1, itEnd );
}
catch( T& ex ) {
return m_translateFunction( ex );
}
}
protected:
std::string(*m_translateFunction)( T& );
};
}
public:
template
ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
getMutableRegistryHub().registerTranslator
( new ExceptionTranslator( translateFunction ) );
}
};
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
static std::string translatorName( signature ); \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ Catch::ExceptionTranslatorRegistrar
INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )(
&translatorName ); } \
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
static std::string translatorName( signature )
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
INTERNAL_CATCH_TRANSLATE_EXCEPTION2(
INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
// end catch_interfaces_exception.h
// start catch_approx.h
#include
#include
namespace Catch {
namespace Detail {
class Approx {
private:
bool equalityComparisonImpl(double other) const;
public:
explicit Approx ( double value );
static Approx custom();
template
Approx operator()( T const& value ) {
Approx approx( static_cast(value) );
approx.epsilon( m_epsilon );
approx.margin( m_margin );
approx.scale( m_scale );
return approx;
}
template
explicit Approx( T const& value ): Approx(static_cast(value))
{}
template
friend bool operator == ( const T& lhs, Approx const& rhs ) {
auto lhs_v = static_cast(lhs);
return rhs.equalityComparisonImpl(lhs_v);
}
template
friend bool operator == ( Approx const& lhs, const T& rhs ) {
return operator==( rhs, lhs );
}
template
friend bool operator != ( T const& lhs, Approx const& rhs ) {
return !operator==( lhs, rhs );
}
template
friend bool operator != ( Approx const& lhs, T const& rhs ) {
return !operator==( rhs, lhs );
}
template
friend bool operator rhs.m_value || lhs == rhs;
}
template
friend bool operator >= ( Approx const& lhs, T const& rhs ) {
return lhs.m_value > static_cast(rhs) || lhs == rhs;
}
template
Approx& epsilon( T const& newEpsilon ) {
double epsilonAsDouble = static_cast(newEpsilon);
if( epsilonAsDouble < 0 || epsilonAsDouble > 1.0 ) {
throw std::domain_error
( “Invalid Approx::epsilon: ” +
Catch::Detail::stringify( epsilonAsDouble ) +
“, Approx::epsilon has to be between 0 and 1” );
}
m_epsilon = epsilonAsDouble;
return *this;
}
template
Approx& margin( T const& newMargin ) {
double marginAsDouble = static_cast(newMargin);
if( marginAsDouble < 0 ) {
throw std::domain_error
( "Invalid Approx::margin: " +
Catch::Detail::stringify( marginAsDouble ) +
", Approx::Margin has to be non-negative." );
}
}
m_margin = marginAsDouble;
return *this;
template
Approx& scale( T const& newScale ) {
m_scale = static_cast(newScale);
return *this;
}
std::string toString() const;
}
private:
double m_epsilon;
double m_margin;
double m_scale;
double m_value;
};
template
struct StringMaker {
static std::string convert(Catch::Detail::Approx const& value);
};
} // end namespace Catch
// end catch_approx.h
// start catch_string_manip.h
#include
#include
namespace Catch {
bool startsWith( std::string const& s, std::string const& prefix );
bool startsWith( std::string const& s, char prefix );
bool endsWith( std::string const& s, std::string const& suffix );
bool endsWith( std::string const& s, char suffix );
bool contains( std::string const& s, std::string const& infix );
void toLowerInPlace( std::string& s );
std::string toLower( std::string const& s );
std::string trim( std::string const& str );
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const&
withThis );
struct pluralise {
pluralise( std::size_t count, std::string const& label );
friend std::ostream& operator match(arg))
return false;
}
return true;
}
std::string describe() const override {
std::string description;
description.reserve( 4 + m_matchers.size()*32 );
description += "( ";
bool first = true;
for( auto matcher : m_matchers ) {
if( first )
first = false;
else
description += " and ";
description += matcher->toString();
}
description += ” )”;
return description;
}
MatchAllOf& operator && ( MatcherBase const& other ) {
m_matchers.push_back( &other );
return *this;
}
std::vector m_matchers;
};
template
struct MatchAnyOf : MatcherBase {
bool match( ArgT const& arg ) const override {
for( auto matcher : m_matchers ) {
if (matcher->match(arg))
return true;
}
return false;
}
std::string describe() const override {
std::string description;
description.reserve( 4 + m_matchers.size()*32 );
description += “( “;
bool first = true;
for( auto matcher : m_matchers ) {
if( first )
first = false;
else
description += ” or “;
description += matcher->toString();
}
description += ” )”;
return description;
}
MatchAnyOf& operator || ( MatcherBase const& other ) {
m_matchers.push_back( &other );
return *this;
}
};
std::vector m_matchers;
template
struct MatchNotOf : MatcherBase {
MatchNotOf( MatcherBase const& underlyingMatcher ) :
m_underlyingMatcher( underlyingMatcher ) {}
bool match( ArgT const& arg ) const override {
return !m_underlyingMatcher.match( arg );
}
};
{
{
std::string describe() const override {
return “not ” + m_underlyingMatcher.toString();
}
MatcherBase const& m_underlyingMatcher;
template
MatchAllOf MatcherBase::operator && ( MatcherBase const& other ) const
return MatchAllOf() && *this && other;
}
template
MatchAnyOf MatcherBase::operator || ( MatcherBase const& other ) const
return MatchAnyOf() || *this || other;
}
template
MatchNotOf MatcherBase::operator ! () const {
return MatchNotOf( *this );
}
} // namespace Impl
} // namespace Matchers
using namespace Matchers;
using Matchers::Impl::MatcherBase;
} // namespace Catch
// end catch_matchers.h
// start catch_matchers_floating.h
#include
#include
namespace Catch {
namespace Matchers {
namespace Floating {
enum class FloatingPointKind : uint8_t;
struct WithinAbsMatcher : MatcherBase {
WithinAbsMatcher(double target, double margin);
bool match(double const& matchee) const override;
std::string describe() const override;
private:
double m_target;
double m_margin;
};
struct WithinUlpsMatcher : MatcherBase {
WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType);
bool match(double const& matchee) const override;
std::string describe() const override;
private:
double m_target;
int m_ulps;
FloatingPointKind m_type;
};
} // namespace Floating
// The following functions create the actual matcher objects.
// This allows the types to be inferred
Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff);
Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff);
Floating::WithinAbsMatcher WithinAbs(double target, double margin);
} // namespace Matchers
} // namespace Catch
// end catch_matchers_floating.h
// start catch_matchers_generic.hpp
#include
#include
namespace Catch {
namespace Matchers {
namespace Generic {
namespace Detail {
std::string finalizeDescription(const std::string& desc);
}
template
class PredicateMatcher : public MatcherBase {
std::function m_predicate;
std::string m_description;
public:
PredicateMatcher(std::function const& elem, std::string const&
descr)
:m_predicate(std::move(elem)),
m_description(Detail::finalizeDescription(descr))
{}
bool match( T const& item ) const override {
return m_predicate(item);
}
};
std::string describe() const override {
return m_description;
}
} // namespace Generic
// The following functions create the actual matcher objects.
// The user has to explicitly specify type to the function, because
// infering std::function is hard (but possible) and
// requires a lot of TMP.
template
Generic::PredicateMatcher Predicate(std::function const&
predicate, std::string const& description = “”) {
return Generic::PredicateMatcher(predicate, description);
}
} // namespace Matchers
} // namespace Catch
// end catch_matchers_generic.hpp
// start catch_matchers_string.h
#include
namespace Catch {
namespace Matchers {
namespace StdString {
struct CasedString
{
CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
std::string adjustString( std::string const& str ) const;
std::string caseSensitivitySuffix() const;
};
CaseSensitive::Choice m_caseSensitivity;
std::string m_str;
struct StringMatcherBase : MatcherBase {
StringMatcherBase( std::string const& operation, CasedString const&
comparator );
std::string describe() const override;
};
CasedString m_comparator;
std::string m_operation;
struct EqualsMatcher : StringMatcherBase {
EqualsMatcher( CasedString const& comparator );
bool match( std::string const& source ) const override;
};
struct ContainsMatcher : StringMatcherBase {
ContainsMatcher( CasedString const& comparator );
bool match( std::string const& source ) const override;
};
struct StartsWithMatcher : StringMatcherBase {
StartsWithMatcher( CasedString const& comparator );
bool match( std::string const& source ) const override;
};
struct EndsWithMatcher : StringMatcherBase {
EndsWithMatcher( CasedString const& comparator );
bool match( std::string const& source ) const override;
};
struct RegexMatcher : MatcherBase {
RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity );
bool match( std::string const& matchee ) const override;
std::string describe() const override;
private:
std::string m_regex;
CaseSensitive::Choice m_caseSensitivity;
};
} // namespace StdString
// The following functions create the actual matcher objects.
// This allows the types to be inferred
StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice
caseSensitivity = CaseSensitive::Yes );
StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice
caseSensitivity = CaseSensitive::Yes );
StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice
caseSensitivity = CaseSensitive::Yes );
StdString::StartsWithMatcher StartsWith( std::string const& str,
CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice
caseSensitivity = CaseSensitive::Yes );
} // namespace Matchers
} // namespace Catch
// end catch_matchers_string.h
// start catch_matchers_vector.h
#include
namespace Catch {
namespace Matchers {
namespace Vector {
namespace Detail {
template
size_t count(InputIterator first, InputIterator last, T const& item) {
size_t cnt = 0;
for (; first != last; ++first) {
if (*first == item) {
++cnt;
}
}
return cnt;
}
template
bool contains(InputIterator first, InputIterator last, T const& item) {
for (; first != last; ++first) {
if (*first == item) {
return true;
}
}
return false;
}
}
template
struct ContainsElementMatcher : MatcherBase {
ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
bool match(std::vector const &v) const override {
for (auto const& el : v) {
if (el == m_comparator) {
return true;
}
}
}
return false;
std::string describe() const override {
return “Contains: ” + ::Catch::Detail::stringify( m_comparator );
}
};
T const& m_comparator;
template
struct ContainsMatcher : MatcherBase {
ContainsMatcher(std::vector const &comparator) : m_comparator(
comparator ) {}
bool match(std::vector const &v) const override {
// !TBD: see note in EqualsMatcher
if (m_comparator.size() > v.size())
return false;
for (auto const& comparator : m_comparator) {
auto present = false;
for (const auto& el : v) {
if (el == comparator) {
present = true;
break;
}
}
if (!present) {
return false;
}
}
return true;
}
std::string describe() const override {
return “Contains: ” + ::Catch::Detail::stringify( m_comparator );
}
};
std::vector const& m_comparator;
template
struct EqualsMatcher : MatcherBase {
EqualsMatcher(std::vector const &comparator) : m_comparator( comparator
) {}
bool match(std::vector const &v) const override {
// !TBD: This currently works if all elements can be compared using !=
// – a more general approach would be via a compare template that defaults
// to using !=. but could be specialised for, e.g. std::vector etc
// – then just call that directly
if (m_comparator.size() != v.size())
return false;
for (std::size_t i = 0; i < v.size(); ++i)
if (m_comparator[i] != v[i])
return false;
return true;
};
}
std::string describe() const override {
return "Equals: " + ::Catch::Detail::stringify( m_comparator );
}
std::vector const& m_comparator;
template
struct UnorderedEqualsMatcher : MatcherBase {
UnorderedEqualsMatcher(std::vector const& target) : m_target(target) {}
bool match(std::vector const& vec) const override {
// Note: This is a reimplementation of std::is_permutation,
//
because I don't want to include inside the common path
if (m_target.size() != vec.size()) {
return false;
}
auto lfirst = m_target.begin(), llast = m_target.end();
auto rfirst = vec.begin(), rlast = vec.end();
// Cut common prefix to optimize checking of permuted parts
while (lfirst != llast && *lfirst != *rfirst) {
++lfirst; ++rfirst;
}
if (lfirst == llast) {
}
return true;
for (auto mid = lfirst; mid != llast; ++mid) {
// Skip already counted items
}
}
if (Detail::contains(lfirst, mid, *mid)) {
continue;
}
size_t num_vec = Detail::count(rfirst, rlast, *mid);
if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) {
return false;
}
return true;
std::string describe() const override {
return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
}
private:
std::vector const& m_target;
};
} // namespace Vector
// The following functions create the actual matcher objects.
// This allows the types to be inferred
template
Vector::ContainsMatcher Contains( std::vector const& comparator ) {
return Vector::ContainsMatcher( comparator );
}
template
Vector::ContainsElementMatcher VectorContains( T const& comparator ) {
return Vector::ContainsElementMatcher( comparator );
}
template
Vector::EqualsMatcher Equals( std::vector const& comparator ) {
}
return Vector::EqualsMatcher( comparator );
template
Vector::UnorderedEqualsMatcher UnorderedEquals(std::vector const&
target) {
return Vector::UnorderedEqualsMatcher(target);
}
} // namespace Matchers
} // namespace Catch
// end catch_matchers_vector.h
namespace Catch {
template
class MatchExpr : public ITransientExpression {
ArgT const& m_arg;
MatcherT m_matcher;
StringRef m_matcherString;
public:
MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString )
: ITransientExpression{ true, matcher.match( arg ) },
m_arg( arg ),
m_matcher( matcher ),
m_matcherString( matcherString )
{}
};
void streamReconstructedExpression( std::ostream &os ) const override {
auto matcherAsString = m_matcher.toString();
os