Str.h, Str.cpp, Str.txt, Code folder, Classes webpage

Illustrates all of the basic parts of a class, e.g., Constructors, operators, destructor, and member data.

Str.cpp

///////////////////////////////////////////////////////////////////
//  Str.cpp   -  implementation file for string class            //
//  ver 2.1                                                      //
//                                                               //
//  Language:     Visual C++, ver 12.0                           //
//  Platform:     Dell XPS 2720, Win 8.0                         //
//  Application:  ADT example, CSE687 - Object Oriented Design   //
//  Author:       Jim Fawcett                                    //
//                Syracuse University, CST 4-187                 //
//                fawcett@ecs.syr.edu, (315) 443-3948            //
///////////////////////////////////////////////////////////////////

//#include "stdafx.h"
#include <iostream>
#include <cstring>
#include <stdexcept>
#include "Str.h"
using namespace std;

//----< sized constructor >------------------------------------

Str::Str(int n) : array(new char[n]), max(n), len(0) 
{
  array[0] = '\0';
}

//----<copy constructor >--------------------------------------

Str::Str(const Str& s) : array(new char[s.max]), max(s.max), len(s.len)
{
  for (int i = 0; i <= len; i++)
    array[i] = s.array[i];
};

//----<move constructor >--------------------------------------

Str::Str(Str&& s) : array(s.array), max(s.max), len(s.len)
{
  s.array = nullptr;  // must do this to avoid delete in s dtor
};

//----< promotion constructor >--------------------------------

Str::Str(const char* s) : len(static_cast<int>(strlen(s)))
{
  max = len+1;
  array = new char[len+1];
  for(int i=0; i<=len; i++)
    array[i] = s[i];
}

//----< destructor >-------------------------------------------

Str::~Str()
{
  delete [] array;
  max = len = 0;
}

//----< copy assignment operator >-----------------------------

Str& Str::operator=(const Str& s) {

  if (this == &s) return *this;
  if (max >= s.len + 1) {
    len = s.len;
    int i;
    for (i = 0; i <= len; i++)
      array[i] = s.array[i];
    return *this;
  }
  delete[] array;
  array = new char[max = s.max + 10];
  int i;
  len = s.len;
  for (i = 0; i <= len; i++)
    array[i] = s.array[i];
  return *this;
}

//----< move assignment operator >-----------------------------

Str& Str::operator=(Str&& s) {

  if (this == &s) return *this;
  max = s.max;
  len = s.len;
  array = s.array;
  s.array = nullptr;
  return *this;
}

//---< index operator >----------------------------------------

char& Str::operator[](int n) {

  if(n<0 || len<=n)
    throw invalid_argument("index out of bounds in operator[]");
  return array[n];
}

//----< index operator for const str >-------------------------

char Str::operator[](int n) const {

  if(n<0 || len<=n)
    throw invalid_argument("index out of bounds in operator[])");
  return array[n];
}

//

//----< append char to string >--------------------------------

Str& Str::operator+=(char ch) {

  if(len < max-1) {
    array[len] = ch;
    array[len+1] = '\0';
    len++;
  }
  else {
    max *= 2;   // multiply by 2
    char *temp = new char[max];
    int i;
    for(i=0; i<len; i++)
      temp[i] = array[i];
    temp[len] = ch;
    temp[len+1] = '\0';
    len++;
    delete [] array;
    array = temp;
  }
  return *this;
}

//----< append string to string >------------------------------

Str& Str::operator+=(const Str& s) {

  if(len < max-s.size()) {
    int i;
    for(i=0; i<=s.len; i++)
      array[len+i] = s.array[i];
    len += s.size();
  }
  else {
    max += max + s.size();
    char *temp = new char[max];
    for(int i=0; i<len; i++)
      temp[i] = array[i];
    for(int i=0; i<s.size(); i++)
      temp[len+i] = s.array[i];
    temp[len+s.size()] = '\0';
    len += s.size();
    delete [] array;
    array = temp;
  }
  return *this;
}

//----< addition operator >------------------------------------

Str Str::operator+(const Str& s)
{
  Str temp = *this;
  temp += s;
  return temp;
}
//
//----< insertion operator >-----------------------------------

ostream& operator<<(ostream& out, const Str& s) {

  int i;
  for(i=0; i<s.size(); i++)
    out << s[i];
  return out;
}

//----< extraction operator >----------------------------------

istream& operator>>(istream& in, Str& s) {

  char ch;
  s.flush();
  in >> ch;
  while((ch != '\n') && in.good()) {
    s += ch;
    in.get(ch);
  }
  return in;
}

//

//----< test stub >--------------------------------------------

#ifdef TEST_STR

#include <fstream>

Str testFunction()    // note return by value
{
  Str s("string created in testFunction");
  return s;
}

int main(int argc, char* argv[]) 
{

  cout << "\n  Testing Str class "
       << "\n ===================\n";

  try
  {
    cout << "\n  testing promotion constructor "
         << "\n -------------------------------\n";

    Str s1 = Str("this is a string");
    cout << "  new Str object: " << s1 << endl;

    cout << "\n  testing copy constructor "
         << "\n --------------------------\n";

    Str s2 = s1;                   // calls Str(const Str &s)
    cout << "  copy of original:    " << s2 << endl;

    cout << "\n  testing move constructor "
         << "\n --------------------------\n";

    Str s2move = testFunction();
    cout << "  " << s2move << endl;

    cout << "\n  testing index operator "
         << "\n ------------------------\n";

    const Str s3 = s1;
    char ch = s3[1];
    cout << "  second character is: " << ch << endl;

    s2[3] = 'x';
    cout << "  modifying fourth character: " << s2 << endl;

    cout << "\n  testing appends "
         << "\n -----------------\n";

    cout << "  appending vowel characters:\n";
    s1 += 'a';
    cout << "  " << s1 << endl;
    s1 += 'e';
    cout << "  " << s1 << endl;
    s1 += 'i';
    cout << "  " << s1 << endl;
    s1 += 'o';
    cout << "  " << s1 << endl;
    s1 += 'u';
    cout << "  " << s1 << endl;
    cout << "  size of Str object is " << s1.size() << endl;
  
    cout << "\n  appending string \"yyy\": ";
    s1 += Str("yyy");
    cout << s1 << endl;
    cout << "  size of Str object is now " << s1.size() << endl; 

    cout << "  appending a long string to Str object:\n  ";
    s1 += Str(" and the rain in Spain falls mainly on the plain");
    cout << s1 << endl;
    cout << "  size of Str object is now " << s1.size() << endl;

    cout << "\n  testing addition operator "
         << "\n -----------------------------\n";

    Str orig = Str("  Original string");
    Str sum = orig + Str(" - this is a concatenated part");
    cout << sum << endl;

    cout << "\n  testing copy assignment operator "
         << "\n ----------------------------------\n";

    cout << "  assigning the original's copy to this string: ";
    s1 = s2;
    cout << s2 << endl;
    cout << "  size of Str object is now " << s1.size() << endl;

    cout << "\n  testing move assignment operator "
         << "\n ----------------------------------\n";

    s2move = s1 + Str(" ") + s1;
    cout << " sum of two strings is: "
         << s2move << endl;

    cout << "\n  testing memory resizing by multiple appends "
         << "\n ---------------------------------------------\n";  
    cout << "  appending \"C++ is great!!! \" several times to this string:\n\n";
    int i;
    for(i=0; i<5; i++) {
      s1 += Str("C++ is great!!! ");
      s2 = s1;
      cout << "  " << s2 << endl;
      cout << "  size of Str object is now " << s2.size() << endl;
    }

    cout << "\n  testing insertion and extraction operators "
         << "\n --------------------------------------------\n";

    ofstream out("test.dat");
    if(!out.good()) {
      cout << "\n  can't open file for writing strings\n\n";
      return 1;
    }
    Str insert1 = Str("Now is the time for all good men ");
    insert1 += Str("to come to the aid of their country");
    out << insert1 << endl;

    Str insert2 = Str("The rain in Spain falls mainly on the plain");
    out << insert2 << endl;

    Str insert3 = Str("This is the last line");
    out << insert3 << endl;

    out.close();
    ifstream in("test.dat");
    if(!in.good()) {
      cout << "\n  can't open file test.dat for input\n\n";
      return 1;
    }

    Str extract;
    while(in.good()) {
      in >> extract;
      cout << "  " << extract << endl;
    }

    cout << "\n  testing cast operator "
         << "\n --------------------------------------------\n";

    const char* ccs = static_cast<const char*>(extract);

    cout << "  The string below is a const char*"
         << " holding address of last Str's character memory:\n\n  "
         << ccs << endl;

    cout << "\n  testing index operator "
         << "\n --------------------------------------------\n";

    Str indexTest = Str("012345");
    cout << "  " << indexTest << " - ";
    for(int i=0; i<7; ++i)
      cout << indexTest[i] << " ";
    cout << endl;
  }
  catch(exception& e)
  {
    cout << "\n  " << e.what() << endl << endl;
    return 1;
  }
  return 0;
}

#endif