[5:08pm] cat array1.h // ARRAY1.H // Simple class Array (for integers) #ifndef ARRAY1_H #define ARRAY1_H #include class Array { friend ostream &operator<<(ostream &, const Array &); friend istream &operator>>(istream &, Array &); public: Array(int = 10); // default constructor Array(const Array &); // copy constructor ~Array(); // destructor int getSize() const; // return size const Array &operator=(const Array &); // assign arrays int operator==(const Array &) const; // compare equal int operator!=(const Array &) const; // compare !equal int &operator[](int); // subscript operator static int getArrayCount(); // Return count of // arrays instantiated. private: int *ptr; // pointer to first element of array int size; // size of the array static int arrayCount; // # of Arrays instantiated }; ***************************************************************** // ARRAY1.CPP // Member function definitions for class Array #include #include #include #include "array1.h" // Initialize static data member at file scope int Array::arrayCount = 0; // no objects yet // Default constructor for class Array Array::Array(int arraySize) { ++arrayCount; // count one more object size = arraySize; // default size is 10 ptr = new int[size]; // create space for array assert(ptr != 0); // terminate if memory not allocated for (int i = 0; i < size; i++) ptr[i] = 0; // initialize array } // Copy constructor for class Array Array::Array(const Array &init) { ++arrayCount; // count one more object size = init.size; // size this object ptr = new int[size]; // create space for array assert(ptr != 0); // terminate if memory not allocated for (int i = 0; i < size; i++) ptr[i] = init.ptr[i]; // copy init into object } // Destructor for class Array Array::~Array() { --arrayCount; // one fewer objects delete [] ptr; // reclaim space for array } // Get the size of the array int Array::getSize() const { return size; } // Overloaded assignment operator const Array &Array::operator=(const Array &right) { if (&right != this) { // check for self-assignment delete [] ptr; // reclaim space size = right.size; // resize this object ptr = new int[size]; // create space for array copy assert(ptr != 0); // terminate if memory not allocated for (int i = 0; i < size; i++) ptr[i] = right.ptr[i]; // copy array into object } return *this; // enables x = y = z; } // Determine if two arrays are equal and // return 1 if true, 0 if false. int Array::operator==(const Array &right) const { if (size != right.size) return 0; // arrays of different sizes for (int i = 0; i < size; i++) if (ptr[i] != right.ptr[i]) return 0; // arrays are not equal return 1; // arrays are equal } // Determine if two arrays are not equal and // return 1 if true, 0 if false. int Array::operator!=(const Array &right) const { if (size != right.size) return 1; // arrays of different sizes for (int i = 0; i < size; i++) if (ptr[i] != right.ptr[i]) return 1; // arrays are not equal return 0; // arrays are equal } // Overloaded subscript operator int &Array::operator[](int subscript) { // check for subscript out of range error assert(0 <= subscript && subscript < size); // reference return creates lvalue return ptr[subscript]; } // Return the number of Array objects instantiated int Array::getArrayCount() { return arrayCount; } // Overloaded input operator for class Array; // inputs values for entire array. istream &operator>>(istream &input, Array &a) { for (int i = 0; i < a.size; i++) input >> a.ptr[i]; return input; // enables cin >> x >> y; } // Overloaded output operator for class Array ostream &operator<<(ostream &output, const Array &a) { for (int i = 0; i < a.size; i++) { output << a.ptr[i] << ' '; if ((i + 1) % 10 == 0) output << endl; } if (i % 10 != 0) output << endl; return output; // enables cout << x << y; } *************************************************************** // FIG8_4.CPP // Driver for simple class Array #include #include "array1.h" main() { // no objects yet cout << "# of arrays instantiated = " << Array::getArrayCount() << endl; // create two arrays and print Array count Array integers1(7), integers2; cout << "# of arrays instantiated = " << Array::getArrayCount() << endl << endl; // print integers1 size and contents cout << "Size of array integers1 is " << integers1.getSize() << endl << "Array after initialization:" << endl << integers1 << endl; // print integers2 size and contents cout << "Size of array integers2 is " << integers2.getSize() << endl << "Array after initialization:" << endl << integers2 << endl; // input and print integers1 and integers2 cout << "Input 17 integers:" << endl; cin >> integers1 >> integers2; cout << "After input, the arrays contain:" << endl << "integers1: " << integers1 << "integers2: " << integers2 << endl; // use overloaded inequality (!=) operator cout << "Evaluating: integers1 != integers2" << endl; if (integers1 != integers2) cout << "They are not equal" << endl; // create array integers3 using integers1 as an // initializer; print size and contents Array integers3(integers1); cout << endl << "Size of array integers3 is " << integers3.getSize() << endl << "Array after initialization:" << endl << integers3 << endl; // use overloaded assignment (=) operator cout << "Assigning integers2 to integers1:" << endl; integers1 = integers2; cout << "integers1: " << integers1 << "integers2: " << integers2 << endl; // use overloaded equality (==) operator cout << "Evaluating: integers1 == integers2" << endl; if (integers1 == integers2) cout << "They are equal" << endl << endl; // use overloaded subscript operator // to create rvalue cout << "integers1[5] is " << integers1[5] << endl; // use overloaded subscript operator // to create lvalue cout << "Assigning 1000 to integers1[5]" << endl; integers1[5] = 1000; cout << "integers1: " << integers1 << endl; // attempt to use out of range subscript cout << "Attempt to assign 1000 to integers1[15]" << endl; integers1[15] = 1000; // ERROR: out of range return 0; } ******************************************************************* [5:14pm] CC fig8_4.cpp array1.cpp fig8_4.cpp: array1.cpp: [5:15pm] a.out # of arrays instantiated = 0 # of arrays instantiated = 2 Size of array integers1 is 7 Array after initialization: 0 0 0 0 0 0 0 Size of array integers2 is 10 Array after initialization: 0 0 0 0 0 0 0 0 0 0 Input 17 integers: 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 After input, the arrays contain: integers1: 2 4 6 8 10 12 14 integers2: 16 18 20 22 24 26 28 30 32 34 Evaluating: integers1 != integers2 They are not equal Size of array integers3 is 7 Array after initialization: 2 4 6 8 10 12 14 Assigning integers2 to integers1: integers1: 16 18 20 22 24 26 28 30 32 34 integers2: 16 18 20 22 24 26 28 30 32 34 Evaluating: integers1 == integers2 They are equal integers1[5] is 26 Assigning 1000 to integers1[5] integers1: 16 18 20 22 24 1000 28 30 32 34 Attempt to assign 1000 to integers1[15] Assertion failed: 0 <= subscript && subscript < size, file array1.cpp, line 93 Abort (core dumped) ******************************************************************* ******************************************************************* [5:11pm] m string2.h // STRING2.H // Definition of a String class #ifndef STRING1_H #define STRING1_H #include class String { friend ostream &operator<<(ostream &, const String &); friend istream &operator>>(istream &, String &); public: String(const char * = ""); // conversion constructor String(const String &); // copy constructor ~String(); // destructor const String &operator=(const String &); // assignment String &operator+=(const String &); // concatenation int operator!() const; // is String empty? int operator==(const String &) const; // test s1 == s2 int operator!=(const String &) const; // test s1 != s2 int operator<(const String &) const; // test s1 < s2 int operator>(const String &) const; // test s1 > s2 int operator>=(const String &) const; // test s1 >= s2 int operator<=(const String &) const; // test s1 <= s2 char &operator[](int); // return char reference String &operator()(int, int); // return a substring int getLength() const; // return string length private: char *sPtr; // pointer to start of string int length; // string length }; #endif ******************************************************************* // STRING2.CPP // Member function definitions for class String #include #include #include #include #include "string2.h" // Conversion constructor: // Convert char * to String String::String(const char *s) { cout << "Conversion constructor: " << s << endl; length = strlen(s); // compute length sPtr = new char[length + 1]; // allocate storage assert(sPtr != 0); // terminate if memory not allocated strcpy(sPtr, s); // copy literal to object } // Copy constructor String::String(const String ©) { cout << "Copy constructor: " << copy.sPtr << endl; length = copy.length; // copy length sPtr = new char[length + 1]; // allocate storage assert(sPtr != 0); // ensure memory allocated strcpy(sPtr, copy.sPtr); // copy string } // Destructor String::~String() { cout << "Destructor: " << sPtr << endl; delete [] sPtr; // reclaim string } // Overloaded = operator; avoids self assignment const String &String::operator=(const String &right) { cout << "operator= called" << endl; if (&right != this) { // avoid self assignment delete [] sPtr; // prevents memory leak length = right.length; // new String length sPtr = new char[length + 1]; // allocate memory assert(sPtr != 0); // ensure memory allocated strcpy(sPtr, right.sPtr); // copy string } else cout << "Attempted assignment of a String to itself" << endl; return *this; // enables concatenated assignments } // Concatenate right operand to this object and // store in this object. String &String::operator+=(const String &right) { char *tempPtr = sPtr; // hold to be able to delete length += right.length; // new String length sPtr = new char[length + 1]; // create space assert(sPtr != 0); // terminate if memory not allocated strcpy(sPtr, tempPtr); // left part of new String strcat(sPtr, right.sPtr); // right part of new String delete [] tempPtr; // reclaim old space return *this; // enables concatenated calls } // Is this String empty? int String::operator!() const { return length == 0; } // Is this String equal to right String? int String::operator==(const String &right) const { return strcmp(sPtr, right.sPtr) == 0; } // Is this String not equal to right String? int String::operator!=(const String &right) const { return strcmp(sPtr, right.sPtr) != 0; } // Is this String less than right String? int String::operator<(const String &right) const { return strcmp(sPtr, right.sPtr) < 0; } // Is this String greater than right String? int String::operator>(const String &right) const { return strcmp(sPtr, right.sPtr) > 0; } // Is this String greater than or equal to right String? int String::operator>=(const String &right) const { return strcmp(sPtr, right.sPtr) >= 0; } // Is this String less than or equal to right String? int String::operator<=(const String &right) const { return strcmp(sPtr, right.sPtr) <= 0; } // Return a reference to a character in a String. char &String::operator[](int subscript) { // First test for subscript out of range assert(subscript >= 0 && subscript < length); return sPtr[subscript]; // creates lvalue } // Return a substring beginning at index and // of length subLength as a reference to a // String object. String &String::operator()(int index, int subLength) { // ensure index is in range and substring length >= 0 assert(index >= 0 && index < length && subLength >= 0); String *subPtr = new String; // empty String assert(subPtr != 0); // ensure new String allocated // determine length of substring if ((subLength == 0) || (index + subLength > length)) subPtr->length = length - index + 1; else subPtr->length = subLength + 1; // allocate memory for substring delete subPtr->sPtr; // delete character from object subPtr->sPtr = new char[subPtr->length]; assert(subPtr->sPtr != 0); // ensure space allocated // copy substring into new String strncpy(subPtr->sPtr, &sPtr[index], subPtr->length); subPtr->sPtr[subPtr->length] = '\0'; // terminate new String return *subPtr; // return new String } // Return string length int String::getLength() const { return length; } // Overloaded output operator ostream &operator<<(ostream &output, const String &s) { output << s.sPtr; return output; // enables concatenation } // Overloaded input operator istream &operator>>(istream &input, String &s) { char temp[100]; // buffer to store input input >> setw(100) >> temp; s = temp; // use String class assignment operator return input; // enables concatenation } ******************************************************************* [5:12pm] m fig8_5.cpp // FIG8_5.CPP // Driver for class String #include #include "string2.h" main() { String s1("happy"), s2(" birthday"), s3; // test overloaded equality and relational operators cout << "s1 is \"" << s1 << "\"; s2 is \"" << s2 << "\"; s3 is \"" << s3 << '\"' << endl << "The results of comparing s2 and s1:" << endl << "s2 == s1 yields " << (s2 == s1) << endl << "s2 != s1 yields " << (s2 != s1) << endl << "s2 > s1 yields " << (s2 > s1) << endl << "s2 < s1 yields " << (s2 < s1) << endl << "s2 >= s1 yields " << (s2 >= s1) << endl << "s2 <= s1 yields " << (s2 <= s1) << endl << endl; // test overloaded String empty (!) operator cout << "Testing !s3:" << endl; if (!s3) { cout << "s3 is empty; assigning s1 to s3;" << endl; s3 = s1; // test overloaded assignment cout << "s3 is \"" << s3 << "\"" << endl << endl; } // test overloaded String concatenation operator cout << "s1 += s2 yields s1 = "; s1 += s2; // test overloaded concatenation cout << s1 << endl << endl; // test conversion constructor cout << "s1 += \" to you\" yields" << endl; s1 += " to you"; // test conversion constructor cout << "s1 = " << s1 << endl << endl; // test overloaded function call operator () for substring cout << "The substring of s1 starting at" << endl << "location 0 for 14 characters, s1(0, 14), is: " << s1(0, 14) << endl << endl; // test substring "to-end-of-String" option cout << "The substring of s1 starting at" << endl << "location 15, s1(15, 0), is: " << s1(15, 0) << endl << endl; // 0 is "to end of string" // test copy constructor String *s4Ptr = new String(s1); cout << "*s4Ptr = " << *s4Ptr << endl << endl; // test assignment (=) operator with self-assignment cout << "assigning *s4Ptr to *s4Ptr" << endl; *s4Ptr = *s4Ptr; // test overloaded assignment cout << "*s4Ptr = " << *s4Ptr << endl; // test destructor delete s4Ptr; // test using subscript operator to create lvalue s1[0] = 'H'; s1[6] = 'B'; cout << endl << "s1 after s1[0] = 'H' and s1[6] = 'B' is: " << s1 << endl << endl; // test subscript out of range cout << "Attempt to assign 'd' to s1[30] yields:" << endl; s1[30] = 'd'; // ERROR: subscript out of range return 0; } ******************************************************************* [5:13pm] CC fig8_5.cpp string2.cpp fig8_5.cpp: string2.cpp: [5:13pm] a.out Conversion constructor: happy Conversion constructor: birthday Conversion constructor: s1 is "happy"; s2 is " birthday"; s3 is "" The results of comparing s2 and s1: s2 == s1 yields 0 s2 != s1 yields 1 s2 > s1 yields 0 s2 < s1 yields 1 s2 >= s1 yields 0 s2 <= s1 yields 1 Testing !s3: s3 is empty; assigning s1 to s3; operator= called s3 is "happy" s1 += s2 yields s1 = happy birthday s1 += " to you" yields Conversion constructor: to you s1 = happy birthday to you The substring of s1 starting at location 0 for 14 characters, s1(0, 14), is: Conversion constructor: happy birthday The substring of s1 starting at location 15, s1(15, 0), is: Conversion constructor: to you Copy constructor: happy birthday to you *s4Ptr = happy birthday to you assigning *s4Ptr to *s4Ptr operator= called Attempted assignment of a String to itself *s4Ptr = happy birthday to you Destructor: happy birthday to you s1 after s1[0] = 'H' and s1[6] = 'B' is: Happy Birthday to you Attempt to assign 'd' to s1[30] yields: Assertion failed: subscript >= 0 && subscript < length, file string2.cpp, line 99 Abort (core dumped)