Чтобы чисто ответить на ваш вопрос, вы можете использовать итератор:
std::vector<char> path;
// ...
for (std::vector<char>::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
Если вы хотите изменить содержимое вектора в цикле for, используйте iterator
вместоconst_iterator
.
Но об этом можно сказать гораздо больше. Если вы просто хотите получить ответ, который можете использовать, тогда вы можете остановиться здесь; в противном случае читайте дальше.
auto (C ++ 11) / typedef
Это не другое решение, а дополнение к вышеуказанному iterator
решению. Если вы используете стандарт C ++ 11 (или более поздний), то вы можете использовать auto
ключевое слово, чтобы улучшить читаемость:
for (auto i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
Но тип i
будет неконстантным (т. Е. Компилятор будет использовать std::vector<char>::iterator
как типi
).
В этом случае вы также можете просто использовать typedef
(не ограничиваясь C ++ 11 и очень полезно использовать в любом случае):
typedef std::vector<char> Path;
Path path;
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
счетчик
Конечно, вы можете использовать целочисленный тип для записи вашей позиции в for
цикле:
for(int i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
Если вы собираетесь это сделать, лучше использовать типы элементов контейнера, если они доступны и уместны. std::vector
имеет тип члена, вызываемый size_type
для этого задания: это тип, возвращаемый size
методом.
// Path typedef'd to std::vector<char>
for( Path::size_type i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
Почему бы просто не использовать это поверх iterator
решения? Для простых случаев вы тоже можете, но дело в том, что iterator
класс - это объект, предназначенный для выполнения этой работы для более сложных объектов, где это решение не будет идеальным.
основанный на диапазоне для цикла (C ++ 11)
Смотрите решение Джеффри . В C ++ 11 (и позже) вы можете использовать новый for
цикл на основе диапазона , который выглядит следующим образом:
for (auto i: path)
std::cout << i << ' ';
Так path
как является вектором элементов (явно std::vector<char>
), объект i
имеет тип элемента вектора (то есть, явно, он имеет тип char
). Объект i
имеет значение, которое является копией фактического элемента в path
объекте. Таким образом, все изменения i
в цикле не сохраняются path
сами по себе. Кроме того, если вы хотите обеспечить тот факт, что вы не хотите иметь возможность изменять скопированное значение i
в цикле, вы можете сделать так, чтобы тип i
был const char
следующим:
for (const auto i: path)
std::cout << i << ' ';
Если вы хотите изменить элементы в path
, вы можете использовать ссылку:
for (auto& i: path)
std::cout << i << ' ';
и даже если вы не хотите изменять path
, если копирование объектов стоит дорого, вы должны использовать ссылку const вместо копирования по значению:
for (const auto& i: path)
std::cout << i << ' ';
станд :: копия
Смотрите ответ Иисуса Навина . Вы можете использовать алгоритм STL std::copy
для копирования векторного содержимого в выходной поток. Это элегантное решение, если вам удобно (и, кроме того, это очень полезно, не только в этом случае печати содержимого вектора).
станд :: for_each
Смотрите решение Макса . Использование этого std::for_each
избыточного сценария является излишним, но это очень полезное решение, если вы хотите сделать больше, чем просто печатать на экран: использование std::for_each
позволяет вам делать любые (разумные) операции с векторным содержимым.
перегрузка ostream :: operator <<
См . Ответ Криса , это скорее дополнение к другим ответам, так как вам все еще нужно будет реализовать одно из решений выше при перегрузке. В своем примере он использовал счетчик в for
цикле. Например, вот как вы можете быстро использовать решение Джошуа :
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;
}
Использование любого из других решений должно быть простым.
вывод
Любое из представленных здесь решений будет работать. Это зависит от вас и от того, какой код является «лучшим». Что-нибудь более подробное, чем это, вероятно, лучше оставить для другого вопроса, где плюсы / минусы можно правильно оценить; но, как всегда, предпочтение пользователя всегда будет играть роль: ни одно из представленных решений не является правильным, но некоторые будут выглядеть лучше для каждого отдельного кодера.
добавление
Это расширенное решение, о котором я писал ранее. Поскольку этот пост продолжал привлекать внимание, я решил расширить его и сослаться на другие отличные решения, которые были опубликованы здесь. Мой оригинальный пост был замечание , что отметил , что , если вы были намерены на модифицируя вектор внутри for
цикла , то есть два способа , предоставляемые std::vector
к элементам доступа: std::vector::operator[]
который не делает проверки границ, и std::vector::at
который действительно выполняет проверку границ. Другими словами, at
будет выброшено, если вы попытаетесь получить доступ к элементу вне вектора и operator[]
не сможете . Первоначально я добавил этот комментарий только для того, чтобы упомянуть кое-что, о чем было бы полезно знать, если кто-то уже этого не сделал. И я не вижу разницы сейчас. Отсюда и это дополнение.