/* Joe Shinnerl (shinnerl@ucla.edu) CS 31 Example: simple variable-length sets of integers Supports Sets of arbitrary length using variable-length arrays. Default Constructor, Copy Constructor, Destructor. Revised the get(), join() and assign() functions accordingly. To do: Set(int data0[], size0); // Initializing constructor. friend Set setUnion(const Set&, const Set&); */ #include #include #include #include using namespace std; class Set{ public: // The four "essential" members for correct automatic handling of // exogenous data: Set() : data(0), size(0), capacity(0) {} // Default constructor. Set( const Set& ); // Copy constructor. ~Set( ); // Destructor. const Set& operator=(const Set&); // Assignment operator (DISABLED). // Other members. Set(int data0[], int size0); // Initializing constructor. bool has( int ) const; // membership checker void join( int ); // membership maker -- union with one more int. void assign( const Set& ); // assignment friend Set setIntersect(const Set&, const Set&); friend Set setUnion(const Set&, const Set&); void get( istream& ); // stream input void put( ostream& ) const; // stream output private: int *data; int size; // number of elements in the Set int capacity; // number of storage locations allocated (array length) void expand(); // reallocate to twice the current capacity if nonempty void copy(const Set&); // called both by assign() and by Set(const Set&) }; // Copy constructor. // Note: the copy() function below requires that "size" be correctly // initialized to zero prior to copying. Set::Set( const Set& rhs ) : data(0), size(0), capacity(0) { copy(rhs); } void Set::copy( const Set& rhs ){ while (rhs.size > capacity) // Accomodate possibly larger rhs. expand(); size = rhs.size; for (int i = 0; i < size; ++i) data[i] = rhs.data[i]; } Set::~Set( ){ // Destructor. size = capacity = 0; delete [] data; data = 0; // for safety. } void Set::expand( ){ capacity = (capacity ? capacity * 2 : 1); // double the storage unless empty int* temp = new int[capacity]; for (int i = 0; i < size; ++i) temp[i] = data[i]; delete [] data; data = temp; } bool Set::has( int value ) const { bool answer = false; for (int i=0; i< size && !answer; ++i) if (data[i] == value ) answer = true; return answer; } void Set::join( int value ) { if ( !has(value) ){ if ( size == capacity ) expand(); data[size++] = value ; } } void Set::assign( const Set& rhs ){ // assignment copy(rhs); } void Set::get( istream& is ){ char ch; is >> ch; assert (ch == '{'); do { is >> ch; if (ch != '}'){ is.putback(ch); int value; is >> value; join(value); } } while (ch != '}'); } void Set::put( ostream& os ) const { // Note: not symmetric w.r.t. get(). os << "{ "; for (int i = 0; i < size; ++i) os << data[i] << " "; os << "}"; } Set setIntersect(const Set& A, const Set& B){ // Quadratic-time solution for unsorted sets Set C; for (int i = 0; i < A.size; ++i) if (B.has( A.data[i] )) C.join( A.data[i] ); return C; } void menu(){ cout << "Enter \n" << " K to enter set A or set B by KEYBOARD input \n" << " F to enter set A or set B by FILE input \n" << " V to VIEW all sets \n" << " W to WRITE a set to a file \n" << " R to REPLACE a set \n" << " I to find the INTERSECTION of A and B \n" << " U to find the UNION of A and B \n" << " Q to QUIT \n" << endl; } void prompt() { cout << "\nKFVWRIUQ > "; } void readSet( Set& A, Set& B, istream &is ){ char ch; cout << "Read Set A or Set B? (A/B)"; cin >> ch; if (&is == &cin) // Keyboard input. if (ch == 'A' || ch == 'B') cout << "Enter set elements delimited by {, } " << "and separated by spaces only:\n"; if (is){ if (ch == 'A') A.get(is); else if (ch == 'B') B.get(is); } } void printSet( const Set &A, const Set& B, const Set& C, ofstream& os ){ string filename; char ch; cout << "Write to which file? "; cin >> filename; cout << "Append or overwrite (a/o)? "; cin >> ch; switch (ch ){ case 'o': case 'O': os.open(filename.c_str()); break; case 'a': case 'A': os.open(filename.c_str(), ios::app); break; } if (!os) cout << "Error opening file for os.\n"; else{ cout << "Write A, B, or C? "; cin >> ch; switch ( ch ){ case 'A' : case 'a': A.put(os); break; case 'B' : case 'b': B.put(os); break; case 'C' : case 'c': C.put(os); break; } os << "\n"; } os.close(); } int main(){ // Should break this into smaller functions. Set A,B,C; string filename; ifstream input; ofstream output; menu(); char ch; do{ prompt(); cin >> ch; switch (ch){ case 'k': case 'K': case 'r' : case 'R': readSet(A, B, cin); break; case 'f': case 'F': cout << "Read from which file? "; cin >> filename; input.open(filename.c_str()); if (!input) cout << "Error opening file for input.\n"; else readSet(A, B, input); input.close(); break; case 'v': case 'V': cout << " A = "; A.put(cout); cout << endl; cout << " B = "; B.put(cout); cout << endl; cout << " C = "; C.put(cout); cout << endl; break; case 'w': case 'W': printSet( A, B, C, output ); case 'i': case 'I': C.assign( setIntersect(A, B) ); break; case 'm': case 'M': case '?' : case 'h': case 'H': menu(); break; case 'q': case 'Q': break; default: cout << "Sorry, that option is not supported.\n"; } } while (ch != 'q' && ch != 'Q' ); return 0; }