# Vectors

Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last
• 11-26-2004
Callith
Vectors
I read cprogramming.com's tutorial on the vector class, and I understand how they work. However, I encountered yet another problem while programming a console based address book.

I want the user to be able to delete a contact from a vector of contacts, and (obviously) specify which contact to delete.

I know there is a clear() function already provided to the vector class, and I was wondering if there is any way to delete specific elements of the vector using the [] operators?

I'm really confused on how to accomplish this, so any help would be appreciated. I don't want to post an entire program here get an answer to a simple question, so if anyone wants/needs to see the code, contact me.

Also, is there a function provided for sorting the vector in any way? If not it's no big deal because I'm pretty sure I could write one for my needs, but it would be handy to have a reference. (I've only glanced over basic sorting algorithms, such as bubble sort and all that.)

Ever since I registered for this board and started using it (like two days ago) I've been making tremendous progress towards my programming education. ^^ I thank you all. This project has been a great learning experience so far.

Thankee. =)
• 11-26-2004
Zach L.
There is an erase function which takes an iterator (or pair of them -- start and end): http://cppreference.com/cppvector_details.html#erase

There is also a sort method in <algorithm>. http://www.sgi.com/tech/stl/sort.html
It takes a begining and ending iterator (vec.begin() and vec.end() for example), and a weak ordering relation (basically some sort of 'less than operator'). The type if a function object (something derived from binary_function of which an example is here: http://www.sgi.com/tech/stl/binary_function.html )

If any of that seems incomprehensible (which it certainly can be) just post here and I (or someone else can help.

Cheers
• 11-26-2004
big146
Vectors provide no operation to remove elements directly that have a certain value.You must use an algorithm to do this.
Take a look at this and it might clear things up a little for ya.
Code:

```#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() {         vector<char> v;         int i;         for( i = 0; i <= 24; ++i )                 v.push_back(i + 'A' );         cout << "Contents of v is: " << endl;         for( i = 0; i < v.size(); ++i )                 cout << v[i];         cout << endl;         vector<char>::iterator p;         p = find( v.begin(), v.end(), 'G' );         if(p != v.end() )                 v.erase(p);         for(i = 0; i < v.size(); ++i )                 cout << v[i];         cout << endl; }```
• 11-26-2004
hk_mp5kpdw
There are other containers that can provide you with all that you seek to do. A set or multiset container for instance will allow you to erase specific elements using either an iterator or a copy of the element you wish to search for. It will also automatically sort the elements you add to it, provided you tell it how the elements should be ordered by implementing the less-than operator. A set will only store unique elements while a multiset can be used to store many elements with the same value. As an example:

Code:

```#include <iostream> #include <iterator> #include <algorithm> #include <string> #include <set> class person { public:     std::string name;     // Constructors     person() {}     person(const std::string& rhs) { name = rhs; }     // Friend operators     friend bool operator<(const person& lhs, const person& rhs);     friend std::ostream& operator<<(std::ostream& os,const person& rhs); }; //Friend insertion operator, needed to make "copy" work properly std::ostream& operator<<(std::ostream& os,const person& rhs) {     return os << rhs.name; } //Friend less-than operator, needed to make "erase" and //automatic sorting work properly bool operator<(const person& lhs, const person& rhs) {     return lhs.name < rhs.name; } int main() {     std::set<person> strSet;     strSet.insert(person("Robert"));     strSet.insert(person("Johnson"));     strSet.insert(person("Albert"));     std::cout << "Before erasing Johnson: ";     std::copy(strSet.begin(),strSet.end(),               std::ostream_iterator<person>(std::cout," "));     // Provide a copy of element "Johnson" to the erase function     strSet.erase(person("Johnson"));     std::cout << "\nAfter erasing Johnson : ";     std::copy(strSet.begin(),strSet.end(),               std::ostream_iterator<person>(std::cout," "));     std::cout << std::endl;     return 0; }```
This should output:

Code:

```Before erasing Johnson: Albert Johnson Robert After erasing Johnson : Albert Robert```
As you can see, even though the elements were inserted in reverse alphabetical order, the set container automatically sorted them properly because that is how I implemented the less-than operator in this case.

If it looks like the copy function and overloading of the insertion operator is too confusing for you, they can be removed and a more conventional looping mechanism can be used to output the contents of the set container to the screen... but you do need the less-than operator to define how the elements are to be sorted.
• 11-26-2004
manofsteel972
A simple way to delete an item from a vector is to swap it with the last element then pop_back() to remove the last element
• 11-27-2004
VirtualAce
Also in vectors do NOT erase() the first element of the vector. If the vector has an odd number of members there is a specific way you must erase them. I've encountered this in my recent project and it is quite annoying.
• 11-27-2004
Sang-drax
Quote:

Originally Posted by Bubba
Also in vectors do NOT erase() the first element of the vector. If the vector has an odd number of members there is a specific way you must erase them. I've encountered this in my recent project and it is quite annoying.

Hmmm, you mean this doesn't work?
It should:
Code:

```vec.erase(vec.begin(),vec.begin()+1); //or vec.erase(vec.begin());```
• 11-27-2004
VirtualAce
It does except that any future access to the vector will crash the program.
• 11-27-2004
Hunter2
This seems to run fine. MSVC 6.0 professional edition:
Code:

```#include <vector> #include <iostream>   int main() {   std::vector<int> x(5);   x.erase(x.begin());     x[0] = 2;   for(std::vector<int>::iterator it = x.begin(); it != x.end(); ++it)         std::cout << *it;     std::cin.get();   return 0; }```
Perhaps it was just a bug in your compiler Bubba? I really can't imagine the standard requiring different deletion methods for odd an even sized vectors.
• 11-28-2004
VirtualAce
Hmm. Shakti and I have come across the bug. I thought it was stupid that the vector implementation did not account for this housekeeping issue. Perhaps it is a bug in my code.

I'll post and let you see for yourself. For some reason I cannot delete the first laser object in the vector - future firing of lasers and thus adding a laser to the vector CTD's the entire game.
Code:

```void Update(D3DXVECTOR3 &_ObjectVector,D3DXMATRIX view,float timeDelta)     {                 //D3DXMATRIX proj;       //Device->GetTransform(D3DTS_PROJECTION,&proj);       std::vector<CLaser>::iterator laser;       LasersDrawn=0;       for (laser=Lasers.begin();laser!=Lasers.end();laser++)       {                 //D3DXMATRIX InvView;         //D3DXMatrixInverse(&InvView,0,&view);                 if (laser->Properties.LifeTimer>laser->Properties.LifeDistance)         {           if (laser!=Lasers.end())           {             laser=Lasers.erase(laser);             NumLasers--;           }                   }         if (laser!=(Lasers.end()))         {               LasersDrawn++;               laser->Properties.LifeTimer+=timeDelta;               laser->Properties.Position+=                 (laser->Properties.VelocityVector*laser->Properties.Speed)*timeDelta;               Render(timeDelta,view,laser);         }```
As you can see I'm constantly checking for the end of the vector yet this loop should never ever get there. If you could help I would be greatly indebted to you as this bug is annoying me. The code right now looks like crap but I had to code it this way or the thing crashed.
• 11-28-2004
VirtualAce
Actually in order not to hijack this thread could you discuss the solution over in my new screenshots thread on the game programming board.

Or if you think it will add to others understanding of vectors perhaps it would be appropriate to post it here. Your decision.
• 11-28-2004
Callith
Another problem.
Well, infact I have another question.
I worked on the code abit more and wrote everything, but it won't compile now. I looked at a few examples and checked out a few more reference sites and vector tutorials, but I think it has to do with member functions returning a value. I'm not sure though. My program won't compile.

It's a syntax error inside of list::list *deleteContact()

I was hoping someone could take a look at it and tell me what I did wrong.

The line that gives me the error is:
contactList=(contactList[(contactNo-1)].contactDelete(contactList);

contactList is a protected data member of list of type vector<contact>, which gets the new value of the new contactList after deleteing a contact.

Maybe someone could look at my program and tell me why it doesn't succesfuly compile? I've tried everything I can think of to fix the compile error. =(

Code:

```#include <iostream> #include <vector> #include <string> using namespace std; class contact{     protected:         string validField[4];         string cFirstName;         string cLastName;         string cEmail;         string cPhoneNumber;             int contactNo;     public:         contact(string *firstName, string *lastName){             cFirstName=(*firstName);             cLastName=(*lastName);             cEmail="Unknown";             cPhoneNumber="Unknown";                         validField[0]="First Name";             validField[1]="Last Name";             validField[2]="E-Mail";             validField[3]="Phone Number";         }         void quickDisplay(){             cout<<cLastName<<", "<<cFirstName<<endl;             return;         }         string firstName(){             return (cFirstName);         }            void edit(){             int select;             string newValue;             for (int i=0;i<4;++i){                 cout<<(i+1)<<". "<<validField[i]<<endl;             }             cout<<"Which field would you like to edit (1-4, 0 aborts): ";             cin>>select;             cout<<endl;             if (!(select>=1&&select<=4)){                 cout<<"Invalid choice. Aborting edit.";                 return;             }             cout<<"Enter new "<<validField[(select-1)]<<" for "<<cFirstName<<": ";             cin>>newValue;                         switch (select){                 case 1:                     cFirstName=newValue;                     break;                 case 2:                     cLastName=newValue;                     break;                 case 3:                     cEmail=newValue;                     break;                 case 4:                     cPhoneNumber=newValue;                     break;                 default:                     cout<<"Error: Selection does not represeent valid field..."<<endl;                     return;                     break;             }             return;         }         vector<contact> *contactDelete(vector<contact> loadedContactList){             vector<contact>::iterator matchingContact;             for (matchingContact=(loadedContactList.begin());(matchingContact)<=(loadedContactList.end());++matchingContact){                 if ((matchingContact->contactNo)==(this->contactNo)){                     loadedContactList.erase(matchingContact);                 }             }             return (&loadedContactList);             }                     void view(){             cout<<validField[0]<<": "<<cFirstName<<endl;             cout<<validField[1]<<": "<<cLastName<<endl;             cout<<validField[2]<<": "<<cEmail<<endl;             cout<<validField[3]<<": "<<cPhoneNumber<<endl;             return;         } };     class list{     public:         list(string *newListName){             listName=(*newListName);             loaded=true; // If there's an instance, it's been loaded.         }         vector<contact> loadedContactList(){             return (contactList);         }         void unload(){             loaded=false;             return;         }         void view(){             cout<<endl                 <<"Contact List: "<<listName<<endl;             for (int i=0;i<(contactList.size());++i){                 cout<<(i+1)<<". ";                 contactList[i].quickDisplay();             }                         cout<<"Blank"<<endl; //Instructions for viewing a specific contact in detail goes here                            return;         }         inline bool loadCheck(){             if (loaded==false){                 cout<<"Please [l]oad or [c]reate a list first..."<<endl;                 return (false);             }             return (true);         }            list *createContact(){             if (!loadCheck()){                 return (this);             }             string firstName;             string lastName;             cout<<"Please enter the new contact's first name: ";             cin>>firstName;             cout<<endl;             cout<<"Please enter the new contact's last name: ";             cin>>lastName;             cout<<endl;             contact newContact(&firstName, &lastName);             contactList.push_back(newContact);             cout<<"Your new contact has been successfully created."<<endl;             return (this);         }         list *editContact(){             if (!loadCheck()){                 return (this);             }             int contactNo;             view();             cout<<"Which contact would you like to edit? (1-"<<(contactList.size())<<", 0 aborts): ";             cin>>contactNo;             cout<<endl;             if ((contactNo<=0)||(contactNo>contactList.size())){                 cout<<"Editing Aborted."<<endl;                 return (this);             }                         cout<<"Editing "                 <<(contactList[(contactNo-1)].firstName())<<endl;                contactList[(contactNo-1)].edit();             cout<<"Field successfully changed."<<endl;             return (this);         }         void viewContact(){             if (!loadCheck()){                 return;             }             int contactNo;             view();             cout<<"Which contact would you like to view? (1-"<<(contactList.size())<<", 0 aborts): ";             cin>>contactNo;             cout<<endl;             if ((contactNo<=0)||(contactNo>contactList.size())){                 cout<<"Viewing Aborted."<<endl;                 return;             }             cout<<"Now viewing "                 <<(contactList[(contactNo-1)].firstName())<<endl;             contactList[(contactNo-1)].view();             return;         }         list *deleteContact(){             if (!loadCheck()){                 return (this);             }             int contactNo;             view();             cout<<"Which contact would you like to delete? (1-"<<(contactList.size())<<", 0 aborts): ";             cin>>contactNo;             cout<<endl;             if ((contactNo<=0)||(contactNo>contactList.size())){                 cout<<"Deletion aborted."<<endl;                 return (this); //Note: I might need to return the new contact list to loadedList for the filestreams to work correctly             }             char confirm;             cout<<"Are you sure who want to delete "                 <<(contactList[(contactNo-1)].firstName())                 <<"? (All details will be lost upon saving.) [Y/N]: ";             cin>>confirm;                 if (confirm=='y'||confirm=='Y'){                 contactList=(contactList[(contactNo-1)].contactDelete(contactList);                 cout<<"Deletion successful. Remember to save.";             }             else cout<<"Deletion aborted."<<endl;             return (this);         }                protected:         bool loaded;         string listName;         vector<contact> contactList; };     //Prototypes void commandLine(); list createNewList(); int main(){     cout<<"Welcome to the console based Contact Manager."<<endl         <<"Input 'h' at the '->' for help."<<endl<<endl;         commandLine();         return (0); } void commandLine(){     char command;     string blankString;         list loadedList(&blankString); //Creates a blank list     loadedList.unload(); //blank list does not count as a loaded list     do{         cout<<endl;         cout<<"-> ";         cin>>command;         cout<<endl;                 switch (command){             case 'h':             case 'H':                 cout<<"Issue a command by inputting the coresposnding"<<endl                     <<"letter in brackets at the command line. [->]"<<endl                     <<endl                     <<"[H]elp"<<endl                     <<"[Q]uit"<<endl                     <<"[C]reate New Contact List"<<endl                     <<"[L]oad Contact List"<<endl                     <<"V[i]ew Contact List"<<endl                     <<"[S]ave Contact List"<<endl                     <<"[D]elete Contact List"<<endl                     <<"Create [N]ew Contact"<<endl                     <<"[E]dit Contact Details"<<endl                     <<"[V]iew Contact Details"<<endl                     <<"Dele[t]e Contact"<<endl                     <<endl;                 break;             case 'q':             case 'Q':                 cout<<"Are you sure you want to quit? [Y/N]: ";                 cin>>command;                 cout<<endl;                 if (command=='Y'||command=='y'){                     return;                 }                 break;             case 'c':             case 'C':                 char confirm;                 cout<<endl                     <<"Are you sure? Make sure to save the current list. [Y/N]: ";                 cin>>confirm;                 cout<<endl;                 if (confirm=='y'||confirm=='Y'){                     loadedList=createNewList();                     cout<<"Your new list has been created and loaded."<<endl;                 }                 break;             case 'i':             case 'I':                 loadedList.view();                 break;             case 'n':             case 'N':                 loadedList=(*(loadedList.createContact())); //changes are made to list here                 break;             case 'e':             case 'E':                 loadedList=(*(loadedList.editContact())); //and here                 break;             case 'v':             case 'V':                 loadedList.viewContact();                 break;             case 't':             case 'T':                 loadedList=(*(loadedList.deleteContact())); // and here. They all should return value of (&this).                 break;             default:                 cout<<"That is an invalid command. Input 'h' for help."<<endl;                 break;         };            }     while(true);     return; } list createNewList(){     string newListName;         cout<<"Please input a name for the new list: ";     cin>>newListName;         list newList(&newListName);         return (newList); }```
Thanks.
Callith

PS I'm new at both programming and posting on this message board. If that was too much code (which I think it was) don't hesitate to tell me. I don't want to be an annoyance.
• 11-28-2004
Zach L.
Better too much code/detail than not enough. :)
In this case, though, I didn't need to look at any of your code. Count the number of opening parentheses and closing parentheses in this line. ;)
Code:

`contactList=(contactList[(contactNo-1)].contactDelete(contactList);`
Cheers
• 11-28-2004
Hunter2
Bubba:
Code:

```if (laser->Properties.LifeTimer>laser->Properties.LifeDistance) { if (laser!=Lasers.end()) {```
This just seems somewhat odd, since you're checking if the iterator is valid AFTER you've already dereferenced it, but I assume that you're already aware of this. [snip]*see edit*[/snip]

**EDIT**
Hm, on second thought, from what I see in your code, every time you delete a laser, the iterator will skip the next laser: You delete the laser, assign the iterator to the next laser, and then you hit the end of the loop and the iterator increments again; thus you've skipped the laser in between. So if you have an odd number of iterators:

0) You have 3 elements
1) Delete element 0, iterator now points to element 0 (previously element 1)
2) Do something with element 0, increment iterator; now points to element 1 (formerly 2)
0b) You now have 2 elements, iterator points to element 1 (last)
1b) Delete this element, iterator now points to end
2b) If iterator != end, do nothing; increment iterator; now points 1 beyond end
0c) You now have 1 element, iterator points beyond the end of the sequence (still != end).
1c) Try to dereference it, and BOOM! kablooey, your loop crashes.

One quick solution I can think of is, stick it in a while loop and do the iterator management by hand (if you erase an element, don't increment iterator).
• 11-28-2004
Callith
Thanks for pointing that out Zach, but it just went back to the error I had before. There's no match for operator=, which I thought (for vectors,) just replaced one vector with the new one. SHouldn't the last part technically be the value of a vector?

I'm confused.
Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last