Solved

using std::stringstream to print a string in hex decimal form

Posted on 2013-12-08
8
1,579 Views
Last Modified: 2014-01-04
I am using a log4cpp  to log any debug info to a file.

log4cpp::Category::getRoot() <<  log4cpp::Priority::DEBUG << "My error string";

There is time I would like to turn the error string into an array of hex codes for each character in the string

log4cpp::Category::getRoot() <<  log4cpp::Priority::DEBUG << "0x65 0x63 0x67 0x68 .. .. ..";

What is the best way to transform "My error string" to "0x65 0x63 0x67 0x68 .. .. .."
0
Comment
Question by:tommym121
  • 3
  • 3
  • 2
8 Comments
 
LVL 33

Assisted Solution

by:sarabande
sarabande earned 200 total points
ID: 39705511
you could use std::ostringstream and iomanip:

#include <sstream>
#include <iomanip>

...
std::ostringstream oss;
for (int n = 0; n < (int)input_string; ++n)
{
      oss << "0x" << std::hex << std::right << std::setw(2) << std::setfill('0')
             << (int)input_string[n] << ' ';
}

Open in new window


Sara
0
 
LVL 86

Assisted Solution

by:jkr
jkr earned 300 total points
ID: 39707165
'<algorithm>' has a few neat helpers to make that simpler, e.g.

#include <string>
#include <sstream>
#include <algorithm>
#include <iostream>
#include <iomanip>
using namespace std;


template<class T> struct hexify {

  hexify(stringstream& out) : ss(out) {}
  void operator() (T& x) { ss << setbase(16) << "0x" << (int) x << ' ';}
  stringstream& ss;
};

template<class T>
ostream& operator<<(ostream& os, const hexify<T>& h) { os << h.ss.str(); return os;}

int main() {

  string s = "My error message";
  stringstream ss;

  cout <<  for_each(s.begin(), s.end(), hexify<char>(ss)) << endl;

  // Or, as in your case:
  //
 // log4cpp::Category::getRoot() <<  log4cpp::Priority::DEBUG << for_each(s.begin(), s.end(), hexify<char>(ss)) << endl;

  return 0;
}

Open in new window

0
 

Author Comment

by:tommym121
ID: 39707551
JKR,

I really like your new trick, as I am learning to apply generic programming. (template).

One more winkle I like to add, what if I would like to print max16 Hex numbers in a row.

how would I do it.
0
NAS Cloud Backup Strategies

This article explains backup scenarios when using network storage. We review the so-called “3-2-1 strategy” and summarize the methods you can use to send NAS data to the cloud

 
LVL 86

Assisted Solution

by:jkr
jkr earned 300 total points
ID: 39707617
You mean like adding a line break after 16 characters? E.g like

#include <string>
#include <sstream>
#include <algorithm>
#include <iostream>
#include <iomanip>
using namespace std;


template<class T> struct hexify {

  hexify(stringstream& out) : ss(out), count(0) {}
  void operator() (T& x) { ss << setbase(16) << "0x" << (int) x << ' '; if(!((count +1 ) % 16)) ss << endl; ++count;}
  stringstream& ss;
  unsigned int count;
};

template<class T>
ostream& operator<<(ostream& os, const hexify<T>& h) { os << h.ss.str(); return os;}

int main() {

  string s = "My error message My error message My error message My error message";
  stringstream ss;

  cout <<  for_each(s.begin(), s.end(), hexify<char>(ss)) << endl;

  // Or, as in your case:
  //
 // log4cpp::Category::getRoot() <<  log4cpp::Priority::DEBUG << for_each(s.begin(), s.end(), hexify<char>(ss)) << endl;

  return 0;
}                                

Open in new window

0
 

Author Comment

by:tommym121
ID: 39707619
JKR,

I forget to mention if what I am trying to print out is an array of char (e.g. TCP/IP) packet, '\n' can be present in the char array, I would like to print '\n' as ASCII code  and still able to print 16 maximum HEX number in a row.  

So I suppose I can not use string or stringstream am I right
0
 
LVL 86

Assisted Solution

by:jkr
jkr earned 300 total points
ID: 39707636
The above should take care of it ;o)

Edit: *Will* definitely take care of it:

#include <string>
#include <sstream>
#include <algorithm>
#include <iostream>
#include <iomanip>
using namespace std;


template<class T> struct hexify {

  hexify(stringstream& out) : ss(out), count(0) {}
  void operator() (T& x) { ss << setbase(16) << "0x" << (int) x << ' '; if(!((count +1 ) % 16)) ss << endl; ++count;}
  stringstream& ss;
  unsigned int count;
};

template<class T>
ostream& operator<<(ostream& os, const hexify<T>& h) { os << h.ss.str(); return os;}

int main() {

  string s = "My error message\n My error message\n My error message\n My error message";
  stringstream ss;

  cout <<  for_each(s.begin(), s.end(), hexify<char>(ss)) << endl;

  // Or, as in your case:
  //
 // log4cpp::Category::getRoot() <<  log4cpp::Priority::DEBUG << for_each(s.begin(), s.end(), hexify<char>(ss)) << endl;

  return 0;
}

Open in new window

0
 
LVL 33

Accepted Solution

by:
sarabande earned 200 total points
ID: 39708622
if you want display a string buffer like a hex editor does which shows the hex values in a table at the left side and the printable characters for each row at the right side

     | 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 |
-----|-------------------------------------------------|-----------------
0000 | 48 65 6c 6c 6f 20 57 6f 72 6c 64 21 20 0a 49 20 | Hello World! .I
0016 | 61 6d 20 68 65 72 65 2e 20 57 68 65 72 65 20 61 | am here. Where a
0032 | 72 65 20 79 6f 75 3f 0a 00 00 00 00 00 00 00 00 | re you?.

Open in new window


you could advance and improve the functor jkr has shown by

struct hexedit 
{
    std::string        srow;
    int nrows;
    
    std::ostringstream & get_oss()
    {
        static std::ostringstream oss;
        return oss;
    }
    hexedit() : nrows(0)
    {
        get_oss() = std::ostringstream();
        get_oss() << "     | 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 |" << std::endl 
                  << "-----|-------------------------------------------------|-----------------" << std::endl 
                  << "0000 | ";
    }
    ~hexedit()
    {
        if (srow.empty() == false)
        {
            this->operator()('\0', true);
        }
    }
    
    void operator() (char c, bool bend = false) 
    { 
        if (bend == true)
        {
            std::string send = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ";
            send = send.substr(srow.length()*3);
            get_oss() << send << srow << std::endl;
            return;
        }
        if (srow.length() == 16)
        {
            get_oss() << "| " << srow << std::endl << std::dec << std::right << std::setw(4) << std::setfill('0') << (++nrows)*16 << " | "; 
            srow = "";
        }
        get_oss() << std::hex << std::setw(2) << std::right << std::setfill('0') << (int) c << ' '; 
        srow += (isprint(c) == 0)? '.' : c;
    }
};

std::ostream& operator<<(std::ostream& os, hexedit& he)
{   
    os << he.get_oss().str(); 
    return os;
}

int main()
{
    std::string s = "Hello World! \nI am here. Where are you?\n";  
    std::cout <<  std::for_each(s.begin(), s.end(), hexedit()) << std::endl;
    s = "0123456789012345";
    std::cout <<  std::for_each(s.begin(), s.end(), hexedit()) << std::endl;
    return 0;
}

Open in new window


note, the code doesn't use template classes as it is specialized for char type only anyhow. it also doesn't require to pass a stringstream object but uses an own temporary.

Sara
0
 

Author Closing Comment

by:tommym121
ID: 39755971
Thanks
0

Featured Post

ScreenConnect 6.0 Free Trial

Explore all the enhancements in one game-changing release, ScreenConnect 6.0, based on partner feedback. New features include a redesigned UI, app configurations and chat acknowledgement to improve customer engagement!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question