2013-03-04 7 views
5

Próbuję dowiedzieć się C++ z odrobiną tle Java i próbuję napisać kod, który zwraca punkt przecięcia dwóch list. Uważam, że mam koncepcję właściwą koncepcyjnie, ale mam problem ze składnią, ponieważ nic nie kompiluje.Początkujący C++: Przekształcenie indeksu składnia do iteratora składni

Oto kod mam wymyślić:

#include <iostream> 
using namespace std; 
#include <list> 

template <typename Object> 
list<Object> intersection(const list<Object> & L1, const list<Object> & L2){ 

    std::list<Object> result;     
    int pos1 = 0; 
    int pos2 = 0; 

    while (pos1 < L1.size() && pos2 < L2.size()) { 
    if (L1[pos1] > L1[pos2]) { 
     pos1++; 
    } else if (L2[pos2] > L1[pos1]) { 
     pos2++; 
    } else { 
     result.push_back(L2[pos2]); 
     pos1++; 
     pos2++; 
    } 
    } 
    return result; 

} 

Rzeczy Myślę, że muszę: iterator (jestem pewien sposób mam dostęp do wykazu nie jest poprawna)

+1

Zmodyfikowałem tytuł, aby uczynić go (miejmy nadzieję) bardziej opisowym i wskazał, że jest to problem stosunkowo ogólny, interesujący dla przyszłych użytkowników. Mam nadzieję, że to jest w porządku (proszę, jeśli to nie nastąpi). – jogojapan

+1

Ponieważ jesteś początkującym w C++, warto wspomnieć, że nie powinieneś używać "std :: list" ... kiedykolwiek. (Nie dlatego, że jest coś złego w klasie C++, ale ponieważ jest to straszna struktura danych). Gdy potrzebujesz tylko kontenera, zamiast niego domyślnie jest "wektor ". (To by również pozwoliło twojemu kodowi pracować z indeksami zamiast iteratorów) – jalf

+0

Dobra uwaga. "wektor" jest lepszy w większości przypadków, ale myślę, że dobrze jest znać zalety i wady zarówno "list", jak i "wektorów", a jeśli chcesz napisać dobry kod C++ w pewnym momencie musisz wiedzieć o wskaźnikach/iteratorach. – Ari

Odpowiedz

4

Zmień poz1 i pos2 do iteratorów:

list<Object> intersection(const list<Object> & L1, const list<Object> & L2){ 
    std::list<Object> result;     
    std::list<Object>::iterator pos1 = L1.begin(), pos2 = L2.begin(); 
    while (pos1 != L1.end() && pos2 != L2.end()) { 
    if (*pos1 > *pos2) { //works only if pos1 != L1.end() and pos2 != L2.end() 
     pos1++; 
     ... 

pos1 = L1.begin() punkty pos1 do pierwszego elementu L1.

++pos1 przesuwa iterator do przodu, do następnego elementu

*pos1 dostaje elementu z pos1

pos1 != L1.end() sprawdza, czy pos1 osiągnięty koniec listy. Nie można wziąć elementu od pos1, gdy pos1 == L1.end().

+0

Dziękuję bardzo, to jest dokładnie to, czego potrzebowałem. –

+1

Iterator musi być "const". –

2

trzeba nie const_iteratoriterator.

Wszystkie klasy kontenerów C++ have typedefs on them definiujące takie rzeczy, jak typ, który zawierają, i typy iteratorów, między innymi.

W twoim przypadku list<Object>::value_type jest typu Object. Więc można powiedzieć:

list<Object>::value_type object = Object(); 

Podobnie list<Object>::iterator jest typ iteratora używane do przechodzenia przez kontener. Możesz pobrać iteratory reprezentujące początek i koniec kontenera za pomocą begin() i end().

Jeśli twój kontener to const, jak w pytaniu, begin i koniec nie zwrócą iterator, zwrócą const_iterator. Nie można przypisać tego do typu iterator. Są różne, ponieważ jedna pozwala modyfikować wartość, a druga nie.

można rozwiązać problemu za pomocą const_iterator. Istnieje jednak wiele innych sposobów na rozwiązanie tego problemu.

  • auto oznacza, że ​​nie musisz jasno mówić o typie. Robi to, co właściwe dla ciebie.
  • Szablony mogą używać ogólnych parametrów, więc znowu nie musisz być jednoznaczny.
  • Biblioteka standardowa ma różne algorytmy, które mogą już robić, co chcesz (np. set_intersection).