Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

C++ help please This is chapter pointers and classes. Client program: Data file:

ID: 639029 • Letter: C

Question

C++ help please

This is chapter pointers and classes.

Client program:

Data file:

Correct output:

See also client program, data file, and correct output.

Write a string class. To avoid conflicts with other similarly named classes, we will call our version myString. This object is designed to make working with sequences of characters a little more convenient and less error-prone than handling raw c-strings, (although it will be implemented as a c-string behind the scenes). The myString class will handle constructing strings, reading/printing, accessing characters, and some simple operators such as concatenation. In addition, the myString object will have the ability to make a full deep-copy of itself when copied.

Your class must have only one data member, a c-string implemented as a dynamic array. In particular, you must not use a data member to keep track of the size or length of the myString.

You should write the class in two phases. I've set it up this way because there are a couple of functions that are very difficult and I want to provide a way for you to skip those two functions and move on if you need to. If you submit the assignment with only phase 1 completed you can still earn almost all of the points.

Phase 1 [90 points]: Write everything except the extraction operator (>>) and the read function. To do this, you'll want to comment out that part of the client program that tests these.

Phase 2 [5 points]: The extraction operator and read() function.

Here is a list of the operations this class must support:

A length member function which returns the number of characters in the string.

Construction of a myString from a const c-string. You should copy the string data, not just store a pointer to an argument passed to the constructor. Constructing a myString with no arguments creates an empty myString object (i.e. ""). A myString object should be implemented efficiently (space-wise) which is to say you should not have a fixed-size buffer of chars, but instead allocate space for chars on an as-needed basis.

Printing a myString to a stream using an overloaded << (insertion) operator, which should simply print out its characters.

Reading into a myString from a stream using an overloaded >> (extraction) operator. The standard >> operator should skip any leading spaces and then read characters into the string to the first whitespace character.

For reasons of convenience, we will impose a limit of 127 on the number of characters this function will read. This is so you can temporarily read into a non-dynamic array and then copy what you need into your data member, which will be a dynamic array. Note that this does not mean that all myStrings will always have a maximum of 127 characters. For example, you might get a myString with more than 127 characters by using the myString constructor or by concatenating two myStrings.

Hint: use the extraction operator to do the reading of the input into a non-dynamic array, then use strcpy() to copy it into your data member.

A read() function. The read() function will allow the client programmer to specify the delimiting character (the one to stop at instead of the first space). This will be a void function that will take two arguments, a stream and the delimiting character. It should not skip leading spaces. The limit of 127 characters imposed on the >> function above also applies to this function.

Hint: use the in.getline() function to do the reading of the input into a non-dynamic array, then use strcpy() to copy it into your data member.

Your myString object should overload the square brackets [ ] operator to allow direct access to the individual characters of the string. This operation should range-check and assert if the index is out of bounds. You will write two versions of the [ ] operator, a const version that allows read access to the chars, and a non-const version that returns the client a reference to the char so they can change the value.

All six of the relational operators (<, <=, >, >=, ==, !=) should be supported. They should be able to compare myString objects to other myStrings as well as myStrings to c-strings using lexicographic ordering (i.e. strcmp). myStrings or c-strings should be able to appear on either side of the comparison operator.

The myString object should have correct "deep-copying" semantics, which is to say that when a copy of a string object is made (via the copy constructor or the operator=) the new copy should create its own copy of the string data, rather than use an alias to the character data in the original object.

myString overloads binary + to do string concatenation and the shorthand += to combine concatenation and assignment. Either myString objects or c-strings can appear on either side of the binary + or the right hand side of the +=. Only myStrings can be on the left-hand side of a += operation.

You may use all of the c-string functionality provided by C++. This will include the strlen(), strcmp(), strcpy(), strcat(), and in.getline() functions, along with the overloaded extraction and insertion operator for c-strings. These functions are all covered in detail in section 9.1 of the text. When you use strcat() and strcpy(), treat them as void functions despite the fact that they have a return value. Do not use strncpy(), strncat(), or strncmp() since they are not implemented in all versions of C++. You may NOT use anything from the C++ string class!!

You must place your header file and implementation file in a namespace. Normally one would call a namespace something more likely to be unique, but for purposes of convenience we will all call our namespace "cs2b_mystring".

Name your files mystring.h and mystring.cpp. Please comment on  the header file and implementation file.

Explanation / Answer

File: mystring.h

#pragma once

#ifndef MYSTRING_H
#define MYSTRING_H

#include <iostream>
#include <cstring>
#include <cassert>
using namespace std;

namespace cs2b_mystring
{
   class myString
   {      
       friend bool operator<(const char *charArr, const myString &obj);
       friend bool operator<=(const char *charArr, const myString &obj);
       friend bool operator>(const char *charArr, const myString &obj);
       friend bool operator>=(const char *charArr, const myString &obj);
       friend bool operator==(const char *charArr, const myString &obj);
       friend bool operator!=(const char *charArr, const myString &obj);
       friend ostream &operator<<(ostream &out, const myString &obj);
       friend istream &operator>> (istream &out, myString &obj);
       friend myString operator+(const myString obj1, const myString obj2);

   public:
       myString();
       myString(const char *charArr);
       myString(const myString &obj);
       ~myString();
       void operator=(myString &obj);
       void operator=(const char *charArr);
      
       bool operator<(const myString &obj) const;
       bool operator<=(const myString &obj) const;
       bool operator>(const myString &obj) const;
       bool operator>=(const myString &obj) const;
       bool operator==(const myString &obj) const;
       bool operator!=(const myString &obj) const;
      
       char &operator [](int index);
       const char &operator[](int index) const;

       int length() const;
       void read(istream& ins, char delimiter);
      
       myString& operator+=(const myString &obj);

   private:
       char *strPtr;
   };
}

#endif

File: mystring.cpp

#include "mystring.h"
using namespace cs2b_mystring;

myString::myString()
{
   strPtr = new char[1];
   strPtr[0] = '';
}


myString::myString(const char *charArr)
{
   int len = strlen(charArr);
   strPtr = new char[len + 1];
   for (int i = 0; i < len; i++)
   {
       strPtr[i] = charArr[i];
   }
   strPtr[len] = '';
}


myString::myString(const myString &obj)
{
   int len = strlen(obj.strPtr);
   strPtr = new char[len + 1];

   for (int i = 0; i < len; ++i)
   {
       strPtr[i] = obj.strPtr[i];
   }
   strPtr[len] = '';
}

myString::~myString()
{
   delete[] strPtr;
}

void myString::operator=(myString &obj)
{
   if (*this != obj)
   {
       int len = strlen(obj.strPtr);
       strPtr = new char[len + 1];

       for (int i = 0; i < len; ++i)
       {
           strPtr[i] = obj.strPtr[i];
       }
       strPtr[len] = '';
   }
}

void myString::operator=(const char *charArr)
{
   int len = strlen(charArr);
   strPtr = new char[len + 1];
   for (int i = 0; i < len; ++i)
   {
       strPtr[i] = charArr[i];
   }
   strPtr[len] = '';
}

bool myString::operator<(const myString &obj) const
{
   return strcmp(strPtr, obj.strPtr) < 0;
}

bool myString::operator<=(const myString &obj) const
{
   return strcmp(strPtr, obj.strPtr) <= 0;
}

bool myString::operator>(const myString &obj) const
{
   return strcmp(strPtr, obj.strPtr) > 0;
}

bool myString::operator>=(const myString &obj) const
{
   return strcmp(strPtr, obj.strPtr) >= 0;
}

bool myString::operator==(const myString &obj) const
{
   return strcmp(strPtr, obj.strPtr) == 0;
}

bool myString::operator!=(const myString &obj) const
{
   return strcmp(strPtr, obj.strPtr) != 0;
}

bool cs2b_mystring::operator<(const char *charArr, const myString &obj)
{
   return strcmp(charArr, obj.strPtr) < 0;
}

bool cs2b_mystring::operator<=(const char *charArr, const myString &obj)
{
   return strcmp(charArr, obj.strPtr) <= 0;
}

bool cs2b_mystring::operator>(const char *charArr, const myString &obj)
{
   return strcmp(charArr, obj.strPtr) > 0;
}

bool cs2b_mystring::operator>=(const char *charArr, const myString &obj)
{
   return strcmp(charArr, obj.strPtr) >= 0;
}

bool cs2b_mystring::operator==(const char *charArr, const myString &obj)
{
   return strcmp(charArr, obj.strPtr) == 0;
}

bool cs2b_mystring::operator!=(const char *charArr, const myString &obj)
{
   return strcmp(charArr, obj.strPtr) != 0;
}

ostream &cs2b_mystring::operator<<(ostream &out, const myString &obj)
{
   out << obj.strPtr;
   return out;
}

istream &cs2b_mystring::operator>>(istream &in, myString &obj)
{
   in >> obj.strPtr;
   return in;
}

char& myString::operator [](int i)
{
   int len = strlen(strPtr);
   assert(0 <= i && i < len);
   return strPtr[i];
}

const char& myString::operator[](int i) const
{
   int len = strlen(strPtr);
   assert(0 <= i && i < len);
   return strPtr[i];
}

int myString::length() const
{
   return strlen(strPtr);
}

void myString::read(istream &ins, char delimiter)
{
   char tempArr[128];
   delete[] strPtr;
   ins.getline(tempArr, 127, delimiter);
   strcpy(strPtr, tempArr);
}

myString cs2b_mystring::operator+(const myString obj1, const myString obj2)
{
   myString tempObj;  
   tempObj.strPtr = new char[strlen(obj1.strPtr) + strlen(obj2.strPtr) + 1];  
   strcat(obj1.strPtr, obj2.strPtr);  
   strcpy(tempObj.strPtr, obj1.strPtr);  
   return tempObj;  
}

myString& myString::operator+=(const myString &obj)
{
   *this = *this + obj;
   return *this;
}

File: main.cpp

#include "mystring.h"
#include <fstream>
#include <cctype>      // for toupper()
#include <string>     // for strchr(), strstr(), etc.
#include <cassert>
#include <iostream>
using namespace std;
using namespace cs2b_mystring;

bool eof(istream& in);
void BasicTest();
void RelationTest();
void ConcatTest();
void CopyTest();
myString AppendTest(const myString& ref, myString val);

int main()
{
   BasicTest();
   RelationTest();
   ConcatTest();
   CopyTest();

   return 0;
}

bool eof(istream& in)
{
   char ch;
   in >> ch;
   in.putback(ch);
   return !in;
}

void BasicTest()
{
   myString s;
   cout << "----- Testing basic String creation & printing" << endl;

   const myString strs[] =
   { myString("Wow"), myString("C++ is neat!"),
       myString(""), myString("a-z") };


   for (int i = 0; i < 4; i++) {
       cout << "string [" << i << "] = " << strs[i] << endl;
   }

   cout << endl << "----- Now reading myStrings from file" << endl;

   cout << endl << "----- first, word by word" << endl;
   ifstream in("string.data");
   assert(in);
   while (in.peek() == '#') {
       in.ignore(128, ' ');
   }
   in >> s;
   while (in) {
       cout << "Read string = " << s << endl;
       in >> s;
   }
   in.close();
  
   cout << endl << "----- now, line by line" << endl;
   ifstream in2("string.data");
   assert(in2);
   while (in2.peek() == '#') {
       in2.ignore(128, ' ');
   }
   s.read(in2, ' ');
   while (in2) {
       cout << "Read string = " << s << endl;
       s.read(in2, ' ');
   }

   cout << endl << "----- Testing access to characters (using const)" << endl;
   const myString s1("abcdefghijklmnopqsrtuvwxyz");
   cout << "Whole string is " << s1 << endl;
   cout << "now char by char: ";
   for (int i = 0; i < s1.length(); i++) {
       cout << s1[i];
   }

   cout << endl << "----- Testing access to characters (using non-const)" << endl;
   myString s2("abcdefghijklmnopqsrtuvwxyz");
   cout << "Start with " << s2;
   for (int i = 0; i < s2.length(); i++) {
       s2[i] = toupper(s2[i]);
   }
   cout << " and convert to " << s2 << endl;
}

void RelationTest()
{
   cout << " ----- Testing relational operators between myStrings ";

   const myString strs[] =
   { myString("app"), myString("apple"), myString(""),
       myString("Banana"), myString("Banana") };

   for (int i = 0; i < 4; i++) {
       cout << "Comparing " << strs[i] << " to " << strs[i + 1] << endl;
       cout << "    Is left < right? " << (strs[i] < strs[i + 1]) << endl;
       cout << "    Is left <= right? " << (strs[i] <= strs[i + 1]) << endl;
       cout << "    Is left > right? " << (strs[i] > strs[i + 1]) << endl;
       cout << "    Is left >= right? " << (strs[i] >= strs[i + 1]) << endl;
       cout << "    Does left == right? " << (strs[i] == strs[i + 1]) << endl;
       cout << "    Does left != right ? " << (strs[i] != strs[i + 1]) << endl;
   }

   cout << " ----- Testing relations between myStrings and char * ";
   myString s("he");
   const char *t = "hello";
   cout << "Comparing " << s << " to " << t << endl;
   cout << "    Is left < right? " << (s < t) << endl;
   cout << "    Is left <= right? " << (s <= t) << endl;
   cout << "    Is left > right? " << (s > t) << endl;
   cout << "    Is left >= right? " << (s >= t) << endl;
   cout << "    Does left == right? " << (s == t) << endl;
   cout << "    Does left != right ? " << (s != t) << endl;

   myString u("wackity");
   const char *v = "why";
   cout << "Comparing " << v << " to " << u << endl;
   cout << "    Is left < right? " << (v < u) << endl;
   cout << "    Is left <= right? " << (v <= u) << endl;
   cout << "    Is left > right? " << (v > u) << endl;
   cout << "    Is left >= right? " << (v >= u) << endl;
   cout << "    Does left == right? " << (v == u) << endl;
   cout << "    Does left != right ? " << (v != u) << endl;
}

void ConcatTest()
{
   cout << " ----- Testing concatentation on myStrings ";

   const myString s[] =
   { myString("outrageous"), myString("milk"), myString(""),
       myString("cow"), myString("bell") };

   for (int i = 0; i < 4; i++) {
       cout << s[i] << " + " << s[i + 1] << " = " << s[i] + s[i + 1] << endl;
   }

   cout << " ----- Testing concatentation between myString and char * ";

   const myString a("abcde");
   const char *b = "XYZ";
   cout << a << " + " << b << " = " << a + b << endl;
   cout << b << " + " << a << " = " << b + a << endl;

   cout << " ----- Testing shorthand concat/assign on myStrings ";

   myString s2[] =
   { myString("who"), myString("what"), myString("WHEN"),
       myString("Where"), myString("why") };

   for (int i = 0; i < 4; i++) {
       cout << s2[i] << " += " << s2[i + 1] << " = ";
       cout << (s2[i] += s2[i + 1]) << endl;
   }

   cout << " ----- Testing shorthand concat/assign using char * ";
   myString u("I love ");
   const char *v = "programming";
   cout << u << " += " << v << " = ";
   cout << (u += v) << endl;
}

myString AppendTest(const myString& ref, myString val)
{
   val[0] = 'B';
   return val + ref;
}

void CopyTest()
{
   cout << " ----- Testing copy constructor and operator= on myStrings ";

   myString orig("cake");


   myString copy(orig);    // invoke copy constructor

   copy[0] = 'f'; // change first letter of the *copy*
   cout << "original is " << orig << ", copy is " << copy << endl;


   myString copy2;      // makes an empty string

   copy2 = orig;        // invoke operator=
   copy2[0] = 'f';      // change first letter of the *copy*
   cout << "original is " << orig << ", copy is " << copy2 << endl;

   copy2 = "Copy Cat";
   copy2 = copy2;        // copy onto self and see what happens
   cout << "after self assignment, copy is " << copy2 << endl;


   cout << "Testing pass & return myStrings by value and ref" << endl;
   myString val = "winky";
   myString sum = AppendTest("Boo", val);
   cout << "after calling Append, sum is " << sum << endl;
   cout << "val is " << val << endl;
   val = sum;
   cout << "after assign, val is " << val << endl;
}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote