Например:
for( auto &iter: item_vector ) {
if(not_on_the_last_element) printf(", ");
}
или
for( auto &iter: skill_level_map ) {
if(not_on_the_last_element) printf(", ");
}
Например:
for( auto &iter: item_vector ) {
if(not_on_the_last_element) printf(", ");
}
или
for( auto &iter: skill_level_map ) {
if(not_on_the_last_element) printf(", ");
}
Ты не можешь. Такова точка диапазона, что вам не нужны итераторы. Но вы можете просто изменить свою логику о том, как вы печатаете запятую, чтобы напечатать ее, если она не первая:
bool first = true;
for (auto& elem : item_vector) {
if (!first) printf(", ");
// print elem
first = false;
}
Если это намерение цикла в любом случае. Или вы можете сравнить адреса:
for (auto& elem : item_vector) {
if (&elem != &item_vector.back()) printf(", ");
// ...
}
Нет отличного метода. Но если у нас есть легкий доступ к последнему элементу контейнера...
std::vector<int> item_vector = ...;
for (auto & elem : item_vector) {
...
if (&elem != &item_vector.back())
printf(", ");
}
Эти типы петель лучше всего пишутся с помощью Loop and half":
#include <iostream>
#include <vector>
int main()
{
auto somelist = std::vector<int>{1,2,3,4,5,6,6,7,8,9,6};
auto first = begin(somelist), last = end(somelist);
if (first != last) { // initial check
while (true) {
std::cout << *first++;
if (first == last) break; // check in the middle
std::cout << ", ";
}
}
}
Живой пример, который печатает
1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 6
то есть. без разделителя в конце последнего элемента.
Проверка в середине - это то, что делает это отличным от do-while (check up front) или for_each/range-based (для проверки в конце). Попытка принудительного циклического цикла на этих циклах вводит либо дополнительные условные ветки, либо дублирующую программную логику.
безопасно сохраните этот код в файле заголовка в вашем маленьком пакете утилит:
namespace detail {
template<class Iter>
struct sequence_emitter
{
sequence_emitter(Iter first, Iter last, std::string sep)
: _first(std::move(first))
, _last(std::move(last))
, _sep(std::move(sep))
{}
void write(std::ostream& os) const {
bool first_element = true;
for (auto current = _first ; current != _last ; ++current, first_element = false)
{
if (!first_element)
os << _sep;
os << *current;
}
}
private:
Iter _first, _last;
std::string _sep;
};
template<class Iter>
std::ostream& operator<<(std::ostream& os, const sequence_emitter<Iter>& se) {
se.write(os);
return os;
}
}
template<class Iter>
detail::sequence_emitter<Iter>
emit_sequence(Iter first, Iter last, std::string separator = ", ")
{
return detail::sequence_emitter<Iter>(std::move(first), std::move(last), std::move(separator));
}
то вы можете испускать любой диапазон любого контейнера без трейлинг-разделителя следующим образом:
vector<int> x { 0, 1, 2, 3, 4, 5 };
cout << emit_sequence(begin(x), end(x)) << endl;
set<string> s { "foo", "bar", "baz" };
cout << emit_sequence(begin(s), end(s), " comes before ") << endl;
ожидаемый вывод:
0, 1, 2, 3, 4, 5
bar comes before baz comes before foo
Это похоже на шаблон состояния.
#include <iostream>
#include <vector>
#include <functional>
int main() {
std::vector<int> example = {1,2,3,4,5};
typedef std::function<void(void)> Call;
Call f = [](){};
Call printComma = [](){ std::cout << ", "; };
Call noPrint = [&](){ f=printComma; };
f = noPrint;
for(const auto& e:example){
f();
std::cout << e;
}
return 0;
}
Output:
1, 2, 3, 4, 5
Первый раз через f
указывает на noPrint
, который служит только для f
, а затем указывает на printComma
, поэтому запятые только печатаются перед вторым и последующим элементами.
Диапазон, основанный на цикле, производится для итерации по всему диапазону. Если вы этого не хотите, почему бы вам просто не сделать регулярный цикл?
auto end = vector.end() - 1;
for (auto iter = vector.begin(); iter != end; ++iter) {
// do your thing
printf(", ");
}
// do your thing for the last element
Если вы не хотите повторять код дважды, чтобы "сделать свою вещь", как я бы хотел, тогда создайте лямбду, которая делает это:
auto end = vector.end() - 1;
// create lambda
for (auto iter = vector.begin(); iter != end; ++iter) {
lambda(*iter);
printf(", ");
}
lambda(vector.back());