Assignment 2: An Object-oriented Dynamic String Array

In this assignment your task is to essentially re-do a assignment 1, but this time using object-oriented programming. The resulting str_vec class is much easier to use than the version in assignment 1 because it manages its memory automatically.

Getting Started

For this assignment, all the code you write should be put into a file named a2.cpp that looks like this:

// a2.cpp

/////////////////////////////////////////////////////////////////////////
//
// Student Info
// ------------
//
// Name : <put your full name here!>
// St.# : <put your full SFU student number here>
// Email: <put your SFU email address here>
//
//
// Statement of Originality
// ------------------------
//
// All the code and comments below are my own original work. For any non-
// original work, I have provided citations in the comments with enough
// detail so that someone can see the exact source and extent of the
// borrowed work.
//
// In addition, I have not shared this work with anyone else, and I have
// not seen solutions from other students, tutors, websites, books,
// etc.
//
/////////////////////////////////////////////////////////////////////////

#include "cmpt_error.h"    // These are the only permitted includes!
#include <iostream>        //
#include <string>          // Don't include anything else.
#include <algorithm>
#include <cassert>

using namespace std;

//
// ... write your code here here ...
//

int main() {
  cout << "Hello, world!\n";

  //
  // ... put code for testing your functions here ...
  //
}

You will need to implement a class called str_vec in a2.cpp, along with the operator== and operator!= functions. You can add other helper functions/methods if you like.

Important: write a test function for each major method/function to ensure it is correct.

Questions

Implement each of the following methods and functions. Be sure to use const, public, and private in useful and sensible ways.

  1. A default constructor str_vec() that creates a new str_vec of size 0 and capacity 10. It can be used like this:

    str_vec arr;
    // arr is an empty str_vec of size 0 and capacity 10
    
  2. A constructor str_vec(n s) that creates a new str_vec of size n where each element contains a copy of the string s. It can be used like this:

    str_vec arr(5, "cat");
    // arr is str_vec of size 5, each entry contain the string "cat"
    

    The capacity of arr should be 5 or more.

    If n is less than 0, use cmpt::error to throw a helpful error message.

  3. A copy constructor str_vec(other) that creates a new str_vec that is a copy of the str_vec named other. It can be used like this:

    str_vec a(5, "<empty>");
    str_vec arr(a);
    // arr is str_vec of size 5 with each entry equal to the string "<empty>"
    

    The capacity of arr should be at least the size of the a.

  4. A destructor ~str_vec() that deletes all the dynamic memory used by this str_vec.

    Be sure to test your program with valgrind!

  5. Write the following three getters:

    • size() returns the size of the str_vec
    • capacity() returns the capacity of the str_vec
    • pct_used() returns the % of the underlying array that is in use, i.e. the size divided by the capacity

    Make sure that these are all const methods!

    They can be used like this:

    str_vec empty;
    
    cout << empty.size() << ' '       // 0
         << empty.capacity() << ' '   // 10
         << empty.pct_used() << '\n'; // 0
    
  6. Write the following three non-mutating methods:

    • to_str() returns a string representation of this str_vec; please use the []-brackets style as shown in the example below.
    • print() is a void method that prints the string representation of this str_vec to cout
    • println() is a void method that does the same thing as print(), but also prints a \n at the end

    Make sure that these are all const!

    They can be used like this:

    str_vec arr(3, "cat");
    
    string s = arr.to_str(); // s is the string ["cat", "cat", "cat"]
    
    arr.print();    // prints ["cat", "cat", "cat"] on cout (no \n at end)
    arr.println();  // prints ["cat", "cat", "cat"] on cout (\n at end)
    
  7. Write the following two methods:

    • get(i) is a getter that returns the string at index location of i of the str_vec. Just as with arrays, the first index location is 0. Make sure this is const!
    • set(i, s) is a setter that sets index location i to be a copy of the string s

    For both of these methods, use cmpt::error to throw a helpful error message if the passed-in index i is less than 0, or greater than size()-1.

    They can be used like this:

    str_vec arr(3, "cat");
    
    arr.set(1, "dog");  // arr is now ["cat", "dog", "cat"]
    
    string s1 = arr.get(1);  // s1 is "dog"
    string s2 = arr.get(2);  // s2 is "cat"
    
  8. Write the following two mutating methods:

    • append(s) is a void method that adds the string s to the right end (the back) of this str_vec, increasing the size by 1
    • prepend(s) is a void method that adds the string s to the left end (the front) of this str_vec, increasing the size by 1

    For both of these methods, the underlying capacity should only be increased if necessary. If the capacity is increased, it should be doubled.

    They can be used like this:

    str_vec arr; // empty, size 0
    
    arr.append("apple");  // ["apple"]
    arr.append("orange"); // ["apple", "orange"]
    arr.prepend("up");    // ["up", "apple", "orange"]
    arr.prepend("down");  // ["down", up", "apple", "orange"]
    
  9. Write the following two mutating methods:

    • reverse() is a void method that reverses the order of the elements in this str_vec; please implement this yourself using basic C++, i.e. don’t just use std::reverse
    • sort() is a void method that re-arranges all the strings in this str_vec into alphabetical order; please use std::sort() to help do this

    They can be used like this:

    str_vec arr;
    
    arr.append("d");
    arr.append("b");
    arr.append("a");
    arr.append("c");  // ["d", "b", "a", "c"]
    arr.sort();       // ["a", "b", "c", "d"]
    arr.reverse();    // ["d", "c", "b", "a"]
    
  10. Write the following two mutating methods:

    • clear() is a void method that removes all elements from this str_vec so its size is 0; the capacity can stay the same
    • shrink_to_fit() is a void method that will, if necessary, re-size the underlying array so that the size and capacity are the same; the elements in the array are not changed in any way

    They can be used like this:

    str_vec arr;         // {}, size 0, capacity 10
    arr.append("a");     // {"a"}, size 1, capacity 10
    arr.append("b");     // {"a", "b"}, size 2, capacity 10
    
    arr.shrink_to_fit(); // {"a", "b"}, size 2, capacity 2
    
    arr.clear();         // {}, size 0, capacity 2
    
  11. Write the following two functions (not methods!):

    • operator==(a, b) is a bool function that returns true if the str_vec a and the str_vec b have the same elements in the same order, and false otherwise
    • operator!=(a, b) is a bool function that returns true if the str_vec a and the str_vec b don’t have the same elements in the same order, and false otherwise

They can be used like this:

str_vec a(3, "cat");
str_vec b(3, "cat");

if (a == b) cout << "same\n";       // prints "same"
if (a != b) cout << "different\n";  // prints nothing

a.set(0, "feline");

if (a == b) cout << "same\n";       // prints nothing
if (a != b) cout << "different\n";  // prints different

Submit Your Work

Please put all your code into a single file named a2.cpp, and submit it on Canvas. Make sure to implement all the methods and functions exactly as described, otherwise the marking software will probably give you 0!

The only file you submit is a2.cpp: don’t submit any other files. A copy of cmpt_error.h will be in the same folder as a2.cpp file when it’s tested.

Basic Requirements

Before we give your program any marks, it must meet the following basic requirements:

  • It must compile on Ubuntu Linux using the standard course makefile:

    $ make a2
    g++  -std=c++14 -Wall -Wextra -Werror -Wfatal-errors -Wno-sign-compare -Wnon-virtual-dtor -g   a2.cpp   -o a2
    

    If your program fails to compile, your mark for this assignment will be 0.

    The standard course file cmpt_error.h will be in the same folder as a2.cpp when it’s compiled, so your program can use cmpt::error if necessary.

  • It must have no memory leaks, according to valgrind, e.g.:

    $ valgrind ./a2
    
    // ... lots of output ...
    

    A program is considered to have no memory leaks if:

    • In the LEAK SUMMARY, definitely lost, indirectly lost, and possibly lost must all be 0.
    • The ERROR SUMMARY must report 0 errors.
    • It is usually okay if still reachable reports a non- zero number of bytes.
  • You must include the large comment section with student info and the statement of originality. If your submitted file does not have this, then we will assume your work is not original and it will not be marked.

If your program meets all these basic requirements, then it will graded using the marking scheme on Canvas.