How about not writing the extra ", "
at the end in the first place...
if(!v.empty())
{
std::copy(v.begin(), v.end()-1, std::ostream_iterator<std::string>(os, ", "));
os << v.back();
}
Вопрос
I want to use std::copy
and std::ostream_iterator
to print out the string within a vector
as a coma separated list between parenthesis. So I have to deal with the issue of removing the ", "
after the last element.
I have tried this:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>
int main() {
std::vector<std::string> v;
v.push_back("a");
v.push_back("b");
v.push_back("c");
std::stringstream os;
os << '(';
std::copy(v.begin(), v.end(), std::ostream_iterator<std::string>(os, ", "));
os.seekp(-2, std::ios_base::cur);
os << ')';
std::cout << os.str() << ".";
return 0;
}
Output:
(a, b, c) .
^
But the output I get has an extra white space character after the closing parenthesis, because seekp
just moves the writing position but doesn't remove the written characters.
Is there a way to remove that last character or write an EOF?
Решение
How about not writing the extra ", "
at the end in the first place...
if(!v.empty())
{
std::copy(v.begin(), v.end()-1, std::ostream_iterator<std::string>(os, ", "));
os << v.back();
}
Другие советы
You are not just removing the characters when you use seekp
, you are setting the current cursor. Your next statement will overwrite that character, but you still have the subsequent characters in the buffer already. There are a couple of ways to deal with that:
Don't output the full pattern:
std::ostringstream os;
os << '(';
std::copy(v.begin(), v.end() - 1, std::ostream_iterator<std::string>(os, ", "));
if (v.size() > 1) // or (!v.empty())
os << *(v.end() - 1) << ')';
This will print all but the last character of your vector with the pattern (the extra ", " combination will be avoided entirely).
Alternatively, you can reset the buffer manually:
std::ostringstream os;
os << '(';
std::copy(v.begin(), v.end(), std::ostream_iterator<std::string>(os, ", "));
std::string t = os.str();
t.resize(t.size() - 2);
os.str() = t;
os << ')';
Or, perhaps a more uniform solution (if you are not opposed to not using copy):
std::ostringstream os;
os << '(';
if (v.size() > 1) // or (!v.empty())
os << v.front();
std::for_each(v.begin() + 1, v.end(), [&](const std::string& s)
{
os << ", " << s;
});
os << ")";