2

This code is for a CS 235 class, but I'm new to C++ and I have no clue how they want me to do this. The grow function works by taking in an array and changing it to become twice as large. Coming from python, I guess this is the equivalent of mutating the array? Anyway, I can't get it do the same for the insert function. I need it to check if the position that we're trying to insert an item at is outside the array bounds and make the array big enough that it can insert the value. Everything works....inside the function. The array does not maintain the changes outside the function. I've tried passing it in as a pointer, as a (reference to a pointer?) like *&array, and basically any combination I can think of.

void grow(int *&original_array, unsigned int & capacity){
    int *temp = new int[capacity * 2];
    for (int i=0; i<capacity*2; i++){
        temp[i] = 0;
    }
    std::cout << "line 18: ";
    print_array(temp, capacity*2);
    for(int i=0; i<capacity; i++){
        temp[i] = original_array[i];
    }
    std::cout << "line 23: ";
    print_array(temp, capacity*2);

//    delete[] original_array;
    original_array = temp;
    std::cout << "line 27: ";
    print_array(original_array, capacity * 2);
    capacity = capacity * 2;
}

bool insert (int array[], unsigned int & maxSize, unsigned int & nFilled, unsigned int pos, int value){
    while (maxSize < pos){
        grow(array, maxSize);
        print_array(array, maxSize);
    }
    for(unsigned int i = nFilled - 1; i >= pos; i = i-1){
        array[i+1] = array[i];
    }
    array[pos] = value;
    print_array(array, maxSize);
    return true;
}

Here's some sample input and what my program outputs right now:

int main() {
    unsigned int my_size = 4;
    int new_array[4] = {1,2,3,4};
    unsigned int nFilled = 4;

    insert(new_array, my_size, nFilled, 5, 15);
    print_array(new_array, my_size);
    return 0;
}

Output:

line 18: {0, 0, 0, 0, 0, 0, 0, 0}
line 23: {1, 2, 3, 4, 0, 0, 0, 0}
line 27: {1, 2, 3, 4, 0, 0, 0, 0}
{1, 2, 3, 4, 0, 0, 0, 0}
{1, 2, 3, 4, 0, 15, 0, 0}
{1, 2, 3, 4, -152629248, 32758, 0, 8}

the second to last line is inside the function and the last one is outside the function. I need these to be the same

Any help is appreciated - the TA's and professors are being unhelpful

Thanks

  • 4
    Sounds to me like you have some question to ask your instruction or teacher. If I had "have no clue how they want me to do this", that's where I would direct my questions to. Your instructor/teacher is paid to help you learn C++, this is their job. – Sam Varshavchik Jan 17 '23 at 20:43
  • 1
    Can you show us the code that is calling these functions? – MPops Jan 17 '23 at 20:50
  • it's all called from int main() as shown – pythoncader Jan 17 '23 at 20:54
  • A good example includes ALL of the code necessary to demonstrate the problem you are having and nothing else. Use [mre] (MRE) for inspiration. What you want to provide is an example that anyone can paste into their tools, compile, run, and (baring the vagaries of undefined behaviour) see exactly what you see. Quite often while figuring out what you need and don't need in the MRE you find your answer, so if you make the MRE early in the question-asking process you're done early. – user4581301 Jan 17 '23 at 20:57
  • 4
    `int new_array[4] = {1,2,3,4};` is not a dynamically allocated array. You can never change its size or swap it for a different sized array. Passing new_array to grow() or calling delete on it is invalid. You evidently need to start out with a dynamically allocated array for this exercise which seems to be implementing something like std::vector( which is provided in the standard library). – Avi Berger Jan 17 '23 at 20:57
  • 2
    Note that pointers just hold an address. They know where an object *could* be. they cannot know where that object came from, how it needs to be disposed of, or even if the object exists. You often have to do a lot of extra thinking and book-keeping when working with pointers. – user4581301 Jan 17 '23 at 21:02
  • 2
    You should review your lessons material and search for either [`new`](https://en.cppreference.com/w/cpp/language/new) or [`std::unique_ptr`](https://en.cppreference.com/w/cpp/memory/unique_ptr) (sooner or later you'll find [`std::vector`](https://en.cppreference.com/w/cpp/container/vector)). If they have talked you about `malloc` or `realloc` you may be in the wrong class. – Bob__ Jan 17 '23 at 21:05
  • What is the subject of the CS235 class and at which University or College? There are no standards for class numberings or subjects. – Thomas Matthews Jan 17 '23 at 21:52
  • CS235 is almost certainly BYU's Data Structures class https://students.cs.byu.edu/~cs235ta/ . Google doesn't find any other good matches. – Mooing Duck Jan 17 '23 at 22:56
  • yes it's data structures – pythoncader Jan 18 '23 at 00:11

1 Answers1

4

There's two problems with your code working as written, the first one is that you can't reassign the value of new_array in main as written. As written it is not dynamically allocated, and so it cannot be changed. You will need to change that to be dynamically allocated:

int* new_array = new int[4];

for(int x = 0; x < 4; ++x)
{
    new_array[x] = x + 1;
}

That will address one issue, however the code still won't work, and that has to do with how variables are passed to insert and grow.

Your grow() function takes int*& a reference to a pointer to integer. This means that the underlying value passed in can be changed. However, your insert() function takes int[] an integer array that decays to to pointer to integer, and changes here will not be reflected at the call site of insert().

You can verify that by adding some more debugging statements:

bool insert (int array[],
    unsigned int & maxSize,
    unsigned int & nFilled,
    unsigned int pos,
    int value)
{

    // unchanged above...
    std::cout << "Inside insert: " << array << '\n';
    return true;
}


int main()
{
    // unchanged above...
    std::cout << "After insert: " << new_array << "\n";
    print_array(new_array, my_size);
    return 0;
}

You will get output similar to this:

line 18: {0 0 0 0 0 0 0 0 }
line 23: {1 2 3 4 0 0 0 0 }
line 27: {1 2 3 4 0 0 0 0 }
{1 2 3 4 0 0 0 0 }
{1 2 3 4 0 15 0 0 }
Inside insert: 0x548ed0
After insert: 0x548eb0
{1 2 3 4 0 0 49 0 }

Note that the array "Inside insert" and "After insert" are different.

To fix this, you need to make sure you pass something to insert() that allows for changing the value, similar to what was done for grow().

That change is as simple as changing the signature of insert() as follows:

bool insert (int *&array,
    unsigned int & maxSize,
    unsigned int & nFilled,
    unsigned int pos,
    int value)

Note the first parameter to insert() was changed to match the type in grow() a reference to pointer to integer. Now when we pass the pointer new_array to insert() a reference to that pointer is passed (which allows the value to be changed), and that is also passed to grow() (if necessary), allowing this to propagate all the way to the call site.

Be aware though there are stylistic problems with this approach -- unclear ownership semantics, potential for memory leaks (present in the posted code) etc.

I will also caveat that "reinventing" this type of data structure instead of using std::vector is not a good practice, however it does have its uses in a teaching context.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
Chad
  • 18,706
  • 4
  • 46
  • 63
  • Most of my programming experience is in python so this is going to sound dumb, but dynamically allocating memory for a variable in c++ seems like it's just a way to be able to change the variable however we want to, right? – pythoncader Jan 17 '23 at 23:21
  • 1
    It's not dumb, but it's not really something we can cover in depth in a comment. I'm sorry you're not getting the support from your Prof/TA, but I would suggest a good book: https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list – Chad Jan 18 '23 at 01:56