0

I am trying to create an implementation file for a sequence class that is dynamically sized. This is a homework assignment and as per the limitations of the assignment, I am onlly allowed to mess with the implementation file I write.

The problem is when I create the dynamic array it appears to be garbage, having no real value and not acting like an array at all. When i look at it in the debugger I often get a value like -6.2774385622041925e+066 (update: this is sort of solved by Anders K.'s catch, though when I look in the debugger now I get 1 vanilla number instead of a whole array like I should, output shows that any element after the first one still is a crazy weird number). Also after a certain point the program stops running and complains about a corrupted heap, which I suspect is directly linked to the array showing up as wonky values.

Any and all help is appreciated. Not looking for a knock out solution or anything, but i must be doing something wrong somewhere to be pissing the heap off. Like I said I only wrote the implementation file so it of course is probably what is wrong. >.>

Update: Pasted new an cleaned up versions of the code in, so that other stupid mistakes don't get in the way of the big one.

Here is my implementation file (the only one I can change) sequence.cpp:

#include "sequence.h"
using namespace main_savitch_4;

typedef double value_type;
typedef std::size_t size_type;

sequence::sequence(size_type initial_capacity){
    data = new value_type[initial_capacity];
    used = 0;
    current_index = initial_capacity + 1;
    capacity = initial_capacity;
}

sequence::sequence(const sequence& source){
    capacity = source.size();
    used = capacity;
    current_index = capacity + 1;
    data = new value_type[capacity];
    for (int i = 0; i < used; i++)
        data[i] = source.data[i];
}

sequence::~sequence(){
    delete [] data;
}

void sequence::resize(size_type new_capacity){
    if (new_capacity > used){
        value_type *temp = new value_type[new_capacity];
        for(int i = 0; i < used; i++)
            temp[i] = data[i];
        value_type *destroyme = data;
        data = temp;
        delete [ ] destroyme;
        capacity = new_capacity;
    }
}

void sequence::start( ){
    current_index = 0;
}

void sequence::advance( ){
    current_index += 1;
}

void sequence::insert(const value_type& entry){
    if (used + 1 > capacity){
        resize(capacity + 5);
    }
    value_type *temp = new value_type[capacity];
    int i(0);
    if (is_item()){
        for(i=i;  i < current_index; i++)
            temp[i] = data[i];
        temp[i] = entry;
        current_index = i;
        i++;
        for(i=i;  i < used; i++)
                temp[i] = data[i];

        value_type *destroyme = data;
        data = temp;
        delete [ ] destroyme;

    }
    else{
        for(int i = used; i > 0; i--)
            data[i] = data[i - 1];
        data[0] = entry;
        current_index = 0;
    }


    used += 1;
}

void sequence::attach(const value_type& entry){
    if (used + 1 > capacity){
        resize(capacity + 5);
    }
    value_type *temp = new value_type[capacity];
    if (is_item()){
        int i(0);
        for(i;  i <= current_index + 1; i++)
            temp[i] = data[i];
        temp[i] = entry;
        current_index = i;
        for(i;  i <= used; i++)
            temp[i] = data[i];
        value_type *destroyme = data;
        data = temp;
        delete [ ] destroyme;       
    }
    else{
        data[used] = entry;
        current_index = used;
    }

    used+= 1;

}

void sequence::remove_current(){
    for(int i = current_index; i < used; i++)
        data[i] = data[i + 1];
    used = used - 1;
}

void sequence::operator=(const sequence& source){
    capacity = source.size();
    used = capacity;
    current_index = capacity + 1;
    data = new value_type[capacity];
    for (int i = 0; i < used; i++)
        data[i] = source.data[i];
}

size_type sequence::size() const{
    return used;
}

bool sequence::is_item() const{
    if (current_index < used)
        return true;
    else
        return false;
}

value_type sequence::current() const{
    return data[current_index];
}

Here is the associated header file sequence.h:

#ifndef MAIN_SAVITCH_SEQUENCE_H
#define MAIN_SAVITCH_SEQUENCE_H
#include <cstdlib>  // Provides size_t

namespace main_savitch_4
{
    class sequence
    {
    public:
        // TYPEDEFS and MEMBER CONSTANTS
        typedef double value_type;
        typedef std::size_t size_type;
        static const size_type DEFAULT_CAPACITY = 30;
        // CONSTRUCTORS and DESTRUCTOR
        sequence(size_type initial_capacity = DEFAULT_CAPACITY);
        sequence(const sequence& source);
  ~sequence( );
        // MODIFICATION MEMBER FUNCTIONS
  void resize(size_type new_capacity);
        void start( );
        void advance( );
        void insert(const value_type& entry);
        void attach(const value_type& entry);
        void remove_current( );
        void operator =(const sequence& source);
        // CONSTANT MEMBER FUNCTIONS
        size_type size( ) const;
        bool is_item( ) const;
        value_type current( ) const;
    private:
        value_type* data;
        size_type used;
        size_type current_index;
  size_type capacity;
    };
}

#endif

I get the following output when I run it:

Running tests for sequence class with a dynamic array

START OF TEST 1:
Testing insert, attach, and the constant member functions (4 points).
Starting with an empty sequence.
Testing that size() returns 0 ... Passed.
Testing that is_item() returns false ... Passed.
I'll call start() and look at the items one more time...
All tests passed for this sequence.

I am now using attach to put 10 into an empty sequence.
Testing that size() returns 1 ... Passed.
Testing that is_item() returns true ... Passed.
The cursor should be at item [0] of the sequence
(counting the first item as [0]). I will advance the cursor
to the end of the sequence, checking that each item is correct...Passed.
I'll call start() and look at the items one more time...
The cursor should be at item [0] of the sequence
(counting the first item as [0]). I will advance the cursor
to the end of the sequence, checking that each item is correct...Passed.
All tests passed for this sequence.

I am now using insert to put 10 into an empty sequence.
Testing that size() returns 1 ... Passed.
Testing that is_item() returns true ... Passed.
The cursor should be at item [0] of the sequence
(counting the first item as [0]). I will advance the cursor
to the end of the sequence, checking that each item is correct...Passed.
I'll call start() and look at the items one more time...
The cursor should be at item [0] of the sequence
(counting the first item as [0]). I will advance the cursor
to the end of the sequence, checking that each item is correct...Passed.
All tests passed for this sequence.

I am now using attach to put 10,20,30 in an empty sequence.
Then I move the cursor to the start and insert 5.
Testing that size() returns 4 ... Passed.
Testing that is_item() returns true ... Passed.
The cursor should be at item [0] of the sequence
(counting the first item as [0]). I will advance the cursor
to the end of the sequence, checking that each item is correct...
    The item [1] should be 10,
    but it was -6.27744e+066 instead.
Failed.
Test of the sequence's items failed.

Test 1 failed.
END OF TEST 1.


START OF TEST 2:
Testing situations where the cursor goes off the sequence (4 points).
Using attach to put 20 and 30 in the sequence, and then calling
advance, so that is_item should return false ... passed.
Inserting 10, which should go at the sequence's front.
Then calling advance three times to run cursor off the sequence ... passed.
Calling attach to put the numbers 40, 50, 60 ...300 at the sequence's end.
Now I will test that the sequence has 10, 20, 30, ...300.
    Test failed to find 30
Test 2 failed.
END OF TEST 2.


START OF TEST 3:
Testing remove_current (4 points).
Using attach to build a sequence with 10,30.
Insert a 20 before the 30, so entire sequence is 10,20,30.
Testing that size() returns 3 ... Passed.
Testing that is_item() returns true ... Passed.
The cursor should be at item [1] of the sequence
(counting the first item as [0]). I will advance the cursor
to the end of the sequence, checking that each item is correct...
    The item [2] should be 30,
    but it was 10 instead.
Failed.
Test of the sequence's items failed.

Test 3 failed.
END OF TEST 3.


START OF TEST 4:
Testing the resize member function (2 points).
I will now resize a sequence to a larger capacity, and then
attach that many items. The sequence should NOT need to
resize itself under this situation.
    sequence does not contain correct items.
stygma
  • 523
  • 4
  • 19
  • Use the [copy-and-swap idiom](http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom). – GManNickG Jan 20 '11 at 05:14

2 Answers2

2

this snippet looks a bit dodgy (insert):

  for(int i = used; i > 0; i--)
   data[used] = data[i - 1];

I think what you should do to get some order is to add asserts in your methods to make sure the values are what you expect them to be.

AndersK
  • 35,813
  • 6
  • 60
  • 86
  • That snippet only becomes active if the current_index has run off in which case, as per the assignment, it is required to insert at the beginning of the sequence. The only way i could think of to do this without making a whole new array was to shuffle everything down one place starting at the end, then overwrite the first item in the array. I believe that is what i am doing there. – stygma Jan 20 '11 at 04:47
  • Nice catch. I have to read your answer twice to understand this one. – J-16 SDiZ Jan 20 '11 at 04:48
  • Yikes! Okay, ya that used should be i. What a stupid mistake! Fixing this fixed the crazy number problem, but I still get a heap error at the same spot around test 4. – stygma Jan 20 '11 at 05:00
1

One problem: Here on the initialization you should initializate all itens.

sequence::sequence(size_type initial_capacity){
 data = new value_type[initial_capacity];
 used = 0;
 current_index = initial_capacity + 1;
 capacity = initial_capacity;
}

And Why the current_index is set on the last item ? Also the current_index should be initial_capacity less one. C start counting on Zero.

bratao
  • 1,980
  • 3
  • 21
  • 38
  • It was my belief that I had handled all four data members. What did I miss? current_index is requite to have the ability to have nothing selected as per the project guidelines. It gets check for this with the is_item function several times. The way i decided to have it not be selected was to have it be a value greater than the used value. That is the reason it is current_index + 1 – stygma Jan 20 '11 at 04:42