Mar 7, 2011

Exploiting the STL: Sending a vector<byte> to cout as ints

I've been working on an embedded project that has to send byte command streams to a touch screen. I store all these command streams in vector<byte> containers. (where byte is just a typedef of unsigned char) When debugging I want to see what these vectors contain. Unfortunately doing any kind of loop that extracts element  and  then doing
cout << element << ",";
would treat the bytes as the underlying unsigned chars that they actually are so instead of seeing this:                                      254, 132, 1, 0,0,0,0
I might see this:                þ,y,,    ,,,
An old trick is to write the output like this:
cout << element +0 << ",";
While this works it starts to become problematic when you want to use some of the built in algorithms for looping through containers.
I'll eventually get to a reasonably elegant solution but I started with a rather naïve one that I'll show because it makes following along to the final template a bit easier.
Well, it works. It's a little verbose and we aren't really taking any advantage of the built in power of C++. This code is begging for either the for_each or copy algorithm.  We can see how we might just use for_each
for_each(data.begin(), data.end(), printIt);
< like looks cout data send copy using idiom standard A copy. use almost can know also I However, data). printIt(char function member non a create>
And then we would need a non-member function printIt(char data) to do the conversion to short and output the comma. However, there's a common idiom using the copy algorithm of the STL that almost does what we want:
copy (data.begin, data.end(), ostream_iterator<byte>(cout, ",") );
Well we did get from ten lines down to one and we are using some built in features but  were back to the funny looking character stream. >þ,y,,    ,,,
The answer is to use an ostream_iterator<short> to send out the data. Now of course we want this to work with more than just vectors of bytes so we can create a template, but we're going to need two types if we want to handle the case where we pass in bytes <T1> but we treat them like shorts <T2>. Here's the resulting template and as a bonus it supports writing out the vector in hex or decimal (BaseOutput is just an enum with UseHex and UseDecimal members). Remember to include <iterator>, <iomanip> and <iostream. If your doing this for the NetBurner you'll need to put this template in a  .h file.
A call of this template to send a vector<bytes> out as shorts and have them show in hex would  look like this:

About Me

My photo
Tod Gentille (@todgentille) is now a Curriculum Director for Pluralsight. He's been programming professionally since well before you were born and was a software consultant for most of his career. He's also a father, husband, drummer, and windsurfer. He wants to be a guitar player but he just hasn't got the chops for it.