Reputation: 1095
I can do it with plain for loop:
vector<unsigned char> v{3, 13, 23, 83};
stringstream ss;
for (auto &el : v)
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(el);
cout << ss.str() << endl;
I am seeking methods that allow me to use std::copy:
std::copy(
std::begin(v),
std::end(v),
std::ostream_iterator<int>(ss << std::hex << std::setw(2) << std::setfill('0'))
);
which does not give me same output values as the for loop method. I have two questions on this:
Upvotes: 0
Views: 247
Reputation: 6474
In order to use the standard algorithms and an output iterator we can define a new class and overload the stream insertion operator <<
. The operator <<
is called by std::copy
for every item we want to stream.
template <class T>
class HexOut
{
public:
HexOut(T val) : value(val)
{
}
friend std::ostream& operator<<(std::ostream& os, const HexOut<T>& elem)
{
os << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(elem.value) << std::dec;
return os;
}
private:
T value;
};
int main()
{
std::vector<unsigned char> v{ 3, 13, 23, 83 };
std::copy(v.begin(), v.end(), std::ostream_iterator<HexOut<unsigned char>>(std::cout));
return 0;
}
Here the operator <<
is setting the right output flags each time and casting the unsigned char to an int. As you can see we had to write more code and define a new class. This is probably overkill for a simple task as this. However, using an iterator makes it portable across different types of streams and we take advantage of the many algorithm functions such std:copy
. Plus all the formatting is contained inside the operator <<
, which makes it more maintainable.
Upvotes: 1
Reputation: 418
Your method using std::copy is the same as
ss << std::hex << std::setw(2) << std::setfill('0');
std::copy(
std::begin(v),
std::end(v),
std::ostream_iterator<int>(ss)
);
the width set by std::setw goes away after the first output operation so only the output for the first character will have it.
To use std::copy, you would have to write a custom iterator instead of using std::ostream_iterator.
Your first method is better because it is shorter and easier to understand.
Upvotes: 1