Re: Printing non-printable characters
On 18 mai, 09:55, Alex Vinokur <alex.vino...@gmail.com> wrote:
Hi,
// --------------------
#include <iostream>
#include <iomanip>
int main()
{
char data[5];
data[0] = 'a';
data[1] = 5;
data[2] = 'b';
data[3] = 10;
data[4] = 0;
for (std::size_t i = 0; i < sizeof(data); i++)
{
char ch = data[i];
if (isprint(static_cast<int>(ch)) != 0)
{
std::cout << ch;
}
else
{
std::cout << "\\" << std::oct << static_c=
ast<int>(ch) << std::dec;
}
}
std::cout << std::endl;
return 0;
}
// ------------------
Output:
a\5b\12\0
Is it possible to get the same or similar output without loop in the
program?
There is James Kanze's filtering streambuf technique. I don't have it
right now because the last time I checked, his site on neuf.fr was
down.
But you can still use a hand made streambuf filter which wrap a
streambuf and use overflow function for encoding the output (defining
the relevant underflow is left as an exercise and is much harder):
class EncodedStreambuf : public streambuf
{
public:
EncodedStreambuf( streambuf* sbuf );
public: // decorates m_sbuf
virtual int underflow() ;
virtual int sync() ;
virtual streambuf* setbuf( char* p , int len ) ;
// encode output
virtual int overflow( int ch ){
if ( ch == EOF || isprint( ch ) ) return m_sbuf->overflow( ch );
// should encode - chech for usual \r\n... that shouldn't be
encoded
char code[5]="\\000";
ch|=0x00ff;
char* it=&code[4];
while(ch){
*it=ch&0x07;
ch>>3;
}
return m_sbuf->xsputn(code,sizeof(code)-1);
}
private:
streambuf* m_sbuf ;
} ;
Well, I hope you get the idea.
Then you can define EncodedStream that take in input a stream and
installs the wrapping streambuf in it upon construction and restore it
upon destruction.
Something like:
class EncodingOStream
{
public:
EncodingOStream( std::ostream& os)
: m_encoder(os.rdbuf()) // build EncodedStreambuf
{
os.rdbuf(&m_encoder); // install EncodedStreambuf
}
~EncodingOStream(){
os.rdbuf(m_encoder.streambuf()); // uninstall EncodedStreambuf
}
// ....
};
In the final code, you simply write:
char data[5];
data[0] = 'a';
data[1] = 5;
data[2] = 'b';
data[3] = 10;
data[4] = 0;
EncodedOstream os(std::cout);
std::cout<<data<<std::endl;
Now that I have given the hard solution, a simple solution if you
don't mind the overhead is:
std::string encodeString( std::string const & str )
{
// boilerplate for encoding string
}
and
std::cout<<encodeString(data)<<std::endl;
--
Michael