using vector insert function

Thread Starter

mentaaal

Joined Oct 17, 2005
451
Hey guys, I am having a problem with a homework assignment which I was given.

I have created a vector of type Kitchen * like this
vector<Kitchen *>members(10);

the code works well enough without problems but when i go to insert a new member at an arbitrary location, it works fine but it appears to write over rather than shift the previous element to the right.

Just to simplify things i have included only the test file. The part in question is in the middle. Just in case you are wandering, this code works in every way, except for the above stated problem. No runtime or compile time errors. Further checking the element in question shows it to be empty. I have checked the copy constructor and it appears fine.

Thanks,

Greg

The necessary declarations have been included like <vector> etc

Rich (BB code):
int main()
{
    ifstream fin;
    fin.open("input.txt");
    if(fin.fail())
    {
        cout << "Could not open file \"input.txt\", exiting program.\n";
        exit(1);
    }
    ofstream fout;
    fout.open("output.txt");
    if(fout.fail())
    {
        cout << "Could not open file \"output.txt\", exiting program.\n";
        exit(1);
    }
     vector<Kitchen *>members(10);
    
    for (unsigned int i = 0; i < members.size(); i++)
    {
        members = new Kitchen;
        fin >> *members;
        if(members->ret_name() != "Empty")
        {        
            cout << *members << endl << endl;
            fout << *members << endl << endl;
        }
    }
    vector<Kitchen *>::iterator It;
    It = members.begin();
    It+=5;
    members.erase(It);
    Kitchen * const  temp2 = new Kitchen("Greg","Bacon-Sandwich-chef",30000,23,2);
    //cout << temp2->salary_details() << endl;
    It = members.begin();
    It+=5;
    members.insert(It,temp2); //temp2 now invalidated. attempting to delete temp2 after this statement will result in a runtime error
    cout << "output all elements after insertion.\n\n";
    for (unsigned int j = 0; j < members.size(); j++)
    {
        if(members[j]->ret_name() != "Empty")
        {
            cout << *members[j] << endl << endl;
            fout << *members[j] << endl;
        }
     }
    int retire = 0,promo = 0,less5 = 0;
    double tot_salaries = 0;
    for(unsigned int k = 0; k < members.size(); k++)
    {
        if(members[k]->ret_name() != "Empty")
        {
            if(members[k]->retirement_check())
                retire++;
            if(members[k]->promotion_check())
                promo++;
            if(members[k]->service_check())
                less5++;
            tot_salaries +=  members[k]->salary_details();
        }
    }

    cout << "Total chefs due for retirement:\t\t\t" << retire << endl
         << "Total chefs due for promotion:\t\t\t" << promo << endl
         << "Total chefs with service less than 5 years:\t" << less5 << endl 
         << "Total cost of salaries:\t\t\t\t" << "Euro: " << tot_salaries << endl << endl;

    fout << "Total chefs due for retirement:\t\t\t" << retire << endl
         << "Total chefs due for promotion:\t\t\t" << promo << endl
         << "Total chefs with service less than 5 years:\t"  << less5 << endl 
         << "Total cost of salaries:\t\t\t\t" << "Euro: " << tot_salaries << endl;

    for (unsigned int j = 0; j < members.size(); j++)
    {
        cout << *members[j] << endl << endl;
        fout << *members[j] << endl;
    }

    cout << "Total salaries for chef 1 and 2 is: " << (*members[0] + *members[1]).salary_details() << endl;
    if(*members[1] >= *members[2])
        cout << "Chef 1 has a larger or equal salary than Chef 2.\n\n";
    if(*members[1] > *members[2])
        cout << "Chef 1 has a larger salary than Chef  2.\n\n";
    if(*members[1] == *members[1])
        cout << "These two chefs have equal salaries.\n";

    for(unsigned int i = 0; i < members.size(); i++)
    {
        delete members;
    }
    return 0;
}
 

Mark44

Joined Nov 26, 2007
628
Hi mentaal,
I don't see enough here to determine what the problem is. From what you said, when you attempt to insert a new Kitchen object into the array, the old one is overwritten rather than get moved to a higher index.

I would set a breakpoint in the code just before where it starts to insert a new Kitchen object. Then single-step through your code and see what happens. That should give you some insight into what's going on.

The underlying structure of your array is type vector. Is this a Standard Template Library (STL) data structure? If so, it should be working correctly. Also, read the documentation for insert() for the vector type. You're assuming that it will shift entries before inserting a new entry, but maybe it is designed to overwrite what's at the target location.


Mark
 

Thread Starter

mentaaal

Joined Oct 17, 2005
451
Hi Mark,
Yes you are right I should pull the finger out and take a look at it myself. I did look at the insert documentation (i think i cplusplus.com) where it said that it shifted the elements before insertion. Yes to answer your question the vector array is of type Kitchen * which is a user defined class containing fundamental data types such as string etc.

The reason why I decided to make the vector array of type Kitchen * as opposed to Kitchen is so that I could use one of the class's constructors.

What I will do is see if I can recreate the occurence with as little code as posible and post that after trying to debug it myself.

Thanks Mark
 

Thread Starter

mentaaal

Joined Oct 17, 2005
451
Well I figured out what it was.
The insert function inserts a new element as expected but what the vector class is not doing is redirecting the pointers to point to the new locations.
In the example below, if you insert and element into members[5] location then members[6] will now point to the old value of members[5].

Solution: Dont be silly and declare an array of pointers!

Rich (BB code):
#include <iostream>
#include <vector>
using namespace std;

class test
{
public:
    test();
    test(const char*);
    test(const test &); //copy constructor
    virtual ~test();
    char* reader();

private:
        char * ptr;
};

test::test()
:ptr(new char[50])
{
    //do nothing
}

test::test(const char *Ptr)
:ptr(new char[strlen(Ptr)+1])
{
    strcpy(ptr,Ptr);
}

test::test(const test & G)
:ptr(new char[strlen(G.ptr) + 1])
{
    strcpy(ptr,G.ptr);
}


test::~test()
{
    delete [] ptr;
}
char * test::reader()
{
    return ptr;
}

int main()
{
    vector<test *>members(10);
    for(int i = 0; i < 10; i++)
    {
        if (i != 7)
            members = new test("hello");
        else members = new test ("this is a test");
    }

    vector<test *>::iterator it = members.begin();
    it+=5;
    delete members[5];
    test * const p = new test("goodbye");
    members.insert(it,p);

    for (int i = 0; i< 10; i++)
        cout << members->reader() << endl;
    
    cout << "members[8] now points to " << members[8]->reader() << endl;

    return 0;

}
 

Mark44

Joined Nov 26, 2007
628
So if you had a vector that was an ordinary array of values, rather than an array of pointers to data, insert() would have worked correctly, right? As people on your side of the pond sometimes say, you were too clever by half!
Mark
 

Thread Starter

mentaaal

Joined Oct 17, 2005
451
Yup it would have! Well the only reason why i had used pointers was because I saw that method used in a book on programming which provides an easy way to use a particular constructor as opposed to the default one.

Well I will definitely keep that in mind as, the bug may not be immediately noticeable in a program!
 
Top