Vous êtes sur la page 1sur 8

Introduction to System Programming 234122

Set Implementation Version 1

Masha Nikolski, CS Department, Technion

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73

// // // //

Version 1.0 Header file for set class. In this implementation set is a container of a limited size holding elements with no repetitions. Elements can be added to the set till it is full.

// Those two lines and the last one prevent the set header from being // included more than once. #ifndef _SET_H_ #define _SET_H_ // We have to include iostream because we want to implement printing // and scanning operators for the set class. #include <iostream> // We are using those two classes and not the whole std namespace. using std::ostream; using std::istream; class Set { // This part is accessible only by the Set class. private: // the size of the set int dim; // current number of elements in the set int numElems; // buffer holding set's data double* buffer; // When a class has dynamically allocated memory in his fields, its usually // useful to implement those two private functions. They later will be used // in constructors, destructor, operator=. void copy(const Set& s); void clear(); // Returns the index of the element d in the buffer or -1 if not found in // the set. int find(const double& d) const; // This part is accessible by everyone. public: // Constructor with a default parameter for set's size. // Its accentual to define one if we want to allocate an array of vectors. // For example: Set array[5]; Set(int s = 10); // Constructor initializing the set from an array of elements. Set(const double* arr, int n); // Copy constructor. // It is accentual to define one since there are dynamically allocated fields // in this class. // Will be used for: // 1. Creating set from another set: Set s1; Set s2 = s1; // 2. For passing set by value to a function: func(s); // 3. For returning a set by value from a function: // Set f(){ return Set();} Set(const Set& s); // Conversion constructors // We want to be able to do: // Set s; s += 7.4; // Here first a conversion constructor will be called converting 7.4 to a set // with one element, and then operator += will be called for s adding the // element 7.4 to the set. Set(const double& d); // Destructor. // It is accentual to define one since there are dynamically allocated fields // in this class and we need to free this memory. ~Set(); // operator=

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134

// It is accentual to define one since there are dynamically allocated fields // in this class. The default operator= supplied by the compiler will simply // copy the set field by field, which will be wrong in case of pointers. Set& operator=(const Set& s); // Checks if an element is inside bool is_in(const double& d) const; // Inserts an element bool insert(const double& d); // Erases an element bool erase(const double& d); // Checks if the set is full bool full() const; // Checks if the set is empty bool empty() const; // Erases all the elements from the set void clean(); // Returns the current size of a set int size() const; // Those operators return a reference to allow concatenation of // operations on sets (s1 += s2) -= s3; Set& operator+=(const Set& s); Set& operator-=(const Set& s); // This function will be used in order to implement the comparison operators // without making them friends. bool compare(const Set& s) const; // This function will be used in order to implement operator<< // without making it a friend. void print(ostream& ost) const; // This function will be used in order to implement operator>> // without making it a friend. void scan(istream& ist); }; // All the following operators are global functions and there is no need // to make them friends. // Comparison operators bool operator==(const Set& s1, const Set& s2); bool operator!=(const Set& s1, const Set& s2); // I/O operators ostream& operator<<(ostream& ost, const Set& s); istream& operator>>(istream& ist, Set& s); // Union/Substruction Set operator+(const Set& s1, const Set& s2); Set operator-(const Set& s1, const Set& s2); #endif

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73

// Version 1.0 // Implementation of the set class. // In this file NULL is defined, in C++ it is the constant 0. #include <cstdlib> #include "set.h" void Set::copy(const Set& s) { dim = s.dim; numElems = s.numElems; buffer = new double[dim]; for (int i = 0; i < numElems; i++) buffer[i] = s.buffer[i]; } void Set::clear() { if (buffer) { delete[] buffer; // make sure there is no garbage there, so we can always check // the value of the fields later buffer = NULL; dim = 0; numElems = 0; } } // Use initialization list to initialize all the fields. Set::Set(int s) : dim(s) , numElems(0) , buffer(new double[s]) { } // This is an example why the copy function is so useful. Set::Set(const Set& s) { copy(s); } Set::Set(const double& d) { dim = 1; numElems = 1; // Allocate a one double and call its constructor. buffer = new double(d); } Set::Set(const double* arr, int n) { dim = n; numElems = 0; buffer = new double[n]; for (int i = 0; i < n; i++) insert(arr[i]); // numElems will be updated in this function } // All the destructor needs to do is to call the clear function. Set::~Set() { clear(); } Set& Set::operator=(const Set& s) { // Check if we are not doing s = s. // If we do, we can't erase ourselves, otherwise it will be a disaster! if (this == &s) return *this;

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

clear(); copy(s); return *this; } Set& Set::operator+=(const Set& s) { // No need to do anything in this case, since the set holds only unique // values. if (this == &s) return *this; Set new_set(dim + s.dim); new_set.numElems = numElems; for (int i = 0; i < numElems; i++) new_set.buffer[i] = buffer[i]; for (int i = 0; i < s.numElems; i++) new_set.insert(s.buffer[i]); // Note that operator= will also call to clear(), // hence preventing a memory leak. *this = new_set; return *this; } // You can always implement global operator+ with method operator+= Set operator+(const Set& s1, const Set& s2) { Set s = s1; s += s2; return s; } Set& Set::operator-=(const Set& s) { // In this case just remove all the elements. if (this == &s) clean(); for (int i = 0; i < s.numElems; i++) erase(s.buffer[i]); return *this; } // You can always implement global operator- with method operator-= Set operator-(const Set& s1, const Set& s2) { Set s = s1; s -= s2; return s; } int Set::size() const { return numElems; } bool Set::compare(const Set& s) const { // for s.compare(s) case if (this == &s) return true; if (numElems != s.numElems) return false; for (int i = 0; i < numElems; i++) { if (!is_in(s.buffer[i])) return false; } return true;

147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219

} // You can always implement global operator== with method compare bool operator==(const Set& s1, const Set& s2) { return s1.compare(s2); } bool operator!=(const Set& s1, const Set& s2) { return !(s1 == s2); } void Set::print(ostream& ost) const { ost << "( "; for (int i = 0; i < numElems; i++) ost << buffer[i] << " "; ost << ")"; } ostream& operator<<(ostream& ost, const Set& v) { // Here we can just use the set method print and no need to make this // function a friend. v.print(ost); return ost; } void Set::scan(istream& ist) { double d; while (!ist.eof() && !full()) { ist >> d; insert(d); } } istream& operator>>(istream& ist, Set& v) { // Here we can just use the set method scan and no need to make this // function a friend. v.scan(ist); return ist; }

bool Set::is_in(const double& d) const { for (int i = 0; i < numElems; i++) if (buffer[i] == d) return true; return false; } bool Set::full() const { return (numElems == dim); } bool Set::empty() const { return (numElems == 0); } bool Set::insert(const double& d) { if (!is_in(d) && !full()) { buffer[numElems++] = d; return true; } return false;

220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245

} bool Set::erase(const double& d) { if (is_in(d)) { int i = find(d); for (int j = i; j < numElems; j++) buffer[j] = buffer[j + 1]; numElems--; return true; } return false; } void Set::clean() { numElems = 0; } int Set::find(const double& d) const { for (int i = 0; i < numElems; i++) if (buffer[i] == d) return i; return -1; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

#include "set.h" // Include <iostream> and not <iostream.h> (see the tutorial for explanation). #include <iostream> // Using for printing/scanning purposes. using std::cout; using std::endl; using std::cin; int main() { double arr[6] = {4.8, 9.5, 8.3, 9.5, 1.2, 4.8}; Set s1; // Constructor with default size = 10. Set s2(3); // Constructor with size = 3. Set s3(arr, 6); cout << "s1 = " << s1 << endl; cout << "s2 = " << s2 << endl; cout << "s3 = " << s3 << endl; s2.insert(4.7); s2.insert(8.2); s2.insert(8.2); s2.insert(9.3); s2.insert(7.1); cout << "s2 = " << s2 << endl; s1 = s2; // s1.operator=(s2) cout << "s1 = " << s1 << endl; s1 = s2 + s3; // operator+(s2, s3), then s1.operator=. cout << "s1 = " << s1 << endl; s3 += 6.8; // Conversion constructor Set(6.8), then s3.operator+=. cout << "s3 = " << s3 << endl; Set s4 = s3; // Copy constructor. cout << "s4 = " << s4 << endl; return 0; // Destructors. }

Vous aimerez peut-être aussi