Чтобы чисто ответить на ваш вопрос, вы можете использовать итератор:
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[]не сможете . Первоначально я добавил этот комментарий только для того, чтобы упомянуть кое-что, о чем было бы полезно знать, если кто-то уже этого не сделал. И я не вижу разницы сейчас. Отсюда и это дополнение.