Question

In: Computer Science

This assignment introduces the concept of dynamic memory allocation, destructors, copy constructors, and overloading the assignment...

This assignment introduces the concept of dynamic memory allocation, destructors, copy constructors, and overloading the assignment operator, , and also provides some insight into how the C++ string class works.

Assignment

In this assignment, you will create a class to represent a string of characters. You can think of this class as a simplified version of the C++ string class.

Program

You will need to write one class for this assignment. A main program to test your class has been provided.

The NIUString class

The NIUString class represents a string of characters. You can think of it as a "wrapper" we can put around an array of char that provides additional functionality (like the ability to assign one string to another, compare strings using the relational operators, etc.). Like the other classes we've written this semester, this class should be implemented as two separate files.

The class declaration should be placed in a header file called NIUString.h. Include header guards to prevent it from accidentally being #included more than once in the same source code file.

Data Members

The NIUString class should contain the following private data members:

a pointer to a char. I'll refer to this data member as the string array pointer. It will be used to dynamically allocate an array of char (the string array).

an unsigned integer or size_t variable used to keep track of the number of elements in the string array. I'll refer to this data member as the string capacity.

an unsigned integer or size_t variable used to store the current length of the C string stored in the string array. I'll refer to this data member as the string size. The string size must always be less than or equal to the string capacity.

In addition to the changes to the data members described above, your class declaration will need prototypes for methods described below.

Methods

The implementations of the class methods should be placed in a separate source code file called NIUString.cpp. Make sure to #include "NIUString.h" at the top of this file.

The NIUString class should have the following methods (most of which are quite small):

NIUString::NIUString()

This "default" constructor for the NIUString class should initialize a new NIUString object to an empty string with a capacity of 0. The required logic is:

< >Set the string size for the new object to 0.

Set the string capacity for the new object to 0.

Set the string array pointer for the new object to the special value nullptr.

NIUString::NIUString(const char* other)

This constructor for the NIUString class should initialize a new NIUString object to the C string other. The required logic is:

< >Set the string size for the new object to the length of the C string other.

Set the string capacity for the new object to the string size.

If the string capacity is 0, set the string array pointer for the new object to nullptr. Otherwise, use the string array pointer for the new object to allocate an array of char. The number of elements in the new string array should be equal to the string capacity.

Copy the characters of the C string other (up to, but not including the null character) into the string array.

NIUString::NIUString(const NIUString& other)

This "copy constructor" for the NIUString class should initialize a new NIUString object to the same string as the existing NIUString object other. The required logic is:

< >Set the string size for the new object to the string size of other.

Set the string capacity for the new object to the string capacity of other.

If the string capacity is 0, set the string array pointer for the new object to nullptr. Otherwise, use the string array pointer for the new object to allocate an array of char. The number of elements in the new string array should be equal to the string capacity.

Copy the contents of the string array of other into the string array of the new object. If other has a string size of 0, this loop will exit immediately.

NIUString::~NIUString()

The destructor for the NIUString class can simply call the clear() method described below.

NIUString& NIUString::operator=(const NIUString& other)

This overloaded assignment operator should assign one NIUString object (the object other) to another (the object that called the method, which is pointed to by this). The required logic is:

< >Check for self-assignment. If the address stored in the pointer this is the same as the address of the object other, then skip to the final step.

Delete the string array for the object pointed to by this.

Set the string size for the object pointed to by this to the string size of other.

Set the string capacity for the object pointed to by this to the string capacity of other.

If the string capacity is 0, set the string array pointer for the object pointed to by this to nullptr. Otherwise, use the string array pointer to allocate an array of char. The number of elements in the new string array should be equal to the string capacity.

Copy the contents of the string array of other into the string array of the object pointed to by this.

Return *this.

NIUString& NIUString::operator=(const char* other)

This overloaded assignment operator should assign a C string (the string other) to an NIUString object (the object that called the method, which is pointed to by this). The required logic is:

< >Delete the string array.

Set the string size for the object pointed to by this to the length of the C string other.

Set the string capacity for the object pointed to by this to the string size.

If the string capacity is 0, set the string array pointer for the object pointed to by this to nullptr. Otherwise, use the string array pointer to allocate an array of char. The number of elements in the new string array should be equal to the string capacity.

Copy the contents of the C string other (up to, but not including the null character) into the string array of the object pointed to by this.

Return *this.

size_t NIUString::capacity() const

This method should return the string capacity.

size_t NIUString::size() const

This method should return the string size.

bool NIUString::empty() const

This method should return true if the string size is 0. Otherwise, it should return false.

void NIUString::clear()

This method should set the string size and string capacity to 0. It should should then use the delete[] operator to delete the string array. Finally, the string array pointer should be set to nullptr.

void NIUString::reserve(size_t n)

This method modifies an object's string capacity without changing its size or the contents of the string array. The required logic is:

< >If n is less than the string size or n is equal to the current string capacity, simply return.

Set the string capacity to n.

Declare a temporary array pointer (a pointer to a char).

If the string capacity is 0, set the temporary array pointer to nullptr. Otherwise, use the temporary array pointer to allocate an array of char. The number of elements in the new temporary array should be equal to the string capacity.

Copy the contents of the string array into the temporary array.

Delete the string array.

Set the string array pointer to the temporary array pointer.

bool NIUString::operator==(const NIUString& rhs) const

This method should return true if the characters stored in the string array of the object that called the method are identical to the characters stored in the string array of the NIUString object passed in as rhs.

The logic for this method is less difficult that it might initially appear to be. The first step is to compare the string sizes of the two strings. If they are different, return false (two strings of different lengths can not be equal).

Otherwise, loop through the elements of both string arrays, starting at 0 and stopping when you reach the string size. (The size of which string doesn't matter, since you know they're the same by this point.) Compare the current element from each string array. If characters are different, return false. If the characters are the same, don't return true; do nothing and let the loop continue.

Once the loop ends and you've reached the end of both strings, return true.

bool NIUString::operator==(const char* rhs) const

This method should return true if the characters stored in the string array of the object that called the method are identical to the characters of the C string passed in as rhs (up to, but not including the null character).

The logic for this method is similar to that of the previous method.

const char& NIUString::operator[](size_t pos) const

This method should return element pos of the string array.

char& NIUString::operator[](size_t pos)

This method should return element pos of the string array.

In addition to the methods described above, you will need to write a couple of standalone functions. These functions are not (and can not be) methods. You should

Include a friend declaration for each of these functions in the NIUString class definition.

Put the definitions for these functions in NIUString.cpp.

ostream& operator<<(ostream& lhs, const NIUString& rhs)

This method should loop through the characters of the string array of the NIUString object passed in as rhs and print them one at a time using the stream object passed in as lhs.

bool operator==(const char* lhs, const NIUString& rhs)

This method should return true if the characters of the C string passed in as lhs (up to, but not including the null character) are identical to the characters stored in the string array of the NIUString object passed in as rhs.

The logic for this function is similar to that of the two relational operator methods.

Driver Program

A short main program to test your class is given below. Either type in this program or copy it to your UNIX account from the pathname ~t90kjm1/CS241/Code/Spring2017/Assign5/assign5.cpp.

/*********************************************************************
   PROGRAM:    CSCI 241 Assignment 5
   PROGRAMMER: your name
   LOGON ID:   your z-ID
   DUE DATE:   due date of assignment

   FUNCTION:   This program tests the functionality of the NIUString
               class.
*********************************************************************/  

#include <iostream>
#include "NIUString.h"

using std::cout;
using std::endl;

int main()
   {
   cout << "Testing default constructor\n\n";

   const NIUString s1;
   
   cout << "s1: " << s1 << endl;   
   cout << "s1 size: " << s1.size() << endl;
   cout << "s1 capacity: " << s1.capacity() << endl;
   cout << "s1 is " << ((s1.empty()) ? "empty\n" : "not empty\n");
   cout << endl;
   
   cout << "Testing second constructor\n\n";
   
   NIUString s2 = "some text";
   
   cout << "s2: " << s2 << endl;   
   cout << "s2 size: " << s2.size() << endl;
   cout << "s2 capacity: " << s2.capacity() << endl;
   cout << "s2 is " << ((s2.empty()) ? "empty\n" : "not empty\n");
   cout << endl;
   
   cout << "Testing second constructor with long string\n\n";
   
   NIUString s3 = "This is a really long string, but all of it will still end up in the array - pretty neat, huh?";
   
   cout << "s3: " << s3 << endl;   
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << endl;

   cout << "Testing write form of subscript operator\n\n";
   
   s2[0] = 'S';
   s2[5] = 'T';
   cout << "s2: " << s2 << endl << endl;
      
   cout << "Testing read form of subscript operator\n\n";
   
   cout << "s2: ";
   for (size_t i = 0; i < s2.size(); i++)
      cout << s2[i];
   cout << endl << endl;

   cout << "Testing reserve() method\n\n";

   s2.reserve(9);

   cout << "s2: " << s2 << endl;   
   cout << "s2 size: " << s2.size() << endl;
   cout << "s2 capacity: " << s2.capacity() << endl;
   cout << "s2 is " << ((s2.empty()) ? "empty\n" : "not empty\n");
   cout << endl;
 
   s2.reserve(30);

   cout << "s2: " << s2 << endl;   
   cout << "s2 size: " << s2.size() << endl;
   cout << "s2 capacity: " << s2.capacity() << endl;
   cout << "s2 is " << ((s2.empty()) ? "empty\n" : "not empty\n");
   cout << endl;
 
   s2.reserve(15);

   cout << "s2: " << s2 << endl;   
   cout << "s2 size: " << s2.size() << endl;
   cout << "s2 capacity: " << s2.capacity() << endl;
   cout << "s2 is " << ((s2.empty()) ? "empty\n" : "not empty\n");
   cout << endl;
 
   s3.reserve(10);
  
   cout << "s3: " << s3 << endl;   
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << "s3 is " << ((s3.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "Testing equality operators\n\n";

   const NIUString s4 = "Some Text";
   
   cout << "s2 and s4 are " << ((s2 == s4) ? "equal\n" : "not equal\n");
   cout << "s3 and s4 are " << ((s3 == s4) ? "equal\n" : "not equal\n\n");
   
   cout << "s4 and \"Some Text\" are " << ((s4 == "Some Text") ? "equal\n" : "not equal\n");
   cout << "s4 and \"More Text\" are " << ((s4 == "More Text") ? "equal\n" : "not equal\n\n");
   
   cout << "\"Some Text\" and s4 are " << (("Some Text" == s4) ? "equal\n" : "not equal\n");
   cout << "\"More Text\" and s4 are " << (("More Text" == s4) ? "equal\n" : "not equal\n\n");

   cout << "Testing clear() method\n\n";

   s3.clear();
   
   cout << "s3: " << s3 << endl;   
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << "s3 is " << ((s3.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "Testing copy constructor\n\n";
   
   NIUString s5(s4);
   
   cout << "s5: " << s5 << endl;   
   cout << "s5 size: " << s5.size() << endl;
   cout << "s5 capacity: " << s5.capacity() << endl;
   cout << endl;

   cout << "Testing assignment operator\n\n";
   
   s3 = s5;

   cout << "s3: " << s3 << endl;   
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << endl;

   s3 = "a different string";

   cout << "s3: " << s3 << endl;   
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << endl;

   cout << "Testing self-assignment\n\n";

   s3 = s3;

   cout << "s3: " << s3 << endl;   
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << endl;

   cout << "Testing chained assignment\n\n";

   s3 = s2 = "Hello, world";

   cout << "s2: " << s2 << endl;
   cout << "s2 size: " << s2.size() << endl;
   cout << "s2 capacity: " << s2.capacity() << endl;
   cout << endl;

   cout << "s3: " << s3 << endl;
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << endl;

   //
   // Extra Credit
   //
   // This code will call the move constructor and move assignment
   // operator if they exist.
   //
   // If those move semantics methods are not implemented, this code
   // will call the copy constructor and copy assignment operator
   // instead. The output will be different in that case.
   //
   cout << "Extra Credit: Testing move constructor\n\n";

   NIUString s6 = std::move(s5);

   cout << "s6: " << s6 << endl;
   cout << "s6 size: " << s6.size() << endl;
   cout << "s6 capacity: " << s6.capacity() << endl;
   cout << "s6 is " << ((s6.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "s5: " << s5 << endl;
   cout << "s5 size: " << s5.size() << endl;
   cout << "s5 capacity: " << s5.capacity() << endl;
   cout << "s5 is " << ((s5.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "Extra Credit: Testing move assignment operator\n\n";

   s5 = std::move(s6);

   cout << "s5: " << s5 << endl;
   cout << "s5 size: " << s5.size() << endl;
   cout << "s5 capacity: " << s5.capacity() << endl;
   cout << "s5 is " << ((s5.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "s6: " << s6 << endl;
   cout << "s6 size: " << s6.size() << endl;
   cout << "s6 capacity: " << s6.capacity() << endl;
   cout << "s6 is " << ((s6.empty()) ? "empty\n" : "not empty\n");

   return 0;
   }

Solutions

Expert Solution

Note: Please save all the files as per the below project.

Program Screenshots:

Sample Output:

Code to be Copied:

NIUString.h

#pragma once
#ifndef NIUSTRING_H
//nclude required header files
#include <cstdlib>
#include <iostream>

using std::ostream;

//declare class
class NIUString {

   //Prints contents of object's char array
   friend ostream& operator<<(ostream&, const NIUString&);     
   //Compares a string and string of an object
   friend bool operator==(const char*, const NIUString&);    

//member functions
public:
   //Default Constructor
   NIUString();  
   //parameterized Constructor
   NIUString(const char*);    
   //Copy Constructor
   NIUString(const NIUString&);
   //Move Constructor
   NIUString(NIUString&&);         
   //Move assignment overload
   NIUString& operator=(NIUString&&);
   //Class Destructor
   ~NIUString();     

   //Accessor methods
   //Returns capacity of string array
   size_t capacity() const;
   //Returns size of string array
   size_t size() const;    
   //Check whether if string is empty
   bool empty() const;
   //Delete dynamically allocated
   //memory
   void clear();       
   //Changes string capacity only
   void reserve(size_t);     
   //Overload == operator
   bool operator==(const NIUString&) const;
   //Overload == operator
   bool operator==(const char*) const;     
   //Overload subscript operator
   const char& operator[](size_t) const;
   //Overload subscript operator
   char& operator[](size_t);       
   //Overload assignment operator
   NIUString& operator=(const NIUString&);     
   //Overload assignment operator
   NIUString& operator=(const char*);    

//private variables
private:
   //Dynamically allocated string array
   char* array;     
   //String capacity
   size_t strCap;
   //String size
   size_t strSize;     
};
#endif

NIUString.cpp

//include header files
#include "NIUString.h"
NIUString::NIUString()
{
   //Initialize data members
   //to empty/default status
   strSize = 0;
   strCap = 0;
   array = nullptr;
}

//Parameterized constructor
NIUString::NIUString(const char* other)
{
   //Counts number of characters in parameter string
   int cnt = 0;
   while (other[cnt] != 0)
       cnt++;
   //Sets string size data member to
   //number of charecters in parameter string
   strSize = cnt;
   //Sets string capacity data member to string size
   strCap = strSize;

   //If parameter string has no charecters,
   //sets object's string array pointer to null.
   if (strCap == 0)
       array = nullptr;

   //Otherwise, dynamically allocates
   //enough mem to hold parameter string
   else
       array = new char[strCap];

   //Loop to copy each element of
   //parameter string to object's string array
   for (size_t i = 0; i < strSize; i++)
   {
       array[i] = other[i];
   }
}


//Implement the copy constructor method
NIUString::NIUString(const NIUString& other)
{
   strSize = other.strSize;
   strCap = other.strCap;     
   if (strCap == 0)
   {
       array = nullptr;
   }
   else
   {
       array = new char[strCap];
   }

   //Loop to copy parameter object's
   //string array to calling object's string array
   for (size_t i = 0; i < strSize; i++)
   {
       array[i] = other.array[i];
   }
}
//Implement destructor method
NIUString::~NIUString()
{
   clear();
}

//Implement overload operator
NIUString& NIUString::operator=(const NIUString& other)
{
   //Checks for self assignment
   if (this != &other)
   {
       ////Deallocates memory pointed to by string array of calling object  
       delete[] this->array;       
       this->strSize = other.strSize;
       this->strCap = other.strCap;

       //Sets calling object's string
       //array pointer to null for empty string
       if (this->strCap == 0)
           array = nullptr;

       //Otherwise, Dynamically allocates
       //enough memory to hold parameter object's string array
       else
           this->array = new char[this->strCap];

       //Loop to copy parameter
       //object's string array to calling object
       for (size_t i = 0; i < this->strSize; i++)
       {
           this->array[i] = other.array[i];
       }
   }
   return *this;
}

//Implement overloaded operator method
NIUString& NIUString::operator=(const char* other)
{
   //Deallocates memory pointed to by string array of calling object
   delete[] this->array;

   //Counts number of characters in parameter string
   int count = 0;
   while (other[count] != 0)
       count++;
   //Assigns calling objects size to size of parameter string
   this->strSize = count;
   //String cap is same as string size
   this->strCap = this->strSize;  

   //Sets array to nullptr if parameter string is empty
   if (this->strCap == 0)
       this->array = nullptr;

   //Otherwise, dynamically allocates
   //enough memory to hold number of charecters in parameter string
   else
       this->array = new char[this->strCap];

   //Loop to copy parameter string
   //array to calling object's string array
   for (size_t i = 0; i < this->strSize; i++)
   {
       this->array[i] = other[i];
   }
   return *this;
}

//Implement method to return the capacity of array
size_t NIUString::capacity() const
{
   return strCap;
}

//Implement method to return the size of array
size_t NIUString::size() const
{
   return strSize;
}

//Implement method to empty the array
bool NIUString::empty() const
{
   //Checks size of string to determine if empty
   if (strSize == 0)
       return true;
   else
       return false;
}
//Implement clear method
void NIUString::clear()
{
   strSize = 0;
   strCap = 0;
   delete[] array;
   array = nullptr;
}
//Does nothing if n is less than/equal to string size or equal to string cap
//Otherwise changes string capacity
void NIUString::reserve(size_t n)
{
   //Sets string capacity to parameter n
   if (n > strSize && n != strCap)
   {
       strCap = n;     
       //Temporary pointer to a char
       char* tempPtr;

       //Sets tempPtr to nullptr if parameter n is zero
       if (strCap == 0)
           tempPtr = nullptr;
       //Otherwise, dynamically allocates
       //enough memory to hold n characters
       else
           tempPtr = new char[strCap];
       //Loop to copy string array of calling object to temp array
       for (size_t i = 0; i < strSize; i++)
       {
           tempPtr[i] = array[i];
       }
       //Deallocates dynamic memory used for string array
       delete[] array;
       //Sets string array pointer to temporary array pointer
       array = tempPtr;
   }
}

//Implement overload operator method
bool NIUString::operator==(const NIUString& rhs) const
{
   //Checks if strings are different sizes
   if (strSize != rhs.strSize)
       return false;

   //Otherwise, compares each respective element
   //of the parameters string arrays
   else
   {
       //Loop to compare each charecter of string
       //in parameter object and calling object
       //Returns false if a charecter is found to be different
       for (size_t i = 0; i < strSize; i++)
       {
           if (array[i] != rhs.array[i])
           {
               return false;
           }
       }
       //Passed compare loop, therefore both are same
       return true;
   }
}

//Iplement overload operatot
bool NIUString::operator==(const char* other) const
{
   //Counts number of characters in parameter string
   size_t count = 0;
   while (other[count] != 0)
       count++;

   //Checks if strings are different sizes
   if (strSize != count)
       return false;

   //Otherwise, compares each respective element of the string arrays
   else
   {
       //Loop to compare each charecter in parameter string and calling object
       //Returns false if a charecter is found to be different
       for (size_t i = 0; i < strSize; i++)
       {
           if (array[i] != other[i])
           {
               return false;
           }
       }
       return true;   //Passed compare loop, therefore both are same
   }
}


const char& NIUString::operator[](size_t pos) const
{
   return array[pos];
}

char& NIUString::operator[](size_t pos)
{
   return array[pos];
}

ostream& operator<<(ostream& lhs, const NIUString& rhs)
{
   //Loops through each element of array
   for (size_t i = 0; i < rhs.strSize; i++)
   {
       //Cascades output to stream object
       lhs << rhs.array[i];
   }
   return lhs;       //Returns output stream object
}

bool operator==(const char* lhs, const NIUString& rhs)
{
   //Counts number of charecters in lhs parameter
   size_t count = 0;
   while (lhs[count] != 0)
       count++;

   //Compares string sizes of lhs and rhs parameters, false if different
   if (rhs.strSize != count)
       return false;

   //Otherwise, compares each respective element of the parameters string array
   else
   {
       //Loop to compare each charecter of parameters string array
       //Returns false if different
       for (size_t i = 0; i < rhs.strSize; i++)
       {
           if (lhs[i] != rhs.array[i])
           {
               return false;
           }
       }
       return true;   //Passed compare loop, therefore both are same
   }
}

NIUString::NIUString(NIUString&& other) : array(NULL), strCap(0), strSize(0)
{
   //Assigns class data members from source object to the one being constructed
   strSize = other.strSize;
   strCap = other.strCap;
   array = other.array;

   //Sets source object to default status
   other.strSize = 0;
   other.strCap = 0;
   other.array = nullptr;
}

NIUString& NIUString::operator=(NIUString&& other)
{
   //Checks for self assignment
   if (this != &other)
   {
       //Delete existing dyanmic memory of calling objects string array
       delete[] array;    

       //Assigns class data members from source object to calling object
       strSize = other.strSize;
       strCap = other.strCap;
       array = other.array;

       //Sets source object to default status
       other.strSize = 0;
       other.strCap = 0;
       other.array = nullptr;
   }
   return *this;
}

main.cpp

/*********************************************************************
   PROGRAM:    CSCI 241 Assignment 5
   PROGRAMMER: your name
   LOGON ID:   your z-ID
   DUE DATE:   due date of assignment
   FUNCTION:   This program tests the functionality of the NIUString class.
*********************************************************************/
#include <iostream>
#include "NIUString.h"

using std::cout;
using std::endl;

int main()
{
   cout << "Testing default constructor\n\n";

   const NIUString s1;

   cout << "s1: " << s1 << endl;
   cout << "s1 size: " << s1.size() << endl;
   cout << "s1 capacity: " << s1.capacity() << endl;
   cout << "s1 is " << ((s1.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "Testing second constructor\n\n";

   NIUString s2 = "some text";

   cout << "s2: " << s2 << endl;
   cout << "s2 size: " << s2.size() << endl;
   cout << "s2 capacity: " << s2.capacity() << endl;
   cout << "s2 is " << ((s2.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "Testing second constructor with long string\n\n";

    NIUString s3 = "This is a really long string, but all of it will still end up in the array - pretty neat, huh?";

   cout << "s3: " << s3 << endl;
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << endl;

   cout << "Testing write form of subscript operator\n\n";

   s2[0] = 'S';
   s2[5] = 'T';
   cout << "s2: " << s2 << endl << endl;

   cout << "Testing read form of subscript operator\n\n";

   cout << "s2: ";
   for (size_t i = 0; i < s2.size(); i++)
       cout << s2[i];
   cout << endl << endl;

   cout << "Testing reserve() method\n\n";

   s2.reserve(9);

   cout << "s2: " << s2 << endl;
   cout << "s2 size: " << s2.size() << endl;
   cout << "s2 capacity: " << s2.capacity() << endl;
   cout << "s2 is " << ((s2.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   s2.reserve(30);

   cout << "s2: " << s2 << endl;
   cout << "s2 size: " << s2.size() << endl;
   cout << "s2 capacity: " << s2.capacity() << endl;
   cout << "s2 is " << ((s2.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   s2.reserve(15);

   cout << "s2: " << s2 << endl;
   cout << "s2 size: " << s2.size() << endl;
   cout << "s2 capacity: " << s2.capacity() << endl;
   cout << "s2 is " << ((s2.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   s3.reserve(10);

   cout << "s3: " << s3 << endl;
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << "s3 is " << ((s3.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "Testing equality operators\n\n";

   const NIUString s4 = "Some Text";

   cout << "s2 and s4 are " << ((s2 == s4) ? "equal\n" : "not equal\n");
   cout << "s3 and s4 are " << ((s3 == s4) ? "equal\n" : "not equal\n\n");

   cout << "s4 and \"Some Text\" are " << ((s4 == "Some Text") ? "equal\n" : "not equal\n");
   cout << "s4 and \"More Text\" are " << ((s4 == "More Text") ? "equal\n" : "not equal\n\n");

   cout << "\"Some Text\" and s4 are " << (("Some Text" == s4) ? "equal\n" : "not equal\n");
   cout << "\"More Text\" and s4 are " << (("More Text" == s4) ? "equal\n" : "not equal\n\n");

   cout << "Testing clear() method\n\n";

   s3.clear();

   cout << "s3: " << s3 << endl;
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << "s3 is " << ((s3.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "Testing copy constructor\n\n";

   NIUString s5(s4);

   cout << "s5: " << s5 << endl;
   cout << "s5 size: " << s5.size() << endl;
   cout << "s5 capacity: " << s5.capacity() << endl;
   cout << endl;

   cout << "Testing assignment operator\n\n";

   s3 = s5;

   cout << "s3: " << s3 << endl;
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << endl;

   s3 = "a different string";

   cout << "s3: " << s3 << endl;
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << endl;

   cout << "Testing self-assignment\n\n";

   s3 = s3;

   cout << "s3: " << s3 << endl;
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << endl;

   cout << "Testing chained assignment\n\n";

   s3 = s2 = "Hello, world";

   cout << "s2: " << s2 << endl;
   cout << "s2 size: " << s2.size() << endl;
   cout << "s2 capacity: " << s2.capacity() << endl;
   cout << endl;

   cout << "s3: " << s3 << endl;
   cout << "s3 size: " << s3.size() << endl;
   cout << "s3 capacity: " << s3.capacity() << endl;
   cout << endl;
   //
   // Extra Credit
   //
   // This code will call the move constructor and move assignment
   // operator if they exist.
   //
   // If those move semantics methods are not implemented, this code
   // will call the copy constructor and copy assignment operator
   // instead. The output will be different in that case.
   //
   cout << "Extra Credit: Testing move constructor\n\n";

   NIUString s6 = std::move(s5);

   cout << "s6: " << s6 << endl;
   cout << "s6 size: " << s6.size() << endl;
   cout << "s6 capacity: " << s6.capacity() << endl;
   cout << "s6 is " << ((s6.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "s5: " << s5 << endl;
   cout << "s5 size: " << s5.size() << endl;
   cout << "s5 capacity: " << s5.capacity() << endl;
   cout << "s5 is " << ((s5.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "Extra Credit: Testing move assignment operator\n\n";

   s5 = std::move(s6);

   cout << "s5: " << s5 << endl;
   cout << "s5 size: " << s5.size() << endl;
   cout << "s5 capacity: " << s5.capacity() << endl;
   cout << "s5 is " << ((s5.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "s6: " << s6 << endl;
   cout << "s6 size: " << s6.size() << endl;
   cout << "s6 capacity: " << s6.capacity() << endl;
   cout << "s6 is " << ((s6.empty()) ? "empty\n" : "not empty\n");
   return 0;
}


Related Solutions

Constructors/Destructors - Initialize your data. Allocate memory if using a dynamically allocated array. The destructor should...
Constructors/Destructors - Initialize your data. Allocate memory if using a dynamically allocated array. The destructor should deallocate the memory. The constructor should take a single int variable to determine the size. If no size is specified (default constructor), then the size should be set to 50. operator[](size_t) - This should return the location with the matching index. For example if given an index of 3, you should return the location at index 3 in the list. Location class/struct - This...
When it comes to dynamic memory allocation and delete[] pointer, what does it mean to say...
When it comes to dynamic memory allocation and delete[] pointer, what does it mean to say that, CRT detected that the application wrote to memory after end of heap buffer? I tried to duplicate the error by deleting the pointer address twice and it didn't produce the same error code so that's not it. What might cause this problem?
Q1: Constraint: Use concept of dynamic allocation for implementation Statement: In a class there are N...
Q1: Constraint: Use concept of dynamic allocation for implementation Statement: In a class there are N students. All of them have appeared for the test. The teacher evaluated the test and noted marks according to their roll numbers. Marks of each students has to be incremented by 5. Print list of marks of students before and after increment.
Purpose Review and reinforcement of pointers, dynamic memory allocation, pointer arithmetic, passing pointers to a function,...
Purpose Review and reinforcement of pointers, dynamic memory allocation, pointer arithmetic, passing pointers to a function, returning a pointer by a function, dangling pointer, and memory deallocation, pointer initialization, and struct data type. Project description In this project, you will create a database of employees of an organization while meeting the requirements described below. Your program MUST NOT interact with the user to receive inputs, so that the instructor and/or the teaching assistant can save a big time in testing...
Write a C++ program (using pointers and dynamic memory allocation only) to implement the following functions...
Write a C++ program (using pointers and dynamic memory allocation only) to implement the following functions and call it from the main function. (1)Write a function whose signature looks like (char*, char) which returns true if the 1st parameter cstring contains the 2nd parameter char, or false otherwise. (2)Create an array of Planets. Populate the array and print the contents of the array using the pointer notation instead of the subscripts.
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT