For this program, I wanted to create a SET class that contains a mathematical set of positive numbers and no duplicates. After I had created the SET class, I created overloaded operators for + and * to add two sets together and to find the intersecting numbers of two sets respectively. However after I started doing testing for my code, I noticed that the + and * overloaded operators did not work on two sets containing numbers unless I created a new SET to output the data. For example I had to do:
SET set3 = set1 + set2;
cout << set3;
Rather than being able to just do:
cout << set1 + set2;
I was able to output the above code only if both sets were empty or if 1 set was filled and the other was empty. I'm not sure what I am doing wrong to make it so two filled sets cannot be output. I broke my code up into three files. Here is the header file:
//CSCI 205
//Brett Milinski
//Assignment 2 - The Set Class
//This problem wants us to create a set class to hold a mathematical set of integers and can later be manipulated to implement the Sieve of Eratosthenes method for computing prime numbers
#ifndef SET_H
#define SET_H
#include<iostream>
using namespace std;
class SET
{
private: int a[50];
int length;
const int SIZE = 50;
public: SET();
SET(int a, int b);
void print(ostream &os);
void insert(int x);
void erase(int x);
int searchList(int a[], int length, int x);
int addSearchList(int a[], int length, int x);
friend SET& operator+(SET& a, SET& b);
friend SET& operator*(SET& a, SET& b);
friend ostream& operator<<(ostream& os, SET& a);
SET& sieveOfEratosthenes(int n);
};
#endif
Here is the set.cpp file that defines the methods:
//CSCI 205
//Brett Milinski
//Assignment 2 - The Set Class
//This problem wants us to create a set class to hold a mathematical set of integers and can later be manipulated to implement the Sieve of Eratosthenes method for computing prime numbers
#include"set.h"
#include<iostream>
using namespace std;
SET::SET() //default constructor
{
length = 0;
}
SET::SET(int start, int end) //overloaded constructor
{
length = end - start + 1; //end of range of numbers to be input
if (length <= SIZE) //range isn't too big for the array
{
for (int x = 0; x < length; x++)
{
a[x] = start;
start++;
}
}
}
void SET::insert(int x) //function to insert numbers from the array
{
bool inserted = false;
for (int i = 0; i < length; i++) //check to see if the value is already in the set, if so, don't add
{
if (a[i] == x)
{
inserted = true;
cout << "Sorry, the SET already contains that number." << endl;
}
}
if (inserted == false) //the SET does not contain the number that is trying to be inserted
{
int check = addSearchList(a, length, x); //check the position of where to add the value
if (length == SIZE) //check to see if the array is already full
{
cout << "You cannot add anymore elements to this array because it is full." << endl;
}
else if (check == length) //check to see if it is added at the end
{
length++; //make the array one size bigger to make room for the addition
a[length - 1] = x; //add the value to the end
}
else
{
length++; //make the array one size bigger to make room for the addition
for (int i = length - 1; i >= check; i--) //start at the bottom and move up towards where the new value should be
{
a[i] = a[i - 1]; //ripple down
}
a[check] = x; //add in the new value
}
}
}
void SET::erase(int x) //function to erase numbers from the array
{
int check = searchList(a, length, x); //check to see what the position is
if (length == 0) //check to see if the array is empty before deleting anything
{
cout << "The array is empty and therefore nothing can be deleted from the elements." << endl;
}
else if (check != -1) //check to see if the value is found
{
for (int x = check; x < length - 1; x++)
{
a[x] = a[x + 1]; //ripples every element up
}
length--; //makes the array one size smaller to accomadate the deletion
}
else
{
cout << "The value entered is not in the array." << endl; //the value being checked for does not exist
}
}
void SET::print(ostream &os) //function to output the values of the array
{
os << "The contents of the set are:" << endl;
for (int x = 0; x < length; x++)
{
os << a[x] << " ";
}
os << endl;
}
int SET::searchList(int a[], int length, int x) //a search for the erase function
{
int index = 0; // Used as a subscript to search array
int position = -1; // Used to record position of search value
bool found = false; // Flag to indicate if the value was found
while (index < length && a[index] <= x && !found)
{
if (a[index] == x) // If the value is found
{
found = true; // Set the flag
position = index; // Record the value's subscript
}
index++; // Go to the next element
}
return position; // Return the position, or -1
}
int SET::addSearchList(int a[], int length, int x) //a search for the insert function
{
int index = 0; // Used as a subscript to search array
int position = -1; // Used to record position of search value
while (index < length && a[index] <= x)
{
index++; // Go to the next element
}
if (index == length) //all the values were smaller than the number trying to be added
{
position = length; //position is at the end of the array
}
else
{
position = index; //found where to add the new element
}
return position; // Return the position, or currentSize
}
//calls the print function to print to the output stream
ostream& operator<<(ostream& os, SET& a)
{
a.print(os);
return os;
}
//join the two sets together
SET& operator+(SET& a, SET& b)
{
SET added;//empty set to add to
if (a.length == 0 && b.length != 0) //for empty sets
{
return b;
}
else if (b.length == 0 && a.length != 0) //for empty sets
{
return a;
}
else
{
for (int x = 0; x < a.length; x++) //add in the elements from the first set
{
added.insert(a.a[x]);
cout << added.a[x] << endl;
}
for (int x = 0; x < b.length; x++) //add in the elements from the second set
{
added.insert(b.a[x]);
cout << b.a[x] << endl;
}
return added; //returns the added set
}
}
//find what the two sets have in common
SET& operator*(SET& a, SET& b)
{
int shortestLength = 0;
SET inCommon;
if (a.length < b.length) //find the shortest length
{
shortestLength = a.length;
}
else
{
shortestLength = b.length;
}
//search through and find the highest common number between the sets
for (int x = 0; x < shortestLength; x++)
{
for (int i = 0; i < shortestLength; i++)
{
if (a.a[i] == b.a[x]) //see if it shares it and has it in common
{
inCommon.insert(a.a[i]); //put in the shared value
}
}
}
return inCommon; //return the common numbers
}
Here is the setTest.cpp that tests the different methods previously defined:
//CSCI 205
//Brett Milinski
//Assignment 2 - The Set Class
//This problem wants us to create a set class to hold a mathematical set of integers and can later be manipulated to implement the Sieve of Eratosthenes method for computing prime numbers
#include"set.h"
#include<iostream>
using namespace std;
int main()
{
int dummy = 0;
SET set1(1, 7); //overloaded constructor
SET set2, set4; //default constructor
SET set3(5, 10);
SET set7(9, 11);
//testing the functions of the SET class (overloaded constructor)
cout << set1;
cout << "Insert 5:" << endl;
set1.insert(5); //try inserting to end
cout << set1;
cout << "Try insertering 5 again:" << endl;
set1.insert(5); //try inserting a duplicate number
cout << set1;
cout << "Insert 0:" << endl;
set1.insert(0); //try inserting to start
cout << set1;
cout << "Erase 3:" << endl;
set1.erase(3); //try erasing from middle
cout << set1;
cout << "Insert 3:" << endl;
set1.insert(3); //try inserting to the middle
cout << set1;
cout << "Erase 0:" << endl;
set1.erase(0); //try erasing from the start
cout << set1;
cout << "Erase 5:" << endl;
set1.erase(5); //try erasing from the end
cout << set1;
cout << "Erase 20 (shouldn't work because it isn't there):" << endl;
set1.erase(20); //try erasing something that isn't there
cout << set1;
cout << "Add to the empty set (set2) and then erase from it:" << endl;
set2.insert(1); //try adding to the empty set
cout << set2;
set2.erase(1); //try erasing from the now populated set
cout << set2;
//test second set (default constructor)
cout << "This is the default constructor (an empty set, should contain no values)." << endl;
cout << set2;
//try adding two overlapping sets together
cout << "Try adding two overlapping sets together:" << endl;
cout << "The First Set:" << endl;
cout << set1;
cout << "The Other Set:" << endl;
cout << set3;
cout << "After adding the sets together together:" << endl;
SET set5 = set1 + set3;
cout << set5;
//try adding two empty sets
cout << "Try adding two empty sets together:" << endl;
cout << "The First Set:" << endl;
cout << set2;
cout << "The Other Set:" << endl;
cout << set4;
cout << "After adding the sets together together:" << endl;
cout << set2 + set4;
//try adding one filled set and one empty set
cout << "Try adding one filled set and one empty set together:" << endl;
cout << "The First Set:" << endl;
cout << set1;
cout << "The Other Set:" << endl;
cout << set2;
cout << "After adding the sets together together:" << endl;
cout << set1 + set2;
//try adding two sets that don't overlap
cout << "Try adding two sets that don't overlap:" << endl;
cout << "The First Set:" << endl;
cout << set1;
cout << "The Other Set:" << endl;
cout << set7;
cout << "After adding the sets together together:" << endl;
cout << set1 + set7;
//find out what the sets have in common
cout << "Find what the two sets have in common:" << endl;
cout << "The First Set:" << endl;
cout << set1;
cout << "The Other Set:" << endl;
cout << set3;
SET set6 = set1 * set3;
cout << "The number that the two sets have in common is contained in the set below (if 0, there is no common number unless it is 0)" << endl;
cout << set6;
cout << "Enter a dummy number:" << endl;
cin >> dummy;
return 0;
}
I'm not sure why I am not able to do what I want, thanks in advance for any help to my problem!
The two functions
SET& operator+(SET& a, SET& b);
SET& operator*(SET& a, SET& b);
return a reference to a temporary object:
SET& operator+(SET& a, SET& b)
{
SET added;
// ...
return added; // <= temporary object returned via a reference - don't!!
}
These temporary objects ( added
and inCommon
) are typically allocated on the stack by the compiler and "disappear" when control flow leaves the function they are defined in, and you end up with dangling references. That's a very nasty bug.
To fix this problem make sure to return these objects by value instead of by reference. All that is needed is to change the return types like so:
SET operator+(SET& a, SET& b);
SET operator*(SET& a, SET& b);
^^^
no more references here
Aside from the issues mentioned by @WhiteViking , your declaration of
friend ostream& operator<<(ostream& os, SET& a);
should be
friend ostream& operator<<(ostream& os, const SET& a);
since otherwise you will not be able to bind rvalues (ie temporary objects) to the parameter a
. And in your code, in the line std::cout << set1 + set2;
, the second argument of operator<<
is the rvalue set1 + set2
, which can only bind to a rvalue reference or a const
reference. Once you implement these changes you'll be able to use std::cout << set1 + set2;
without any more issues.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.