-3

I have a header and .cpp file. I am having difficulty initializing the array. The problem is that I can't specify the array size. The size depends on the number of elements the user inputs. When I make a new dynamicArray, I believe I have to use the "new" like dynamicArray = new string[sizeof(array)] (because I have to delete the memory later according to the assignment) but when I run it through Linux, it says that it cannot appear in a constant - expression.

I'm still a little unfamiliar with C++. Any feedback is appreciated.

What the error looks like:

image

I also had issues with the header redefinition and I think the #pragma once helped. I know #include "stdafx.h" is bad for linux. I remove it every time I run it on linux.

DynamaicStringArray.cpp

// DynamicStringArray.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "DynamicStringArray.h"
#include "Assignment9Test_V1.cpp"

// copy constructor that copies the array
DynamicStringArray::DynamicStringArray(string array[]) {
    // string *dynamicArray = new string[sizeof(array)]; // without pointer, error with conversion between types
    dynamicArray = new string[sizeof(array)];

    for (int i = 0; i < sizeof(array); i++) {
        dynamicArray[i] = array[i];
    }
}

// default constructor
DynamicStringArray::DynamicStringArray() {
    size = 0;

    dynamicArray = NULL;
    // dynamicArray = new string[size];
}

// frees up dynamic array memory
void DynamicStringArray::destructor(string array[]) {
    delete[] array;
    array = NULL;
}

// return number of entries in array
int DynamicStringArray::getSize() {
    return size;
}

// creates a new dynamic array one element larger than dynamicArray
// copies all elements of dynamicArray to new array and
// add new string to end of new array
// increment size
// delete old dynamicArray
// set new array as dynamicArray
void DynamicStringArray::addEntry(string newString) {
    string *newArray;
    newArray = new string[size + 1];

    for (int i = 0; i < size; i++) {
        newArray[i] == dynamicArray[i];
    }

    int endIndex = sizeof(newArray);
    newArray[endIndex] = newString;

    destructor(dynamicArray);
    dynamicArray = newArray;
}

// searches for dynamicArray for specific string,
// if string not found, return false
// if string is found, create new one size smaller dynamic array
// than dynamicArray
// copy elements of old dynamicArray to new array without the string
// delete old dynamicArray
// decrement size
// return true
bool DynamicStringArray::deleteEntry(string deleteMe) {
    string *newArray;
    newArray = new string[size - 1];

    bool isFound = false;

    for (int i = 0; i < size; i++) {
        if (dynamicArray[i] == deleteMe) {
            i++;
            isFound = true;
        }
        else if (dynamicArray[i] != deleteMe) {
            newArray[i] == dynamicArray[i];
        }
    }

    if (isFound) {
        return true;
        destructor(dynamicArray);

        dynamicArray = newArray;
    }
    else if (!isFound) {
        return false;
    }
}

// returns the string at that index
string DynamicStringArray::getEntry(int findMe) {
    return dynamicArray[findMe];
}

DynamicStringArray.h

#pragma once
#include <string>
#include <iostream>

using namespace std;

class DynamicStringArray {
public:
    DynamicStringArray();

    DynamicStringArray(string array[]);

    // overloading the assignment operator

    void destructor(string array[]);
    int getSize();
    void addEntry(string);
    bool deleteEntry(string);
    string getEntry(int);

private:
    int size; // holds number of entries in the array
    string *dynamicArray; // references a dynamic array of type string
};
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Maina Aoita
  • 35
  • 1
  • 1
  • 5
  • 4
    Use a std::vector. – Jake Freeman Dec 08 '17 at 02:07
  • 1
    `sizeof` is a compile-time constant. The size of the array must be known at compile time. Which is obviously not the case here, and why the whole thing goes down in flaming wreckage. – Sam Varshavchik Dec 08 '17 at 02:15
  • You should **listen more carefully your teacher** during course! – Phil1970 Dec 08 '17 at 02:22
  • `void DynamicStringArray::destructor(` -- In C++, we have [destructors](http://en.cppreference.com/w/cpp/language/destructor) – PaulMcKenzie Dec 08 '17 at 02:28
  • When `array[]` is a parameter, `sizeof(array)` doesn't even tell you how many elements there are in the array. [Why isn't the size of an array parameter the same as within main?](https://stackoverflow.com/questions/1975128/why-isnt-the-size-of-an-array-parameter-the-same-as-within-main) And in the `addEntry` this code `newArray[i] == dynamicArray[i];` will compare the elements instead of copying them. – Bo Persson Dec 08 '17 at 02:32
  • I can't use vectors. We weren't taught that in class. I had size initially where sizeof was but that still didn't work. For destructor, I have to define my own function instead of a function that is already provided. And thanks @BoPersson I didn't notice that one. – Maina Aoita Dec 08 '17 at 02:42
  • @MainaAoita: There are a LOT of problems with your code. Lack of a proper destructor. Mismanaging your `size` variable. Not copying strings correctly. Not following the [Rule of Three](http://en.cppreference.com/w/cpp/language/rule_of_three). To name a few... – Remy Lebeau Dec 08 '17 at 02:51
  • @RemyLebeau I haven't heard of Rule of Three before. I'll look into it. – Maina Aoita Dec 08 '17 at 02:58
  • @MainaAoita *I have to define my own function instead of a function that is already provided* -- This is one of the most bizarre things I've ever heard of. A destructor is already provided for you by C++. The issue is that you need to customize it to delete the memory instead of the default behavior. Who is teaching you C++? – PaulMcKenzie Dec 08 '17 at 03:03
  • @Maina - The sad thing is that once you have learned about `std::vector` you will never do things like this again. To me it looks a bit like you are taught how to ride a unicycle first, before being shown the "advanced" two wheel bike. – Bo Persson Dec 08 '17 at 03:26

1 Answers1

0

Your instinct to use new (specifically, new[] and delete[]) to solve this issue is correct. You must dynamically allocate the array at runtime since you don't know the number of elements at compile-time. However, you are not using new[]/delete[] correctly, which is why you are getting errors (amongst many other problems with your code).

Try something more like this instead:

DynamicStringArray.h

#pragma once
#include <string>

class DynamicStringArray {
public:
    DynamicStringArray();
    DynamicStringArray(const std::string *array, int arraySize);
    DynamicStringArray(const DynamicStringArray &array);
    ~DynamicStringArray();

    DynamicStringArray& operator=(const DynamicStringArray &array);

    int getSize() const;
    void addEntry(const std::string &newString);
    bool deleteEntry(const std::string &deleteMe);
    std::string getEntry(int findMe) const;

private:
    int size; // holds number of entries in the array
    string *dynamicArray; // references a dynamic array of type string
};

DynamicStringArray.cpp

// DynamicStringArray.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "DynamicStringArray.h"

// default constructor
DynamicStringArray::DynamicStringArray() {
    size = 0;
    dynamicArray = NULL;
}

// constructor that copies an array
DynamicStringArray::DynamicStringArray(const std::string *array, int arraySize) {
    size = arraySize;
    dynamicArray = new std::string[size];

    for (int i = 0; i < size; i++) {
        dynamicArray[i] = array[i];
    }
}

// copy constructor that copies the array
DynamicStringArray::DynamicStringArray(const DynamicStringArray &array) {
    size = array.size;
    dynamicArray = new std::string[size];

    for (int i = 0; i < size; i++) {
        dynamicArray[i] = array.dynamicArray[i];
    }
}

// frees up dynamic array memory
DynamicStringArray::~DynamicStringArray() {
    delete[] array;
}

// copy assignment operator that copies the array
DynamicStringArray& DynamicStringArray::operator=(const DynamicStringArray &array) {
    if (&array != this) {
        DynamicStringArray copied(array);
        std::string *temp = copied.dynamicArray;
        copied.dynamicArray = dynamicArray;
        dynamicArray = temp;
        size = array.size;
    }
    return *this;
}

// return number of entries in array
int DynamicStringArray::getSize() const {
    return size;
}

// creates a new dynamic array one element larger than dynamicArray
// copies all elements of dynamicArray to new array and
// add new string to end of new array
// increment size
// delete old dynamicArray
// set new array as dynamicArray
void DynamicStringArray::addEntry(const std::string &newString) {
    std::string *newArray = new std::string[size + 1];
    for (int i = 0; i < size; i++) {
        newArray[i] = dynamicArray[i];
    }
    newArray[size] = newString;
    delete[] dynamicArray;
    dynamicArray = newArray;
    ++size;
}

// searches the dynamic array for a specific string,
// if string not found, return false
// if string is found, create new array one size smaller than dynamicArray
// copy elements of old dynamicArray to new array without the string
// delete old dynamicArray and replace with new array
// decrement size
// return true
bool DynamicStringArray::deleteEntry(const string &deleteMe) {
    for (int i = 0; i < size; i++) {
        if (dynamicArray[i] == deleteMe) {
            std::string *newArray = new std::string[size - 1];
            for (int j = 0; j < i; ++j) {
                newArray[j] = dynamicArray[j];
            }
            for (int j = i+1; j < size; ++j) {
                newArray[j-1] = dynamicArray[j];
            }
            delete[] dynamicArray;
            dynamicArray = newArray;
            --size;
            return true;
        }
    }
    return false;
}

// returns the string at that index
std::string DynamicStringArray::getEntry(int findMe) const {
    return dynamicArray[findMe];
}

That being said, using a std::vector is the preferred solution. It is a dynamic-sized array that wraps new[]/delete[] for you. It is simpler and safer to use than using new[]/delete[] directly, eg:

DynamicStringArray.h

#pragma once
#include <string>
#include <vector>

class DynamicStringArray {
public:
    DynamicStringArray();
    DynamicStringArray(const std::string *array, int arraySize);

    int getSize() const;
    void addEntry(const std::string &newString);
    bool deleteEntry(const std::string &deleteMe);
    std::string getEntry(int findMe) const;

private:
    std::vector<std::string> dynamicArray; // dynamic array of type string
};

DynamicStringArray.cpp

// DynamicStringArray.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "DynamicStringArray.h"
#include <algorithm>

// default constructor
DynamicStringArray::DynamicStringArray() {
}

// copy constructor that copies the array
DynamicStringArray::DynamicStringArray(const std::string *array, int arraySize) :
    dynamicArray(array, array + arraySize) {
}

// return number of entries in array
int DynamicStringArray::getSize() const {
    return dynamicArray.size();
}

// appends a new element to the end of the dynamic array
void DynamicStringArray::addEntry(const std::string &newString) {
    dynamicArray.push_back(newString);
}

// searches the dynamic array for a specific string,
// if string not found, return false
// if string is found, remove it and return true
bool DynamicStringArray::deleteEntry(const std::string &deleteMe) {
    std::vector<std::string>::iterator iter = std::find(dynamicArray.begin(), dynamicArray.end(), deleteMe);
    if (iter != dynamicArray.end())
    {
        dynamicArray.erase(iter);
        return true;
    }
    return false;
}

// returns the string at that index
std::string DynamicStringArray::getEntry(int findMe) const {
    return dynamicArray[findMe];
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770