Please send questions to st10@humboldt.edu .
/*-----------------------------------------------------------
   a string_list is a class:
      string_list
   ...representing a list with:
       a size,
       the strings it currently contains

   template for a function involving a string_list:
   ret_type process_string_list(string_list a_string_list)
   {
       return  ...a_string_list.get_length()...
               ...a_string_list.get_element(i)...
    }
-------------------------------------------------------------*/

#include "string_list.h"
using namespace std;

// constructor

string_list::string_list()
{
    element_array = new string[INITIAL_CAP];
    curr_capacity = INITIAL_CAP;
    curr_size = 0;
}
    
// destructor

string_list::~string_list()
{
    delete [ ] element_array;
}

// copy constructor

string_list::string_list(const string_list& a_string_list)
{
    // INSIDE this class -- can access private data fields;

    element_array = new string[a_string_list.curr_capacity];
    curr_size = a_string_list.curr_size;
    curr_capacity = a_string_list.curr_capacity;

    for (int i=0; i<curr_size; i++)
    {
        element_array[i] = a_string_list.element_array[i];
    }
}

// selectors              

int string_list::get_length() const
{
    return curr_size;
}


// signature: string_list::get_element: int -> string
// purpose: expects the "index" (starting with 0, like an
//     array) of the list element desired, and produces
//     the string at that position in this string_list
// examples: for:
//    string_list greetings;
//    greetings.add("hi");
//    greetings.add("hello");
//    greetings.add("howdy");
//
//    greetings.get_element(0) == "hi"
//    greetings.get_element(2) == "howdy"

string string_list::get_element(int index) const
{
    // if had time, we would throw an EXCEPTION if
    //    someone tried to access a "nonexistent" element --
    //    as a cheesy first step, we'll just return an empty string
    //    if they try that

    if (index >= curr_size)
    {
        return "";
    }
    else
    {
        return element_array[index];
    }
}

// modifiers

// signature: string_list::add: string -> void
// purpose: expects a string, and produces nothing, but
//     has the side-effect of adding the given string
//     to the end of the list (making it its last element)
// examples: after:
//     string_list greetings;
//     greetings.add("hi");
//
//     now:
//     greetings.get_size() == 1
//     greetings.get_element(0) == "hi"
//
//     and then after:
//     greetings.add("hello");
//
//     now:
//     greetings.get_size() == 2
//     greetings.get_element(1) == "hello"

void string_list::add(string new_string)
{
    // IF are about to exceed internal array's current capacity --
    //    need a new, "bigger" internal array!

    if (curr_size == curr_capacity)
    {
        string* new_element_array;

        // growing it by 10 each time an increase is needed

        new_element_array = new string[curr_capacity + INITIAL_CAP];

        // copy over the existing elements into the new array

        for (int i=0; i < curr_size; i++)
        {
            new_element_array[i] = element_array[i];
        }

        // can now safely deallocate the old element array, and
        //    have it point here

        delete [] element_array;
        element_array = new_element_array;

        curr_capacity += INITIAL_CAP;
    }

    // NOW it should be safe to copy in the new element!

    element_array[curr_size] = new_string;
    curr_size++;
}

// signature: string_list::remove: string -> bool
// purpose: expects a string, and tries to remove its
//    first instance from the calling string_list,
//    producing true if it finds it and removes it,
//    and producing false if the string is not in the string_list
// examples: after:
//     string_list greetings;
//     greetings.add("hi");
//     greetings.add("howdy");
//     greetings.add("hi");
//     greetings.add("hello");
//
//     greetings.remove("hi") == true
//     and after:
//     greetings.get_size() == 3
//     greetings.get_element(0) == "howdy"
//     (and greetings contains "howdy", "hi", "hello")
//
//     greetings.remove("bonjour") == false
//     greetings.get_size() == 3
//     greetings.get_element(0) == "howdy"
//     (and greetings contains "howdy", "hi", "hello")

bool string_list::remove(string a_string)
{
    bool found = false;
    int curr_index = 0;

    while (!found && (curr_index < curr_size))
    {
        if (element_array[curr_index] == a_string)
        {
            found = true;
        }
        else
        {
            curr_index++;
        }
    }

    // if you FOUND it -- REMOVE it;

    if (found)
    {
        // to remove it, SHIFT up the elements AFTER it;

        for (int i=curr_index; i < (curr_size-1); i++)
        {
            element_array[i] = element_array[i+1];
        }

        // ...and adjust the curr_size accordingly

        curr_size--;

        return true;   // remove succeeded
    }

    else
    {
        return false;  // removal did not succeed -- string not in list
    }
}

// overloaded operator =
   
string_list& string_list::operator =(const string_list& right_side)
{
    // only go to the trouble of copying if this isn't a 
    //     a self-assignment

    // the keyword this is a SPECIAL POINTER -- it contains the
    //     address of the calling object
    // (reference:
    // http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr035.htm
    // )

    if (this != &right_side) // if these addresses AREN'T the same
    {
        delete [] element_array;
	curr_capacity = right_side.curr_capacity;
	curr_size = right_side.curr_size;
 	element_array = new string[curr_capacity];

        for (int i=0; i<curr_size; i++)
	{
	    element_array[i] = right_side.element_array[i];
	}
    }

    return *this; // return the modified calling object
}