3

I have a small problem: I am using an iterator to go through a list, but I can't seem to access previous positions using just it.

std::list<int>::iterator i;
for(i=mylist.begin();i!=mylist.end();i++)
{
        if(*i<0) fprintf(fout,"%d",*(i-1));//here i want to access the (i-1)th element 
}
Jongware
  • 22,200
  • 8
  • 54
  • 100
Mihnea Gafton
  • 61
  • 1
  • 8
  • 1
    Or you could create a new variable after that `if` and save the `i` in that variable, and check with it at the next `if`. Edit:see my answer. – bitcell Nov 11 '14 at 10:13

4 Answers4

2

You can try std::prev:

fprintf( fout,"%d",*std::prev(i) )
Columbo
  • 60,038
  • 8
  • 155
  • 203
2

Here's one way to do it that works with C++03:

#include <iostream>
#include <list>

int main()
{
    std::list<int> mylist { 11, -22, -33, 44, -55 };
    std::list<int>::iterator i, j;
    if (!mylist.empty())
    {
        for (i = mylist.begin(); ++i != mylist.end(); )
            if (*i < 0)
                printf("%d ",*--(j=i));
        printf("\n");
    }
}

With C++11 you can replace the malarky with j with std::prev(i), as Columbo first suggested....

Notice that I changed your loop to avoid potential attempted access to some imagined element "before" *begin(). You can see it running here.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Without C++11, I'd still use a function instead of that malarkey (but writing it myself or using [boost](http://www.boost.org/doc/libs/release/libs/utility/utility.htm)). As well as less head-scratching to see what it's doing, it would prevent mistakes like http://stackoverflow.com/questions/26864387 – Mike Seymour Nov 11 '14 at 12:12
  • @MikeSeymour's function suggestion's good, indeed - it's normally a good idea to implement (or take from `boost` if available) something providing as close to the C++11 interface as possible to make it easy for C++11-literate programmers to follow and reduce later porting effort. The linked "mistakes" question exhibits typical "undefined behaviour for lack of sequence point" errors that people manage to do with a single iterator anyway - not sure that's particularly relevant). – Tony Delroy Nov 12 '14 at 02:38
1

There are different categories of iterators (see Types of iterator : Output vs. Input vs. Forward vs. Random Access Iterator). Your code requires a random access iterator, whereas std::list only provides a bi-directional iterator.

One way to work around this is to save the previous value in a variable and use that instead of *(i-1).

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
0
std::list<int>::iterator i;

int temp = mylist.begin(); //temp variable to save the past i

for(i = mylist.begin(); i != mylist.end(); i++)
{
    if(*i<0) fprintf(fout,"%d", temp);//here i want to access the (i-1)th element 
    temp = *i;
}

Something like this.

bitcell
  • 921
  • 8
  • 16