Щоб відповісти на ваше запитання, ви можете використовувати ітератор:
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
буде не const (тобто компілятор буде використовувати 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 << ' ';
std :: копія
Дивіться відповідь Джошуа . Ви можете використовувати алгоритм STL, std::copy
щоб скопіювати векторний вміст у вихідний потік. Це елегантне рішення, якщо вам це зручно (і до того ж це дуже корисно, не тільки в цьому випадку друку вмісту вектора).
std :: for_each
Дивіться рішення Макса . Використання std::for_each
зайвого сценарію для цього простого сценарію, але це дуже корисне рішення, якщо ви хочете зробити більше, ніж просто друк на екрані: використання std::for_each
дозволяє робити будь-які (розумні) операції над векторним вмістом.
перевантаження ostream :: оператор <<
Дивіться відповідь Кріса , це більше доповнення до інших відповідей, оскільки вам все одно потрібно буде реалізувати одне з вищезазначених рішень при перевантаженні. У своєму прикладі він використав лічильник у 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[]
не вдалося б. Я лише додав цей коментар спочатку, щоб згадати щось, про що може бути корисно знати, якщо хтось уже цього не зробив. І я зараз не бачу різниці. Звідси цей додаток.