I have the following method in my program.
Weird thing is the data is not removed after I call erase.
Any idea?
map<int,obj>::iterator it = this->indexMap.find(id);
if(it != this->indexMap.end())
{
int mapSize = this->indexMap.size();
int dataSize = (*it).second.getDataMap().size();
//copy data to another node | even when it doesn't get into this if condition, it does not remove the data
if(mapSize> 1 && dataSize != 0)
{
it++;
this->copyData(id,it->first);
it--;
}
//remove peer | i've tried id and it, both does not work
this->indexMap.erase(it);
map<int,obj>::iterator iter = this->indexMap.find(id);
if(iter == this->indexMap.end())
{
cout << "ERROR" << endl;
}
}
Output:
ERROR
Thanks! :)
This block:
map<int,obj>::iterator iter = this->indexMap.find(id);
if(iter == this->indexMap.end())
{
cout << "ERROR" << endl;
}
prints out ERROR if an element with key id is not found in the map. Hence it has been removed.
Related
I am learning c++ and I am working my way double linked lists, but I noticed something very peculiar when I was trying to delete elements from my list.
Problem: I am inserting an element before the value of 2 in my list , numbers, and then I am trying to delete any element that has the value 1.
Expected: After I call erase() in my conditional statement in my first loop my list, numbers, should get adjusted. The only values that numbers should should contain 0,1234,2,3.
Observed: My list numbers contains the values 0,1,1234,2,3. It is as if nothing was erased.
Code Example:
#include "stdafx.h"
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> numbers;
numbers.push_back(1);
numbers.push_back(2);
numbers.push_back(3);
numbers.push_front(0);
list<int>::iterator it = numbers.begin();
it++;
numbers.insert(it, 100);
cout << "Element: " << *it << endl;
list<int>::iterator eraseIt = numbers.begin();
eraseIt++;
eraseIt = numbers.erase(eraseIt);
cout << "Element: " << *eraseIt << endl;
for (list<int>::iterator it = numbers.begin(); it != numbers.end(); it++)
{
if (*it == 2)
{
numbers.insert(it, 1234);
}
if (*it == 1)
{
it = numbers.erase(it);
}
else
{
it++;
}
}
for (list<int>::iterator it = numbers.begin(); it != numbers.end(); it++)
{
cout << *it << endl;
}
return 0;
}
I would greatly appreciate any assistance with this problem. Thank you for your time.
You should remove the it++ at the end of the for loop declaration, because it might be increased inside the for loop too; when it gets inscreased twice some elements will be skipped. i.e.
for (list<int>::iterator it = numbers.begin(); it != numbers.end(); )
LIVE
It's quite enough to remember the next iterator value before doing any deletion/insertion at the current position. This will help you to keep yourself careless about what and when are your modifications concretely doing.
list<int>::iterator it = numbers.begin();
while (it != numbers.end()) {
{
list<int>::iterator next_it = it;
++next_it;
// Do your insertion or deletion here
it = next_it;
}
This question already has answers here:
How to remove from a map while iterating it?
(6 answers)
Closed 5 years ago.
I am trying to determine the maximum number of items I can remove from a list using std list to get the minimum size. However, it keeps ending up in bad memory access.
This is my recursive function:
int step (list<int> mylist) {
int count = mylist.size();
// Terminations
if (!checkRemaining(mylist)) {
return mylist.size();
}
if (mylist.empty()) {
return 0;
}
//printf("mysize: %d\n", mylist.size());
// Else we do not terminate first
for (auto i=mylist.begin(); i != prev(mylist.end()); ++i)
{
if ((*i + *next(i))%2 == 0) // Problem starts from here, bad access
{
mylist.erase(next(i));
mylist.erase(i);
printf("this size %lu\n", mylist.size());
list<int> tempList = mylist;
for (auto it = tempList.begin(); it != tempList.end(); it++) {
printf("%d ", *it);
}
printf("\n");
int temp = step (tempList);
if (temp < count) count = temp;
}
}
return count;
}
It managed to get down to the desired size but the program would crash due to bad memory access.
Once you do mylist.erase(i);, i is invalided, so your ++i in the loop is UB.
Your code should look like:
for (auto i = mylist.begin(); i != mylist.end() && i != prev(mylist.end()); /* Empty */)
{
if ((*i + *next(i)) % 2 == 0)
{
mylist.erase(next(i));
i = mylist.erase(i);
// maybe you want prev(i) if i != mylist.begin()
#ifdef DEBUG
std::cout << "this size " << mylist.size() << "\n";
for (const auto& e : myList) {
std::cout << e << " ";
}
std::cout << "\n";
#endif
count = std::min(count, step(myList));
} else {
++i;
}
}
In addition, final check should handle correctly when you remove last elements.
list<CPoint> l;
l.push_back( CPoint(1,2) );
l.push_back( CPoint(30,40) );
l.push_back( CPoint(4,6) );
l.push_back( CPoint(70,80) );
CPoint * point = 0;
for ( list<CPoint>::iterator iter = l.begin();
iter != l.end();
iter++)
{
cout << iter->x << " , " << iter->y << endl;
// compilation error, I can't typcast it like below?
point = (CPoint *) iter;
}
The problem with above is that how to typcast the iter in the loop to the actual data structure pointer? That way I can write code like point.x, point.yto say the least.
The above is the demo code I wrote but in reality I have this code in a search function. If an item is found in the list, it will return pointer to that item otherwise NULL. In order to get that pointer back I need to dereference the iterator back to the underlying data structure pointer but how? Thanks.
To fix your syntax error, you need to dereference iterator then take the address from the underneath object:
point = &*iter;
You'd better just use std::find/std::find_if and store the iterator which is returned from std::list.
auto it = std::find_if(l.begin(), l.end(),
[](const CPoint& cp) { return cp.x == 1 && cp.y == 2; } );
if (it != l.end()) // test iterator to see is desired CPoint is found
{
std::cout << (*it).x << " " << (*it).y << std::endl;
}
I cannot find the reason why my program throws a SIGBART error.
I've narrowed it down when this function is called.
bool Node::isEdgeConnected(Node vertex1, Node vertex2){
//I'm not sure if this is the right way to copy this vector <list>
vector<list<Node> > myEdgeList = *edgeList;//edgeList is a private data member of Node
vector<list<Node> >::iterator it;
cout << myEdgeList.size();
for (it = myEdgeList.begin(); it != myEdgeList.end(); it++) {
list<Node> edge;
edge = *it;
Node placeNode = edge.front();
cout <<placeNode.getNodeId()<<endl;
list<Node>::iterator eIt;
for (eIt = edge.begin(); eIt != edge.end(); eIt++) {
Node placeNode1, placeNode2;
placeNode1 = edge.front();
placeNode2 = *eIt;
cout << placeNode1.getNodeId() << " " << placeNode2.getNodeId()<<endl;
if(placeNode1.getNodeId() == vertex1.getNodeId() &&
placeNode2.getNodeId() == vertex2.getNodeId()){
return true;
}
}
}
return false;
}
Any help would be appreciated.
Most likely your code fails in line Node placeNode = edge.front();, you need to check if edge is empty or not
if (edge.empty()){
continue;
}
Node placeNode = edge.front();
BTW, isEdgeConnected() function is just to check node value inside edgeList, you don't need to copy all elements. if your edgeList is big, copy will be expensive.
For example, you could iterate edgeList directly, also ++iter is more efficient than `iter++, see this
for (vector<list<Node> >::iterator it = edgeList->begin();
it != edgeList->end(); ++it) {
}
If i iterate over a STL container i sometimes need to know if the current item is the last one in the sequence. Is there a better way, then doing something like this? Can i somehow convert rbegin()?
std::vector<int> myList;
// ....
std::vector<int>::iterator lastit = myList.end();
lastit--;
for(std::vector<int>::iterator it = myList.begin(); it != myList.end(); it++) {
if(it == lastit)
{
// Do something with last element
}
else
{
// Do something with all other elements
}
Try the following
std::vector<int>::iterator it2 = (++it);
if ( it2 == myList.end() ) {
...
}
The following should work as well
if ( it+1 == myList.end() ) {
// it is last
...
}
Maybe you can iterate backwards (use rbegin/rend) and put your special task before the loop or replace the end check with it != lastit and put the special handling after the loop
I would have some doubts about my design if some elements need to be treated differntly, but this suggestion is a bit cleaner for me (don't forget to test for empty containers)
std::vector<int>::iterator lastit = myList.end();
if (lastit != myList.begin())
{
lastit--;
for(std::vector<int>::iterator it = myList.begin(); it != lastit; ++it)
{
// Do
}
// Do with last
}
Use reversed iteration, this way you will have only one end()-1-like computation (notice the rbegin()+1) and no comparsions:
for(vector<int>::iterator it = myValues.rbegin()+1; it != myValues.rend(); it++) {
cout << *it << endl;
}
cout << "Process last one: " << *myValues.rbegin() << endl;
Also, for the vector<>, computing end()-1 is probably fast, so you can also do it like following:
for(vector<int>::iterator it = myValues.begin(); it != myValues.end()-1; it++) {
cout << *it << endl;
}
cout << "Process last one: " << *myValues.rbegin() << endl;
If you don't want to process the element after the loop, you can:
for(vector<int>::iterator it = myValues.rbegin(); it != myValues.rend(); it++) {
if(it == myValues.rbegin())
cout << "Process last one: " << *it << endl;
else
cout << *it << endl;
}
For a random access iterator like that for vector, you don't need the temporarary. You can say:
if ( it + 1 == v.end() ) {
// at one before end
}
Edit: And even for non-random access types one could use std:;distance:
if ( distance( it, v.end() ) == 1 ) {
// at one before end
}
An important question is: why create a loop if you do something special for 1 element. Why not do something special to the 3rd element? To every 4rth? ...
Just iterate over the elements to be treated the same, write separate code to treat the others.
Have a look at answers to this question, too.
Why not:
if(!myList.empty())
last_it = myList.begin() + myList.size()-1;
else
last_it = myList.end();
//or
last_it = myList.empty() ? myList.end() : myList.begin() + myList.size() - 1;
If you're using a vector, it's actually much simpler to use an integer index to iterate:
std::vector<int> myList;
for (unsigned int i = 0; i < myList.size(); i++)
{
if (i == (myList.size() - 1))
{
processDifferently (myList[i])
}
else
{
process (myList[i])
}
}
Minimizing the number of calls to myList.size() is left as an exercise for the OP :)