I'm facing some problems with set::iterators in c++. I have a set of 2-D points and I need to iterate and compare these points three by three.
My thought was to use three loops incrementing the iterators, one by one. But c++ gave me an error when I tried:
for (set<pair<double, double> >::iterator i = S.begin(); i != S.end(); i++){
for (set<pair<double, double> >::iterator j = i+1; j != S.end(); j++){
...
}
}
Edit: the error was "error: no match for ‘operator+’ in ‘i + 1’"
std::set has a bidirectional iterator. It has no such operation as iterator + integer number. So use instead
for (set<pair<double, double> >::iterator j = std::next( i ); j != S.end(); j++){
Related
I have a vector with char type;
vector<char> a_chars;
and it contains 6 characters but 3 of them are duplicate.
How can I delete the duplicate char? Here is my current code and it doesnt compile:
for(int i = 0; i < a_chars.size(); i++)
{
char current = a_chars.at(i);
for(int j = i+1; j < a_chars.size(); j++)
{
if (current == a_chars.at(j))
{
a_chars.erase[j];
}
}
}
here is the compile error: "C:invalid types '[int]' for array subscript|"
EDIT:
Also I have tried with a_chars.erase(j) and a_chars.erase(a_chars.at(j) and still had compile error.
You can use std::unique with combination of vector::erase method (known as erase-remove idiom). The vector has to be, however, sorted.
vector<char> a_chars;
std::sort(a_chars.begin(), a_chars.end());
a_chars.erase(std::unique(a_chars.begin(), a_chars.end()), a_chars.end());
If you don't want to sort your vector. You can use following snippet to remove duplicites.
void remove_duplicities(std::vector<char>& vec)
{
for (auto iter = vec.begin(); iter != vec.end(); ++iter)
{
for (auto jter = std::next(iter); jter != vec.end(); ++jter)
{
if (*iter == *jter)
jter = std::prev(vec.erase(jter));
}
}
}
After some attempts I found out by my self.
It is not working with a_chars.erase[j]; nor a_chars.erase(j); neither a_chars.erase(a_chars.at(j));. All I had to do is make an iterator and make it same as 'j'.
vector<char>::iterator itr = a_chars.begin();
itr+=j;
a_chars.erase(itr);
I'm trying to create a set of loops with iterators and I'm having trouble with some iterator arithmetic (that I thought was possible but is not working).
Below is some code:
for (list<Term>::iterator itr = final.begin(); itr != final.end(); itr++) {
for(list<Term>::iterator j = itr + 1; j != final.end(); j++) {
cout << itr->term << " " << j->term;
if(itr->term == j->term) {
//Do stuff
}
}
}
What I am trying to do is have j start at the next place in the queue along from itr. The reason for this is I don't want to check the first item against itself. The error itself comes from the part in the code where I have specified itr + 1. Now I was sure with pointers you could do arithmetic like this, why is it not working with the list iterator (which is essentially the same thing?)
The error I am getting from my IDE is as follows: main.cpp:237:48: error: no match for ‘operator+’ in ‘itr + 1’. Again I thought you could do this sort of arithmetic on iterators so I'm not really sure what to do to make this work, is there an alternate implementation I could try?
list iterators are not random access so you cannot do + with them. They are bidirectional iterators so the only movement operations you can do are -- and ++. You can either make a copy and use ++ on it, or make a copy and std::advance(it, 1).
For C++11 there is also std::next which gives you it + 1, without you having to explicitly make a named copy like you do with the others.
list has bidirectional iterators, that doesn't support operator +. You can use std::advance, or std::next in C++11.
for (list<Term>::iterator j = next(itr); j != final.end(); ++j)
or
list<Term>::iterator j = itr;
advance(j, 1); // or ++j
for (; j != final.end(); ++j)
I have a vector < vector < Point> > X and want to copy all the elements in it into a vector < Point > Y (and in the same order if is possible)
I tried something like (in a for cycle):
Y.push_back(i) = X.at(i).at(i);
but obviously it doesn't work...
I also find this (on stackoverflow) but it doesn't work for me as well...
for (std::vector<std::vector<Point> >::iterator it = X.begin(), itEnd = X.end(); it != itEnd; ++it)
Y.push_back((*it));
but the compiler tells me that "there isn't an instance of function in overload" (and honestly I don't even know what does it mean).
for(vector<vector<Point> >::iterator it = X.begin(); it != X.end(); ++it)
Y.insert(Y.end(), it->begin(), it->end());
If you know the size of the resulting vector, you could call Y.reserve(finalYSize) before the loop.
Y.push_back(i) = X.at(i).at(i);
This takes element i from the vector i. If you want to copy all the elements:
vector<vector<Point> > X;
vector<Point> Y;
//....
for ( int i = 0 ; i < X.size() ; i++ )
for ( int j = 0 ; j < X[i].size() ; j++ )
Y.push_back(X[i][j]);
Edit: As per the comments and the other answer, the more C++-ish way of doing it is found also in this question - What is the best way to concatenate two vectors?
I have a set<string> from "one", "two", and "three".
How can I get all pairs from it?
one - two
one - three
two - three
Use a two-level loop:
// Loop over all members.
for (set<string>::iterator j = s.begin(); j != s.end(); ++j)
{
// Loop over all members up to, but excluding, the current outer-loop member.
for (set<string>::iterator i = s.begin(); i != j; ++i)
{
do_something_with(*i, *j);
}
}
I'm trying to do a double-loop over a std::list to operate on each pair of elements. However, I'm having some trouble initialising the second iterator. The code I'd like to write is:
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
for(std::list<int>::iterator j = i+1; j != l.end(); ++j) {
...
}
}
That doesn't work because list iterators aren't random-access, so you can't do +1. But I'm having some trouble finding a neat alternative; the compiler doesn't seem to be very happy with std::list<int>::iterator j(i)++; which I had some hope for. Achieving what I want seems like I'm going to have to have some awkward extra increment which won't fit the structure of the for loop nicely.
There are obvious alternatives (using a vector, for example!) but it seems to me that there should be some reasonably neat way of doing this which I'm just not seeing at the moment.
Thanks in advance for any help :)
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
std::list<int>::iterator j = i;
for(std::advance(j, 1); j != l.end(); ++j) {
...
}
}
How about:
for (std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
for (std::list<int>::iterator j = i; ++j != l.end(); ) {
// ...
}
}
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
std::list<int>::iterator j = i; ++j;
for(; j != l.end(); ++j) {
...
}
}
Back in the game!
Actually, this a pretty common idiom in numerical algorithms, so I do not see it as ugly.
I'm just going off the idea I had in dirkgently's answer:
template <typename Iter, typename Dist>
Iter advance_copy(Iter pIter, const Dist& pOffset)
{
std::advance(pIter, pOffset);
return pIter;
}
// ...
typedef std::list<int> int_list;
for(int_list::iterator i = l.begin(); i != l.end(); ++i)
{
for(int_list::iterator j = advance_copy(i, 1); j != l.end(); ++j)
{
}
}
You can make another class of utility functions too, to help make it concise:
// for consistency,
template <typename Iter>
void increment(Iter& pIter)
{
++pIter;
}
template <typename Iter>
Iter increment_copy(Iter pIter)
{
return ++pIter;
}
// ...
typedef std::list<int> int_list;
for(int_list::iterator i = l.begin(); i != l.end(); ++i)
{
for(int_list::iterator j = increment_copy(i); j != l.end(); ++j)
{
}
}
The straightforward "neat" alternative can be based on the fact that list iterator is an object of user-defined type with overloaded operators (as opposed to a built-in type). (Of course, this is not formally guaranteed, but one can expect this based on the nature of the list container.) For this reason, it is possible to apply the overloaded prefix ++ operator to a temporary object of list iterator type.
To achieve what you want you just need to create a temporary copy of i, increment it using the prefix ++ and then use the resultant value to initialize j
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
for(std::list<int>::iterator j = ++std::list<int>::iterator(i); j != l.end(); ++j) {
...
}
}
And that's it. Note, that this trick is fairly popular and can be encountered in real code from time to time. Note also, that it will not generally work with std::vector because many implementations use ordinary built-in pointers as vector iterators, but it will normally work with std::list.
However, personally, I wouldn't really use this in my code. You have already received several good answers that do this by adding an extra line of code.
I'd go for Sean's suggestion, except make it a while loop:
for (std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
std::list<int>::iterator j( i );
while( ++j != l.end() ) {
// ...
}
}
If you're already using Boost, then the easiest approach is to use boost::next.
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i)
for(std::list<int>::iterator j = boost::next(i); j != l.end(); ++j)