// STRING.CPP // Member function definitions for class String #include <iostream.h> #include <iomanip.h> #include <string.h> #include <assert.h> #include <stdlib.h> #include "string.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 } int String::isNum() { for (int i=0;i<length;i++) if ((sPtr[i] != '.') && (sPtr[i] < '0' || sPtr[i] > '9')) return 0; return 1; // double d = atof(sPtr); } double String::getNum() { if (!(isNum())) { cerr << "ERROR: trying to convert non-number to double." << endl; return 0.0; } return atof(sPtr); }