How to implement resize() to change capacity of dynamic member data in c++

307 Views Asked by At

I need to implement the function resize() :

 void IntSet::resize(int new_capacity)
 {
     if (new_capacity < used)
         new_capacity = used;
     if (used == 0)
         new_capacity = 1;

     capacity = new_capacity;

     int * newData = new int[capacity];

     for (int i = 0; i < used; ++i)
         newData[i] = data[i];

     delete [] data;
     data = newData;
}

inside the functions :

 IntSet IntSet::unionWith(const IntSet& otherIntSet) const
 {
       IntSet unionSet = otherIntSet;

       for (int i = 0; i < used; i++)
       {
           if (unionSet.contains(data[i]))
              unionSet.add(data[i]);
       }
       return unionSet;
 }

and this one: ( NOTE: that I have it already inside the add() function but I think it is incorrect)

 bool IntSet::add(int anInt)
 {
     if (contains(anInt) == false)
     {
        if (used >= capacity)
           resize(used++);

        data[used++] = anInt;

        return true;
     }
     return false;
 }

The program compiles correctly without errors, but it does give me an error of Segmentation fault

NOTE: The main thing is that I need help in learning how to use the resize function to resize the capacity of the the dynamic member data. Also, I know vectors would help in this case, but we are not allowed to use vectors yet

Here is the Special Requirements from professor:

>Special Requirement (You will lose points if you don't observe this.) <br/>

>When calling resize *(while implementing some of the member functions)* to 
>increase the capacity of the dynamic arrays, use the following resizing 
>rule (unless the new capacity has to be something else higher as dictated 
>by other >overriding factors): <br/>
>
>*"new capacity" is "roughly 1.5 x old capacity" and at least "old capacity 
> + 1".* <br/>
>
>The latter *(at least " old capacity + 1 ")* is a simple way to take care 
>of the subtle case where " 1.5 x old capacity " evaluates (with truncation) 
>to the >same as "old capacity". <br/>
1

There are 1 best solutions below

1
On

When you resize because of add, you increment used twice.

bool IntSet::add(int anInt)
{
    if (contains(anInt) == false)
    {
       if (used >= capacity)
          resize(used++);  // Here And this is a post increment. 
                           // resize will be called with used before the increment
                           // so you will wind up asking for a buffer the same size.

       data[used++] = anInt; // and here. 

       return true;
    }
    return false;
}  

So nothing goes into used. You skip a space and write into the space after. Plus resize(used++); didn't ask for more space, so you actually wind up writing two spots outside the allocated storage, and this probably triggers the segfault.

Solution

You don't want to increment anything at resize(used++);. You want to add one to the capacity, but not increment it, so

resize(capacity +1);

Looks about right. However, what the instructions asked for is something more like:

int newcap = capacity * 1.5;
if (newcap == capacity) // newcap didn't change. eg: 1*1.5 = 1
{
    newcap ++;
}
resize(newcap);

This is brute force though. There are smarter ways to do this.