1

I'm trying to expand a dynamic array of objects of a class called Coffee( Coffee * brands = new Coffee[sizeOf]; ), usually I would just make a temp dynamic array whose size is one bigger than the initial array's size - I copy them over to temp, add the new one at the end, delete the old one, make it anew but expanded, and copy back everything to it from temp.

But now, I have to do it outside of the main function where the array must be situated(yes, this is an assignment, a tricky one at that), so I carry in the array and the size through as parameters, and start off making the temp array and copying over everything, adding the new object at the end.

Now this is where I'm lost; if I want to delete the array from main through the subfunction, how do I replace it/make it anew through the same function? It sounds nonsensical to me, but I don't see how to get that extra notch in required, or is it just about adding +1 to the size variable and copying over the new object's info to the last slot somehow?

This question isn't a duplicate because I've checked some other answers to other questions but can't find this same one, because this is about making the change happen from another function specifically with a dynamic array, every answer I've seen(such as this one: How to expand an array dynamically in C++? {like in vector } ) deals with either the main-function only, or vectors are suggested(which doesn't help me since I have to use dynamic arrays), and I get confused by some unrelated minutiae like *(p+i) = i.

Also, can somebody explain the scope differences here and why your solution works in harmony with them? What is it I've neglected or missed?

Some code:

#include <iostream>
#include <string>
#include "Coffee.h"

using namespace std;

void addCoffee(Coffee c[], int &amount);
void showAllCoffees(Coffee c[], int amount);

int main()
{
    int sizeOf = 5;
    Coffee * brand = new Coffee[sizeOf];
    addCoffee(brand, &sizeOf);
    showAllCoffees(brand, sizeOf); //nevermind this part, 
                                   //just added it so it makes more sense
    delete [] brand;
    return 0;
}

void addCoffee(Coffee c[], int &amount){
    string name;
    amount++;
    Coffee * temp = new Coffee[amount];

    for(int i=0;i<amount-1;i++){
        temp[i] = c[i];
    }

    cout<<"What is the coffee's name?: ";
    cin>>name;
    temp[amount-1].setName(name);

    /*THIS IS WHERE I'M NOT SURE WHAT TO DO*/

    delete [] temp;
}
Community
  • 1
  • 1
user326964
  • 452
  • 1
  • 5
  • 13
  • Thanks for all of the answers, I'll nominate the solution in a short while, just testing things out. :) – user326964 Jan 04 '16 at 22:59
  • *This question isn't a duplicate* -- It is a "composite" duplicate. How to allocate, copy, assign (which you linked to and the answer got 17 upvotes), and how to pass a pointer and have the value reflect back to the caller: http://stackoverflow.com/questions/10240161/reason-to-pass-a-pointer-by-reference-in-c – PaulMcKenzie Jan 04 '16 at 23:03
  • 1
    What you missed is that your variable is a pointer, not an array. Just as you have passed by reference the `amount`, so also must be done with `c`. Also, this code won't compile since you cannot pass the address of `sizeOf` to `addCoffee`s second parameter. – jxh Jan 04 '16 at 23:07

4 Answers4

3

I'm trying to expand a dynamic array of objects of a class called Coffee( Coffee * brands = new Coffee[sizeOf]; ), usually I would just make a temp dynamic array whose size is one bigger than the initial array's size - I copy them over to temp, add the new one at the end, delete the old one, make it anew but expanded, and copy back everything to it from temp.


every answer I've seen(such as this one: How to expand an array dynamically in C++? {like in vector } ) deals with either the main-function only, or vectors are suggested(which doesn't help me since I have to use dynamic arrays)

I think you really need a std::vector.

Those are dynamic arrays.

Update:

Ok, this may be an assignment where you are forced to create your own dynamic arrays. One quick tip about expanding and adding new items:

Normally expanding is done by reallocating/growing the existing array (but this might be outside this assignment). But if you expand by creating a new array each time, it is best to grow the array in larger sizes (and keep track of the allocated size). That way you don't have to create a new one for every add().

Usually this is done by expanding the size in powers of 2: 16 items -> 32 -> 64 --> 1024, and from then on 1024 each time maybe.

Thus, it would be best to create your own dynamic-array class (where you can keep track of the allocated size, number of items, etc.).

Edit: check out Jerry Coffin's blog post for a nice example.

Danny_ds
  • 11,201
  • 1
  • 24
  • 46
  • 1
    The question clearly says this is an assignment, and many teachers really do forbid the use of vector to force students to learn how to manage dynamic array allocation themselves. – user433534 Jan 04 '16 at 22:47
  • 1
    @user433534 Yep, then they give "A" grades to code that isn't really "A" level (has bugs / pitfalls / deficiencies that an experienced C++ coder would spot immediately, but elude the "professor"), or the student drops the course and takes Java. – PaulMcKenzie Jan 04 '16 at 22:52
  • @user433534 - Oh, I'm sorry.. what can I say.. (I must have overlooked that - I'll update my answer somewhat). – Danny_ds Jan 04 '16 at 22:53
  • @PaulMcKenzie - Now _that_ was exactly what I didn't dare to say.. :) – Danny_ds Jan 04 '16 at 22:54
  • 2
    The drawback is that rarely do these courses teach dynamic array creation correctly. More like "Here is a constructor, here is your destructor, here is the test case, and here is the link to SO so that they will teach you the rule of 3". – PaulMcKenzie Jan 04 '16 at 22:58
  • @PaulMcKenzie - Indeed, and probably testing with a small number of items. – Danny_ds Jan 04 '16 at 23:06
  • @Danny_ds: [Related](http://coderscentral.blogspot.com/2012/08/c-dynamic-arrays.html). – Jerry Coffin Jan 04 '16 at 23:22
  • @JerryCoffin - Interesting read! (only, those `<`'s in the code.. :) – Danny_ds Jan 04 '16 at 23:39
  • @Danny_ds: Yeah--I hardly post there any more, largely because getting it to leave code in a usable state is next to impossible. – Jerry Coffin Jan 04 '16 at 23:51
3

You have to pass a reference to a pointer to your function:

void addCoffee(Coffee *&c, int &amount){
                   // ^^ c is input and output
    string name;
    amount++;
    Coffee * temp = new Coffee[amount];

    for(int i=0;i<amount-1;i++){
        temp[i] = c[i];
    }

    cout<<"What is the coffee's name?: ";
    cin>>name;
    temp[amount-1].setName(name);

    delete [] c; // delete old array
    c = temp;    // assign new array pointer to c
}

But I recommend to use std::vector instead of dynamic arrays.

void addCoffee( std::vector<Coffee> &c ){

    cout<<"What is the coffee's name?: ";
    cin>>name;
    c.push_back( Coffee( name ) );
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Just out of curiousity; how come this works? And won't the temp need a delete later on or does it simply change name? Seeing as I'm supposed to avoid memory leaks too, so it would be good to know how to solve that too in case it happens. Otherwise it was exactly the answer I was looking for, good job! (y) – user326964 Jan 04 '16 at 23:04
  • Ahh, so they even eachother out in the end after all. So 100% no memory leaks whatsoever? – user326964 Jan 04 '16 at 23:16
  • 1
    @user326964 Once you delete `delete [] brand;` at end of `main` there are no memory leaks. – Rabbid76 Jan 04 '16 at 23:23
2

You're passing a pointer to addCoffee. Since you want to be able to modify that pointer, you probably want to pass it by reference instead of by value.

void addCoffee(Coffee *&c, int &amount)

Then inside of addCoffee, after you've copied all the elements from c to temp (and added the new item to temp), want to swap the pointers temp and c, then delete the old array.

If I were doing something on this general order, I'd probably define a structure to hold the pointer and the current size:

template <class T>
struct dynamic_array {
    T *array;
    size_t size;
};

This is pretty much making a small step toward what std::vector provides.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
0

At the end of addCoffee, don't delete[] temp - that's where your new data is stored; instead delete[] c, then return temp and change the function return type to Coffee*.
In main say brand = addCoffee(...) so it saves the return value.

All that said, you've got a bit of thinking to do - you hardcore an initial size of 5 despite having no data in the first 5 elements.

McBooley
  • 433
  • 1
  • 5
  • 16
user433534
  • 1,043
  • 6
  • 8