This is the implementation as found on cplusplus.com
template <class InputIterator, class OutputIterator>
OutputIterator unique_copy (InputIterator first, InputIterator last,
OutputIterator result) {
if (first==last) return result;
*result = *first;
while (++first != last) {
typename iterator_traits<InputIterator>::value_type val = *first;
if (!(*result == val)) // or: if (!pred(*result,val)) for version (2)
*(++result)=val;
}
return ++result;
}
So when when "first" and "last" iterators point to the same element, we don't return anything? That seems out-of-line with unique_copy's definition: the first element from every consecutive group of equivalent elements in the range [first,last) is copied. Is it because of the "last)" part? Can anyone clarify? Thanks!
You are correct that the [first, last) is the problem.
When assigning iterators to containers, it is standard that the last iterator you can possible have is to the memory position 1 iteration after the last element in the container.
Ex.
vector<int> aVec{5,-8,23,200};
vector<int>::iterator currentItr, lastItr;
// iterator to first element, 5
currentItr = aVec.begin();
// iterator to element ***directly after*** last element
lastItr = aVec.end();
// in other words, there is no reason to access the value attached to lastItr
One reason why the .end() standard exists is to easily tell when the currentItr has reached past the usable values in a container;
Ex.
while (currentItr != lastItr) // currentItr will not print once it's equal to lastItr
cout << *currentItr++ << endl;
In your specific example, if there is one element in a container, then the iterators [first, last) should not be equal.
"first" is an iterator located one element to the left of iterator "last".
If first == last, then the span of possible iterators is:
[first, first)
or
[last, last)
The possible span cannot both include and exclude any iterator.
That sounds crazy.
Good luck.
Related
I'm (forward) iterating over a std::map and would like to find if the iterator points to the second last element. I can't seem to find how to do that anywhere.
I've got:
bool
isSecondLastFile(const TDateFileInfoMap::const_iterator &tsFile)
{
TDateFileInfoMap::reverse_iterator secondLastIt = mFileInfoMap.rbegin() + 1;
return (tsFile == secondLastIt);
}
Where TDateFileInfoMap is std::map
I'm getting:
error: no match for ‘operator==’ in ‘tsFile == secondLastIt’
/usr/lib/gcc/i686-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_tree.h:287: note: candidates are: bool std::_Rb_tree_const_iterator<_Tp>::operator==(const std::_Rb_tree_const_iterator<_Tp>&) const [with _Tp = std::pair<const long int, TFileInfo>]
Does that mean I can't compare the forward and reverse iterator?
How do I figure out if the forward iterator is pointing at the second last element?
std::map's iterator type is BidirectionalIterator. Just decrement the end iterator twice--first to get the last element since m.end() returns an iterator at the after the end position, and then again to get the second-last element:
auto penultimate = std::prev(m.end(), 2);
Then you can simply check for equality with the resultant iterator:
auto it = m.begin();
it == penultimate;
see it live on Coliru
Naturally, you should check that the map has two elements first if it's not guaranteed by other logic in your program.
Does that mean I can't compare the forward and reverse iterator?
Yes you can't compare them directly.
You can use base() to get the underlying base iterator.
Returns the underlying base iterator. That is
std::reverse_iterator(it).base() == it.
The base iterator refers to the element that is next (from the
std::reverse_iterator::iterator_type perspective) to the element the
reverse_iterator is currently pointing to. That is &*(rit.base() - 1) == &*rit.
e.g.
return (tsFile == (++secondLastIt).base());
BTW: mFileInfoMap.rbegin() + 1 won't compile since the iterator of std::map is not RandomAccessIterator. You might write:
TDateFileInfoMap::reverse_iterator secondLastIt = mFileInfoMap.rbegin();
++secondLastIt;
Note that we're not checking whether the map is empty or has only one element.
A simple solution for forward iterators:
template <typename ForwardIterator>
inline bool isNthLast(std::size_t n, ForwardIterator pos, ForwardIterator last) {
for( ;; --n, ++pos) {
if(n == 0)
return (pos == last);
if(pos == last)
return false;
}
}
bool isSecondLastFile(TDateFileInfoMap::const_iterator sFile) {
return isNthLast(2, sFile, mFileInfoMap.end());
}
Let's say you have a set with name s.
s= {s1,s2,...,sN-1, sN}
Now to iterate from s1.. to sN-1 (which is second last element) we will use STL functions, s.begin() and s.end().
end = s.end(); //end points to end
end--// end points to sN
Now in the for loop when itr (starts from the beginning of set) becomes equal to sN the loop will break, and you will get s1,s2,..sN-1 inside the loop.
map<int,int> s;
// to iterate till fixed range in map
auto end =s.end();
end--; // end to second last;
for(auto itr = s.begin(); itr!=end;itr++){
// do your operation
}
I am using a list in the c++ standard library and I want to know how can I get the 2nd element with an iterator. I have two iterators and I want iterator 2 to be 1 node ahead.
intPaint(string input){
list<char>sequence (input.begin,input.end);
int count;
list<char>::iterator ptr1= sequence.begin();
list<char>::iterator ptr2= ?// I want to get the second node
...//rest of the code isn't important it just checks the characters and moves
//the iterator
}
If you are indeed using C++11, then std::next() should do the trick:
list<char>::iterator ptr1 = sequence.begin();
list<char>::iterator ptr2 = std::next(sequence.begin())
From the documentation:
template <class ForwardIterator>
ForwardIterator next(ForwardIterator it,
typename iterator_traits<ForwardIterator>::difference_type n = 1);
Get iterator to next element. Returns an iterator pointing to the
element that it would be pointing to if advanced n positions.
This code snippet determines whether an integer is in a list called engie.
return std::find(engie.begin(), engie.end(), find_value) !=
engie.end();
Why is it an if statement comparing the iterator to the end of the list?
I realize the find range is from [first, last)
So for a list containing the integers {1,2,3}, isn't last = 3?
How does it find 3 if it isn't searched?
Input iterators to the initial and final positions in a sequence. The range searched is [first,last), which contains all the elements between first and last, including the element pointed by first but not the element pointed by last.
The function
find (InputIterator first, InputIterator last, const T& val) returns the position of the first match, if there is a match. Else it returns the last position. It will search in the range [first, last). This range includes the first element but not the last.
Hence in the code snippet when the iterator is not equal to the last element (i.e. engie.end) you get the match and the position of the match is returned.
You can refer this
std::find(b, e, v) searches for value v in half-open range [b,e), that is, excluding the last position e, and returns the first position where v is found, or e if v is not found in the range. So checking
std::find(b, e, v) != e
means, in words, "v is found in range [b,e)". You may think of std::find as
template<typename I, typename T>
I find(I b, I e, const T& v)
{
while (b != e && !(*b == v))
++b;
return b;
}
In the STL list {1,2,3}, end() does not point to 3, it points to one element past 3 or the "end" of the list. The find function iterates the list, and if the current iterator equals the value you're trying to find it returns the iterator. If it never finds the value it returns end() because one element past the last element in the list would be end().
The find method returns an iterator to the location (if found) or the value engie.end().
The comparison is simply converting the return value to true if found, false otherwise
I have a sorted vector and want to find a particular element in it. I can use binary_search for this but it only tells if it is present or not. I also need an iterator to access the element. Is there an easy way to this or I have to search it sequentially.
Any help appreciated.
Look into lower_bound and upper_bound. lower_bound gives the iterator to the first matching element while upper_bound gives the iterator one past the last matching element.
If either algorithm fails to find a match, it returns an iterator to the place where the item could be inserted to maintain a sorted container.
I've always felt binary_search was misleadingly named.
std::lower_bound will return the first element that is not less than your value. Meaning if the element returned is equal to your value your good, if it is not equal or the end iterator than the right element hasn't been found.
Here is the code from the dupe
template<class Iter, class T>
Iter binary_find(Iter begin, Iter end, T val)
{
// Finds the lower bound in at most log(last - first) + 1 comparisons
Iter i = std::lower_bound(begin, end, val);
if (i != end && !(val < *i))
return i; // found
else
return end; // not found
}
Remember if you use std::upper_bound than it returns the first greater element so it is not as easy to adapt to your purposes because if your element is indeed found you have to decrement the iterator and even then you still may not find it
I'm trying to implement some STL-style sorting algorithms. The prototype for std::sort looks something like this (from cplusplus.com):
template <class RandomAccessIterator>
void sort ( RandomAccessIterator first, RandomAccessIterator last );
The function is generally called like this (although the container type can vary):
std::vector<int> myVec;
// Populate myVec
std::sort(myVec.begin(), myVec.end());
I duplicated the prototype of std::sort for my own sorting function. To iterate through the container to be sorted, I do the following:
template <class RandomAccessIterator>
void mySort(RandomAccessIterator first, RandomAccessIterator last) {
RandomAccessIterator iter;
for (iter = first; iter != last; ++iter) {
// Do stuff
}
}
Easy enough. But what if I want to use a reverse iterator? This would be convenient in algorithms that sort a container from both ends, e.g. cocktail sort.
Is there any way to get a reverse iterator from the iterators that are passed in as parameters? If I knew the container type in advance, I could do something like this:
template <class RandomAccessIterator>
void mySort(RandomAccessIterator first, RandomAccessIterator last) {
std::vector<int>::reverse_iterator riter(last);
std::vector<int>::reverse_iterator rend(first);
for ( ; riter != rend; ++riter) {
// Do stuff
}
}
Unfortunately, I don't know the container type. What I really need to do is something like this:
template <class RandomAccessIterator>
void mySort(RandomAccessIterator first, RandomAccessIterator last) {
RandomAccessIterator riter = reverse_iterator(last);
RandomAccessIterator rend = reverse_iterator(begin);
for ( ; riter != rend; ++riter) {
// Do stuff
}
}
Is there some way to do this without having to pass in reverse iterators as additional parameters (which would solve the problem, but make the function prototype less intuitive)?
Note that I need both forward and reverse iterators in my implementation, so calling the function this way
std::vector<int> myVec;
// Populate myVec
mySort(myVec.rbegin(), myVec.rend());
will not work.
The STL has std::reverse_iterator<Iterator>:
template <class RandomAccessIterator>
void mySort(RandomAccessIterator first, RandomAccessIterator last)
{
typedef std::reverse_iterator<RandomAccessIterator> RIter;
RIter riter(last);
RIter rend(first);
for ( ; riter != rend; ++riter) {
// Do stuff
}
}
An important note:
Notice however that when an iterator
is reversed, the reversed version does
not point to the same element in the
range, but to the one preceding it.
This is so, in order to arrange for
the past-the-end element of a range:
An iterator pointing to a past-the-end
element in a range, when reversed, is
changed to point to the last element
(not past it) of the range (this would
be the first element of the range if
reversed). And if an iterator to the
first element in a range is reversed,
the reversed iterator points to the
element before the first element (this
would be the past-the-end element of
the range if reversed).
Check out the base() method of reverse_iterator.