traversing through a list - c++

im trying to traverse through a list 2 values at a time, but for some reason, its getting stuck in an infinite loop
i have:
list<mystruct> a, b; // defined, each guaranteed to have at least 1 value
a.insert(a.end(), b.begin(), b.end());
a.sort(mysort);
list<mystruct>::iterator it1 = a.begin(), it2 = it1// or = a.begin(), it doesnt seem to make a difference
it2++;
while(it2 != a.end()){// im not sure if this condition is correct; probably the error
if (<condition>){
// stuff
a.erase(it2);
}
else{
it1++;
it2++;
}
}
say the combined list a is {1,2,3,3,4,5,6,6,6,7} and that i am trying to remove duplicates. i am trying to get *i = 1 and *j = 2 at first and then shift down so *i = 2 and *j = 3. what did i do wrong in this code??
im new to c++ lists, so sorry if this question sounds silly

You want to use it2 = a.erase(it2); otherwise it2 will be pointing to an element that you've erased from the list. a.erase returns the element following it2.

Since your list appears to be sorted and you want to remove duplicates, use unique:
a.unique();
Then you don't have to mess with iterators, erasing, etc.
See http://www.cplusplus.com/reference/stl/list/unique/

Related

Looping back near the beggining using std::vector iterators

I have an iterator that needs to loop near the beginning of the vector whenever it reaches its end, for the amount it went over the end, like so:
std::vector<int> vec = {...}, vec1;
std::vector<int>::iterator it = vec.begin();
for(;vec.size() != 0;){
it += k; //k is a const integer
if(it >= vec.end()){
it -= items.end(); // something like that, but this syntax is obviously invalid
}
vec1.push_back(*it);
it = vec.erase(it);
}
So perhaps I increment vec{1,2,3,4,5} by 3, it should first remove 3, then 1 and put them in vec1, in a sense it loops around by however was left when it reached the end. I tried a bunch of different syntaxes, but there's always a type mismatch error. Is there an elegant way of doing this?
XY-solution: I recommend keeping an index instead of an iterator and use the remainder operator.
for(std::size_t i = 0; vec.size() != 0;){
i = (i + k) % vec.size();
vec1.push_back(vec[i]);
vec.erase(vec.begin() + i);
}
So perhaps I increment vec{1,2,3,4,5} by 3, it should first remove 3
This doesn't match your attempted code. If you increment iterator to first element by 3 and erase it, then you'd be erasing the element with value 4.

Iterate over a vector of pairs and access first and second element

I am trying to iterate over a vector of pairs and access first and second elements.
I cannot use auto, so I need to use the iterator.
for (list<string>::const_iterator it = dest.begin(); it != dest.end(); ++it)
{
for (vector< pair < string, string > >::iterator it2 = class1.begin(); it2 = class1.end(); ++it2)
{
if (it == it2.first)
cout << it2.second;
}
}
I keep getting errors:
Has no member named first.
I have tried: it2->first, it2.first and (*it2).first.
Why is it not working?
You are trying to compare an iterator to a string. This isn't only about the syntax to dereference it2, you also have to dereference it. The proper syntax is
if (*it == it2->first)
By the way you've made a typo, you've written it2 = class1.end() instead of it2 != class1.end().
Change this:
if (it == it2.first)
to this:
if (*it == it2->first)
since it iterates over a vector of string, so you need to dereference it to take the actual string. Similarly for it2, where instead of using * and .. together, you use -> for easiness.

How do i use the for loop for a specified range while using maps in c++

I want to use the for loops with iterators while using maps and want to run it for a specified range not from begin() end end(). I would want to use it for a range like from 3rd element to 5th element
I would want to use it for a range like from 3rd element to 5th
element
Since std::map's iterator is not a RandomAccessIterator, but only a BidirectionalIterator (you cannot write .begin() + 3), you can use std::next for this purpose:
for (auto it = std::next(m.begin(), 2); it != std::next(m.begin(), 5); ++it)
{
// ...
}
And remember - check your ranges to ensure, that you iterate over a valid scope.
This code should be pretty optimal and safe for corner cases:
int count = 0;
for( auto it = m.begin(); it != m.end(); ++it ) {
if( ++count <= 3 ) continue;
if( count > 5 ) break;
// use iterator
}
but the fact you are iterating an std::map this way shows most probably you are using a wrong container (or your logic for 3rd to 5th element is wrong)

C++ understanding iter and erase

I am just looking at a code, and I must say that I don't fully understand it yet.
vector<long>::iterator iter1;
vector<long>::iterator iter2;
while(m_vPitchMarks[0]<=vPitchPeriode[0])
{
iter1 = m_vPitchMarks.begin();
iter2 = vPitchPeriode.begin();
m_vPitchMarks.erase(iter1);
vPitchPeriode.erase(iter2);
if((m_vPitchMarks.size()==0)||(vPitchPeriode.size()==0))
break;
}
I am trying to break it down:
Here we will do a while-statement while the value of the first element of m_vPitchMarks is smaller than the value of the first element of vPitchPeriod.
while(m_vPitchMarks[0]<=vPitchPeriode[0])
{
}
Here we set something like a reference to the first element (element at index [0]) of both vectors.
iter1 = m_vPitchMarks.begin();
iter2 = vPitchPeriode.begin();
Now we erase all elements from m_vPitchMarks<> that have just this value.
For example, if iter1 had a value of 15, all elements in m_vPitchMarks<> that also have the value of 15 will be deleted, and the vector becomes shortened.
m_vPitchMarks.erase(iter1);
vPitchPeriode.erase(iter2);
Is that correct?
Thank you.
Almost as you say this:
while(m_vPitchMarks[0]<=vPitchPeriode[0])
will loop while the first value of m_vPitchMarks is less than or equal to the first value of vPitchPeriode.
Your explanation for this this code:
iter1 = m_vPitchMarks.begin();
iter2 = vPitchPeriode.begin();
m_vPitchMarks.erase(iter1);
vPitchPeriode.erase(iter2);
is not quite right. It simply removes the first value from both the vectors.
If you were using a std::deque or a std::list instead then you would just call pop_front to get the same result.
Then if we're out of values stop looping:
if((m_vPitchMarks.size()==0)||(vPitchPeriode.size()==0))
break;
Seems a particularly inefficient route given erasing an element from the front of a vector requires shifting every element that is left.

Return iterator of a sublist c++

We have a list
std::list<int> list;
// fill part of the list with 5
list.push_back(5);
list.push_back(5);
list.push_back(5);
// fill part of the list with 10
list.push_back(10);
list.push_back(10);
list.push_back(10);
// iterator that starts with 5
std::list<int>::iterator iterFiveBegin = list.begin();
//
std::list<int>::iterator iterEnd = list.end();
How can I get the iterator std::list<int>::iterator iterTenBegin of the list where it starts with "10"?
Firstly, don't use variable name list, try intList instead.
You may use std::find
std::list<int>::iterator it = std::find (intList.begin(), intList.end(), 10);
Per std::find documentation:
std::find
Return value
Iterator to the first element satisfying the condition or last if no such element is found.
Just use std::find, from the <algorithm> header:
std::list<int>::const_iterator ten = std::find(list.begin(), list.end(), 10);
Make sure to check that it is valid:
if (ten == list.end())
{
// no 10 found in list
}
Also, don't name your std::list instance "list".
if your list is sorted, I guess you can use std::lower_bound and std::upper_bound