2011-06-21 13 views
15

Io attualmente ho il seguente ciclo:Iterator per il secondo all'ultimo elemento in una lista

for(list<string>::iterator jt=it->begin(); jt!=it->end()-1; jt++) 

Ho una lista di stringhe che si trova in un elenco più ampio (list<list<string> >). Voglio scorrere il contenuto della lista interna fino a quando non arrivo al penultimo elemento. Questo perché ho già elaborato i contenuti dell'elemento finale e non ho motivo di rielaborarli.

Tuttavia, l'utilizzo di it->end()-1 non è valido - Non è possibile utilizzare l'operatore - qui. Mentre potrei usare l'operatore --, questo decrementerebbe questo iteratore finale per ogni ciclo.

Credo che una lista di STL sia una lista doppiamente collegata, quindi dal mio punto di vista, dovrebbe essere possibile farlo.

Consigli? Grazie in anticipo

risposta

9

raccomandazione Requisite di utilizzare la libreria standard:

std::for_each(lst.begin(), --lst.end(), process); 

Se non si vuole complicarsi la vita con la creazione di un funtore [ho quasi mai fare], e non è possibile utilizzare gli iteratori inverso, issare il controllo end fuori dal giro:

for(iterator i = lst.begin(), j = --lst.end(); i != j; ++i) { 
    // do 
    // stuff 
} 

in alternativa, si può semplicemente fidarsi l'ottimizzatore di riconoscere che esso non ha bisogno di mantenere ricreare la condizione di fine, e fare il sollevamento stesso. Quanto è affidabile dipende dall'implementazione della lista, e quanto è complesso il tuo codice di loop, e quanto è buono il tuo ottimizzatore.

In ogni caso, basta fare ciò che è più facile da capire e preoccuparsi delle prestazioni dopo aver finito.

+0

Ho apprezzato la semplicità di questa soluzione. Sì, altre soluzioni con iteratore inverso erano buone, ma la tua soluzione mi ha insegnato un metodo senza usare un iteratore speciale. – BSchlinker

+0

"Se non vuoi problemi con la creazione di un functor" - oggi ti consiglierei di attaccare un lambda lì – Paladin

6

Elenco iteratore non iteratore casuale. Si dovrebbe fare il seguente:

if (! it->empty()) 
{ 
    list<string>::iterator test = it->end(); 
    --test; 
    for(list<string>::iterator jt = it->begin(); jt != test; ++jt) 
    { 
    ... 
    } 
} 

Ancora una cosa: usare ++jt contro jt++. jt++ codice sorgente di solito simile a questa:

iterator operator++ (int i) 
{ 
    iterator temp = (*this); 
    ++(*this); 
    return temp; 
}; 
4

Mentre ho potuto usare l'operatore -, questo sarebbe diminuire questo iteratore finale su ogni ciclo.

No, non lo sarebbe. Otterrebbe una copia dell'iter iter finale e la diminuirà. È tutto. Non cambierebbe l'iteratore di fine memorizzato nell'elenco.

Il tuo problema principale dovrebbe essere verificare che l'elenco sia non vuoto, garantendo così che --it-> end() esista.

4

che dire di un iteratore inverso?

for(list<string>::reverse_iterator jt=++(it->rbegin()); jt!=it->rend(); jt++) 
+0

Ciò si traduce in realtà in un errore a causa dell'uso della "!" operatore nella dichiarazione "jt! = it-> rend();" – BSchlinker

+0

Il tipo dovrebbe essere 'lista :: reverse_iterator' piuttosto che solo' lista :: iteratore'. –

+0

Non ero a conoscenza di iteratori inversi - grazie! – BSchlinker

1

in C++ 11 e più tardi, la risposta migliore sembra essere quella di utilizzare std::prev

for(iterator i = lst.begin(); i != std::prev(lst.end()); ++i) { 
    // do 
    // stuff 
} 

La documentazione per std :: prev su http://en.cppreference.com/w/cpp/iterator/prev dice,

Anche se l'espressione - c.end() spesso compila, non è garantito che lo faccia: c.end() è un'espressione rvalue e non esiste un requisito iteratore che specifica che il decremento di un valore rvalore funzioni. In particolare, quando gli iteratori sono implementati come puntatori, --c.end() non compila, mentre std :: prev (c.end()) lo fa.

Credo std :: prev() su un elenco vuoto non è definito, quindi potrebbe essere necessario per avvolgere questo in una condizione !i.empty()

Problemi correlati