1
vector<string> v;
v.push_back("A");
v.push_back("B");
v.push_back("C");
v.push_back("D");

for (vector<int>::iterator it = v.begin(); it!=v.end(); ++it) {
//printout 
   cout << *it << endl;

}

I like to add a comma after each element as follow: A,B,C,D

I tried researching on Google, but I only found CSV to vector.

AndrewS
  • 177
  • 5
  • 21

6 Answers6

8

Loop way:

for (vector<string>::iterator it = v.begin(); it != v.end(); ++it) {
   if (it != v.begin()) cout << ',';
   cout << *it;
}

"Clever" way:

#include <algorithm>
#include <iterator>

if (v.size() >= 2)
   copy(v.begin(), v.end()-1, ostream_iterator<string>(cout, ","));
if (v.size() >= 1)
   cout << v.back();
n611x007
  • 8,952
  • 8
  • 59
  • 102
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
3

With a normal ostream_iterator, you'll get a comma after every data item -- including the last, where you don't want one.

I posted an infix_iterator in a previous answer that fixes this problem, only putting commas between the data items, not after the final one.

Community
  • 1
  • 1
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
0

Below should do the job. Thanks.

    ofstream CSVToFile("ava.csv", ios::out | ios::binary);
    //////////////////vector element to CSV////////////////////////////////////////
for (std::vector<string>::iterator i = ParamHeaders.begin(); i != ParamHeaders.end(); i++)
{
    if (i != ParamHeaders.begin()) 
    {
            CSVToFile << ",";
            std::cout << ",";
    }
    std::cout << *i;
    CSVToFile << *i;

}
AndrewS
  • 177
  • 5
  • 21
0

This is an old question but I noticed that a couple of people used two explicit tests to stop the last comma from appearing. That's unnecessary. Only need to test if the vector is not empty. If the vector contains one element then the copy becomes a no-op.

std::vector<std::string> V { "A", "B", "C", "D" };
if (!V.empty()) {
  std::copy(V.begin(), V.end() - 1, std::ostream_iterator<std::string>(std::cout, ", "));
  std::cout << V.back();
}

If you want a function that takes begin and end args:

template<typename OS, typename IT>
OS& csv(OS& os, IT begin, IT end, char const* delim = ", ") {
  if (begin != end) {
    using value_type = typename std::iterator_traits<IT>::value_type;
    std::copy(begin, end - 1, std::ostream_iterator<value_type>(os, delim));
    os << end[-1];
  }
  return os;
}
Adrian
  • 10,246
  • 4
  • 44
  • 110
0

Does really nobody know the std::experimental::ostream_joiner?. See here. To be used in algorithms, like std::copy

Or, if you do not want to use std::experimental alternatively, std::exchange? See here

Like this:

#include <iostream>
#include <vector>
#include <utility>

int main() {
    
    std::vector data{1,2,3,4};
    
    bool showComma{};
    for (const int i: data) std::cout << (std::exchange(showComma, true) ? "," : "") << i;
}

Maybe, I have a misunderstanding . . .

A M
  • 14,694
  • 5
  • 19
  • 44
-1

To avoid the trailing comma, loop until v.end() - 1, and output v.back() for instance:

#include <vector>
#include <iostream>
#include <iterator>
#include <string>
#include <iostream>

template <class Val>
void Out(const std::vector<Val>& v)
{
    if (v.size() > 1)
        std::copy(v.begin(), v.end() - 1, std::ostream_iterator<Val>(std::cout, ", ")); 
    if (v.size())
        std::cout << v.back() << std::endl;
}
int main()
{
    const char* strings[] = {"A", "B", "C", "D"};
    Out(std::vector<std::string>(strings, strings + sizeof(strings) / sizeof(const char*)));

    const int ints[] = {1, 2, 3, 4};
    Out(std::vector<int>(ints, ints + sizeof(ints) / sizeof(int)));
}

BTW you posted:

vector<string> v; 
//...
for (vector<int>::iterator it = v.begin(); //...

which is unlikely to compile :)

Alain Rist
  • 827
  • 6
  • 11