Par exemple:
for( auto &iter: item_vector ) {
if(not_on_the_last_element) printf(", ");
}
ou
for( auto &iter: skill_level_map ) {
if(not_on_the_last_element) printf(", ");
}
Tu ne peux pas vraiment. C'est un peu le point de départ, c'est que vous n'avez pas besoin d'itérateurs. Mais vous pouvez simplement changer de logique pour imprimer la virgule si ce n’est pas la première:
bool first = true;
for (auto& elem : item_vector) {
if (!first) printf(", ");
// print elem
first = false;
}
Si tel est le but de la boucle quand même. Ou vous pouvez comparer les adresses:
for (auto& elem : item_vector) {
if (&elem != &item_vector.back()) printf(", ");
// ...
}
Il n'y a pas de bonne méthode. Mais si nous avons un accès facile au dernier élément du conteneur ...
std::vector<int> item_vector = ...;
for (auto & elem : item_vector) {
...
if (&elem != &item_vector.back())
printf(", ");
}
Il est préférable d’écrire ces types de boucles en utilisant la construction "Boucle et demi":
#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 << ", ";
}
}
}
Exemple en direct qui imprime
1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 6
c'est-à-dire sans séparateur à la fin du dernier élément.
Le contrôle au milieu est ce qui le rend différent de do-while (contrôle en amont) ou de for_each/range-based for (contrôle à la fin). Essayer de forcer une boucle for régulière sur ces boucles introduira soit des branches conditionnelles supplémentaires, soit une logique de programme en double.
stockez ce code en toute sécurité dans un fichier d’en-tête de votre petit paquet d’utilitaires:
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));
}
alors vous pouvez émettre n'importe quelle plage de n'importe quel conteneur sans séparateur final comme ceci:
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;
production attendue:
0, 1, 2, 3, 4, 5
bar comes before baz comes before foo
C'est comme un modèle d'état.
#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
La première fois à travers f
pointe sur noPrint
qui sert uniquement à rendre f
puis pointe sur printComma
, de sorte que les virgules ne sont imprimées qu'avant le deuxième élément et les suivants.
Les boucles basées sur la plage sont faites pour parcourir la plage entière. Si vous ne le souhaitez pas, pourquoi ne faites-vous pas une boucle régulière?
auto end = vector.end() - 1;
for (auto iter = vector.begin(); iter != end; ++iter) {
// do your thing
printf(", ");
}
// do your thing for the last element
Si vous ne voulez pas répéter le code deux fois pour "faire ce que vous voulez", créez un lambda qui l'appelle:
auto end = vector.end() - 1;
// create lambda
for (auto iter = vector.begin(); iter != end; ++iter) {
lambda(*iter);
printf(", ");
}
lambda(vector.back());