Aby odpowiedzieć na twoje pytanie, możesz użyć iteratora:
std::vector<char> path;
// ...
for (std::vector<char>::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
Jeśli chcesz zmodyfikować zawartość wektora w pętli for, użyj iterator
raczej niż const_iterator
.
Ale jest o wiele więcej do powiedzenia na ten temat. Jeśli chcesz tylko odpowiedzi, której możesz użyć, możesz zatrzymać się tutaj; w przeciwnym razie czytaj dalej.
auto (C ++ 11) / typedef
To nie jest kolejne rozwiązanie, ale uzupełnienie powyższego iterator
rozwiązania. Jeśli używasz standardu C ++ 11 (lub nowszego), możesz użyć auto
słowa kluczowego, aby poprawić czytelność:
for (auto i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
Ale typem i
będzie non-const (tzn. Kompilator użyje std::vector<char>::iterator
jako typu i
).
W takim przypadku możesz równie dobrze użyć typedef
(nie ograniczonego do C ++ 11 i bardzo przydatnego w każdym razie):
typedef std::vector<char> Path;
Path path;
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
licznik
Możesz oczywiście użyć typu liczby całkowitej, aby zapisać swoją pozycję w for
pętli:
for(int i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
Jeśli masz zamiar to zrobić, lepiej użyć typów członków kontenera, jeśli są one dostępne i odpowiednie. std::vector
ma typ członka wywołany size_type
dla tego zadania: jest to typ zwracany przez size
metodę.
// Path typedef'd to std::vector<char>
for( Path::size_type i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
Dlaczego nie wykorzystać tego zamiast iterator
rozwiązania? W prostych przypadkach równie dobrze możesz, ale chodzi o to, że iterator
klasa jest obiektem zaprojektowanym do wykonywania tego zadania w przypadku bardziej skomplikowanych obiektów, w których to rozwiązanie nie będzie idealne.
oparte na zakresie dla pętli (C ++ 11)
Zobacz rozwiązanie Jefffreya . W C ++ 11 (i nowszych) możesz użyć nowej for
pętli opartej na zakresie , która wygląda następująco:
for (auto i: path)
std::cout << i << ' ';
Ponieważ path
jest wektorem elementów (jawnie std::vector<char>
), obiekt i
jest typu elementu wektora (tj. Jawnie jest typu char
). Obiekt i
ma wartość będącą kopią faktycznego elementu w path
obiekcie. Dlatego wszystkie zmiany i
w pętli nie są zachowane path
same w sobie. Dodatkowo, jeśli chcesz, aby wymusić na fakt, że nie chcesz, aby móc zmienić skopiowane wartości i
w pętli, można wymusić typ i
być const char
tak:
for (const auto i: path)
std::cout << i << ' ';
Jeśli chcesz zmodyfikować elementy path
, możesz użyć odwołania:
for (auto& i: path)
std::cout << i << ' ';
a nawet jeśli nie chcesz modyfikować path
, jeśli kopiowanie obiektów jest drogie, powinieneś użyć stałego odwołania zamiast kopiowania według wartości:
for (const auto& i: path)
std::cout << i << ' ';
std :: kopia
Zobacz odpowiedź Jozuego . Za pomocą algorytmu STL std::copy
można skopiować zawartość wektora do strumienia wyjściowego. Jest to eleganckie rozwiązanie, jeśli czujesz się z nim komfortowo (a poza tym jest bardzo przydatne, nie tylko w tym przypadku drukowania zawartości wektora).
std :: for_each
Zobacz rozwiązanie Maxa . Używanie std::for_each
jest przesadą w tym prostym scenariuszu, ale jest to bardzo przydatne rozwiązanie, jeśli chcesz zrobić więcej niż tylko drukowanie na ekranie: użycie std::for_each
pozwala na wykonanie dowolnej (sensownej) operacji na zawartości wektorowej.
przeciążenie ostream :: operator <<
Zobacz odpowiedź Chrisa , jest to bardziej uzupełnienie innych odpowiedzi, ponieważ nadal będziesz musiał wdrożyć jedno z powyższych rozwiązań w przypadku przeciążenia. W swoim przykładzie użył licznika w for
pętli. Na przykład w ten sposób możesz szybko użyć rozwiązania Jozuego :
template <typename T>
std::ostream& operator<< (std::ostream& out, const std::vector<T>& v) {
if ( !v.empty() ) {
out << '[';
std::copy (v.begin(), v.end(), std::ostream_iterator<T>(out, ", "));
out << "\b\b]";
}
return out;
}
Korzystanie z innych rozwiązań powinno być proste.
wniosek
Każde z przedstawionych tutaj rozwiązań będzie działać. To zależy od Ciebie i od tego, który kod jest „najlepszy”. Wszystko, co jest bardziej szczegółowe niż to, jest prawdopodobnie najlepiej pozostawić w innym pytaniu, w którym zalety / wady można odpowiednio ocenić; ale jak zawsze preferencje użytkownika zawsze będą odgrywać rolę: żadne z przedstawionych rozwiązań nie jest złe, ale niektóre będą ładniejsze dla każdego kodera.
uzupełnienie
To jest rozwinięte rozwiązanie wcześniejszego, które opublikowałem. Ponieważ ten post wciąż cieszył się zainteresowaniem, postanowiłem go rozwinąć i odnieść się do innych doskonałych rozwiązań, które zostały tutaj opublikowane. Mój oryginalny post miał uwagę, że wspomniany, że jeśli były zamierzający na zmodyfikowanie wektor wewnątrz for
pętli następnie istnieją dwie metody przewidziane std::vector
do elementów dostępu: std::vector::operator[]
który nie robi granice kontroli, a std::vector::at
który ma wykonać sprawdzanie ograniczeń. Innymi słowy, at
wyrzuci, jeśli spróbujesz uzyskać dostęp do elementu poza wektorem i operator[]
nie zrobi tego. Pierwotnie dodałem ten komentarz tylko po to, by wspomnieć o czymś, co może być przydatne, jeśli ktoś już tego nie zrobił. I nie widzę teraz żadnej różnicy. Stąd to uzupełnienie.