I am trying to modify my function add() so it throws an exception every time an array passed already matches what is in the set. The code compiles but my visual studio keeps throwing an "unhandled exception" error and am at a lost point. Here is what we are mainly focusing on.
#ifndef SET_INTERFACE
#define SET_INTERFACE
#include <vector>
#include <algorithm>
#include <iterator>
namespace cs_set {
template<class ItemType>
class SetInterface
{
public:
/** Gets the current number of entries in this bag.
@return The integer number of entries currently in the bag. */
virtualint getCurrentSize() const = 0;
/** Sees whether this bag is empty.
@return True if the bag is empty, or false if not. */
virtualbool isEmpty() const = 0;
/** Adds a new entry to this bag.
@post If successful, newEntry is stored in the bag and
the count of items in the bag has increased by 1.
@param newEntry The object to be added as a new entry.
@return True if addition was successful, or false if not. */
virtualvoid add(const ItemType& newEntry) = 0;
/** Removes one occurrence of a given entry from this bag,
if possible.
@post If successful, anEntry has been removed from the bag
and the count of items in the bag has decreased by 1.
@param anEntry The entry to be removed.
@return True if removal was successful, or false if not. */
virtualvoid remove(const ItemType& anEntry) = 0;
/** Removes all entries from this bag.
@post Bag contains no items, and the count of items is 0. */
virtualvoid clear() = 0;
/** Counts the number of times a given entry appears in this bag.
@param anEntry The entry to be counted.
@return The number of times anEntry appears in the bag. */
// virtual int getFrequencyOf(const ItemType& anEntry) const = 0;
/** Tests whether this bag contains a given entry.
@param anEntry The entry to locate.
@return True if bag contains anEntry, or false otherwise. */
virtualbool contains(const ItemType& anEntry) const = 0;
/** Empties and then fills a given vector with all entries that
are in this bag.
@return A vector containing all the entries in the bag. */
virtual std::vector<ItemType> toVector() const = 0;
/** Destroys this bag and frees its assigned memory. (See C++ Interlude 2.) */
virtual ~SetInterface() { }
};
}
#endif
#ifndef ARRAY_SET_
#define ARRAY_SET_
#include <algorithm>
#include <iterator>
#include "SetInterface.h"
namespace cs_set {
template<class ItemType>
class ArraySet : public SetInterface<ItemType>
{
public:
typedef ItemType value_type;
class DuplicateItemError {};
class ItemNotFoundError {};
ArraySet();
int getCurrentSize() const;
bool isEmpty() const;
void add(const ItemType& newEntry);
void remove(const ItemType& anEntry);
void clear();
bool contains(const ItemType& anEntry) const;
//int getFrequencyOf(const ItemType& anEntry) const;
std::vector<ItemType> toVector() const;
private:
staticconstint DEFAULT_CAPACITY = 6;
ItemType items[DEFAULT_CAPACITY];
int itemCount;
int maxItems;
// Returns either the index of the element in the array items that
// contains the given target or -1, if the array does not contain
// the target.
int getIndexOf(const ItemType& target) const;
};
}
#include "ArraySet.cpp"
#endif
Change the name of ArraySet.cpp to some other extension. I like ".tcpp" ,myself.
A .cpp is intended to be compiled. Your ArraySet.cpp is template code that cannot be compiled until it is instantiated. I like how you include this file from your ArraySet.h file, but do yourself a favor and don't use .cpp as an extension.
p.s. I don't know if that will fix your problem, but it's a start.
@doug4 i excluded that file from my visual studio so it would compile but the problem is in the add() function itself it keeps throwing an unhandled exception error like this one,
1 2 3 4 5
Unhandled exception at 0x74E440B2 in ArraySetV1.exe: Microsoft C++ exception:
cs_set::ArraySetstd::basic_string<char,std::char_traits<char,std::allocator >
>::DuplicateItemError at memory location 0x00AFF577.
Any guidance on fixing the function so it can throw the exception like it is supposed to would be appreciated.
You didn't put your calls to add inside a try/catch block in line 33. The attempt to add the last string is a duplicate of the first string, so the add function throws the exception. Because there's no try/catch, the exception is unhandled.
Edit: BTW, line 47 will not cause an exception as you expect because you never check to see if adding the item in line 14 of ArraySet.cpp is out of bounds.
Oh okay, i understand that now it iterates through and sees that the last time it is called it is a pre existing string. Would I need to add another try/catch in the loop to prevent getting a unhandled exception error?
std::string items[] = {"one", "two", "three", "four", "five", "one"};
cout << "Add 6 items to the set: " << endl;
for (int i = 0; i < 6; i++) {
try {
set.add(items[i]);
cout << "Exception?" << endl;
}
catch (ArraySet<string>::DuplicateItemError e)
{
cout << "EXCEPTION!" << endl;
}
}
The output is
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Testing the Array-Based Set:
The initial set is empty.
isEmpty: returns 1; should be 1 (true)
The set contains 0 items:
Add 6 items to the set:
EXCEPTION!
EXCEPTION!
EXCEPTION!
EXCEPTION!
EXCEPTION!
EXCEPTION!
The set contains 0 items:
isEmpty: returns 1; should be 0 (false)
getCurrentSize: returns 0; should be 6
All done!
The try/catch apparently outputs that every element in the array is a duplicate??????
Even though the only ones that should be a duplicate should be the first element and the last...
Testing the Array-Based Set:
The initial set is empty.
isEmpty: returns 1; should be 1 (true)
The set contains 0 items:
Add 6 items to the set:
one
two
three
four
five
IT IS A DUPLICATE!
The set contains 5 items:
one two three four five
isEmpty: returns 0; should be 0 (false)
getCurrentSize: returns 5; should be 6
All done!
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
Press any key to close this window . . .
I did not change anything in void setTester but instead in the add() function of the class I changed from using the auto result1 to this instead:
Way to go! It feels good to fix a bug in your code, doesn't it?
Something you might be interested in: When printing out Boolean values, if you want to see "true" or "false", you can use the std::boolalpha stream manipulator found in <iomanip>. Call it once on a stream, and all prints (actually stream insertions) of bools onto that stream will show up as the text values.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#include <iostream>
#include <iomanip>
int main()
{
bool a = true;
bool b = false;
std::cout << "Before boolalpha" << std::endl;
std::cout << a << std::endl;
std::cout << b << std::endl;
std::cout << std::boolalpha;
std::cout << "After boolalpha" << std::endl;
std::cout << a << std::endl;
std::cout << b << std::endl;
}