using vector insert function

Discussion in 'Programmer's Corner' started by mentaaal, Mar 11, 2009.

  1. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    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

    Code ( (Unknown Language)):
    1. int main()
    2. {
    3.     ifstream fin;
    4.     fin.open("input.txt");
    5.     if(fin.fail())
    6.     {
    7.         cout << "Could not open file \"input.txt\", exiting program.\n";
    8.         exit(1);
    9.     }
    10.     ofstream fout;
    11.     fout.open("output.txt");
    12.     if(fout.fail())
    13.     {
    14.         cout << "Could not open file \"output.txt\", exiting program.\n";
    15.         exit(1);
    16.     }
    17.      vector<Kitchen *>members(10);
    18.    
    19.     for (unsigned int i = 0; i < members.size(); i++)
    20.     {
    21.         members[i] = new Kitchen;
    22.         fin >> *members[i];
    23.         if(members[i]->ret_name() != "Empty")
    24.         {        
    25.             cout << *members[i] << endl << endl;
    26.             fout << *members[i] << endl << endl;
    27.         }
    28.     }
    29.     vector<Kitchen *>::iterator It;
    30.     It = members.begin();
    31.     It+=5;
    32.     members.erase(It);
    33.     Kitchen * const  temp2 = new Kitchen("Greg","Bacon-Sandwich-chef",30000,23,2);
    34.     //cout << temp2->salary_details() << endl;
    35.     It = members.begin();
    36.     It+=5;
    37.     members.insert(It,temp2); //temp2 now invalidated. attempting to delete temp2 after this statement will result in a runtime error
    38.     cout << "output all elements after insertion.\n\n";
    39.     for (unsigned int j = 0; j < members.size(); j++)
    40.     {
    41.         if(members[j]->ret_name() != "Empty")
    42.         {
    43.             cout << *members[j] << endl << endl;
    44.             fout << *members[j] << endl;
    45.         }
    46.      }
    47.     int retire = 0,promo = 0,less5 = 0;
    48.     double tot_salaries = 0;
    49.     for(unsigned int k = 0; k < members.size(); k++)
    50.     {
    51.         if(members[k]->ret_name() != "Empty")
    52.         {
    53.             if(members[k]->retirement_check())
    54.                 retire++;
    55.             if(members[k]->promotion_check())
    56.                 promo++;
    57.             if(members[k]->service_check())
    58.                 less5++;
    59.             tot_salaries +=  members[k]->salary_details();
    60.         }
    61.     }
    62.  
    63.     cout << "Total chefs due for retirement:\t\t\t" << retire << endl
    64.          << "Total chefs due for promotion:\t\t\t" << promo << endl
    65.          << "Total chefs with service less than 5 years:\t" << less5 << endl
    66.          << "Total cost of salaries:\t\t\t\t" << "Euro: " << tot_salaries << endl << endl;
    67.  
    68.     fout << "Total chefs due for retirement:\t\t\t" << retire << endl
    69.          << "Total chefs due for promotion:\t\t\t" << promo << endl
    70.          << "Total chefs with service less than 5 years:\t"  << less5 << endl
    71.          << "Total cost of salaries:\t\t\t\t" << "Euro: " << tot_salaries << endl;
    72.  
    73.     for (unsigned int j = 0; j < members.size(); j++)
    74.     {
    75.         cout << *members[j] << endl << endl;
    76.         fout << *members[j] << endl;
    77.     }
    78.  
    79.     cout << "Total salaries for chef 1 and 2 is: " << (*members[0] + *members[1]).salary_details() << endl;
    80.     if(*members[1] >= *members[2])
    81.         cout << "Chef 1 has a larger or equal salary than Chef 2.\n\n";
    82.     if(*members[1] > *members[2])
    83.         cout << "Chef 1 has a larger salary than Chef  2.\n\n";
    84.     if(*members[1] == *members[1])
    85.         cout << "These two chefs have equal salaries.\n";
    86.  
    87.     for(unsigned int i = 0; i < members.size(); i++)
    88.     {
    89.         delete members[i];
    90.     }
    91.     return 0;
    92. }[/i][/i][/i][/i][/i][/i]
     
  2. Mark44

    Well-Known Member

    Nov 26, 2007
    626
    1
    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
     
  3. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    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
     
  4. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    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!

    Code ( (Unknown Language)):
    1. #include <iostream>
    2. #include <vector>
    3. using namespace std;
    4.  
    5. class test
    6. {
    7. public:
    8.     test();
    9.     test(const char*);
    10.     test(const test &); //copy constructor
    11.     virtual ~test();
    12.     char* reader();
    13.  
    14. private:
    15.         char * ptr;
    16. };
    17.  
    18. test::test()
    19. :ptr(new char[50])
    20. {
    21.     //do nothing
    22. }
    23.  
    24. test::test(const char *Ptr)
    25. :ptr(new char[strlen(Ptr)+1])
    26. {
    27.     strcpy(ptr,Ptr);
    28. }
    29.  
    30. test::test(const test & G)
    31. :ptr(new char[strlen(G.ptr) + 1])
    32. {
    33.     strcpy(ptr,G.ptr);
    34. }
    35.  
    36.  
    37. test::~test()
    38. {
    39.     delete [] ptr;
    40. }
    41. char * test::reader()
    42. {
    43.     return ptr;
    44. }
    45.  
    46. int main()
    47. {
    48.     vector<test *>members(10);
    49.     for(int i = 0; i < 10; i++)
    50.     {
    51.         if (i != 7)
    52.             members[i] = new test("hello");
    53.         else members[i] = new test ("this is a test");
    54.     }
    55.  
    56.     vector<test *>::iterator it = members.begin();
    57.     it+=5;
    58.     delete members[5];
    59.     test * const p = new test("goodbye");
    60.     members.insert(it,p);
    61.  
    62.     for (int i = 0; i< 10; i++)
    63.         cout << members[i]->reader() << endl;
    64.    
    65.     cout << "members[8] now points to " << members[8]->reader() << endl;
    66.  
    67.     return 0;
    68.  
    69. }
    70. [/i][/i][/i]
     
  5. Mark44

    Well-Known Member

    Nov 26, 2007
    626
    1
    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
     
  6. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    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!
     
Loading...