?
Solved

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

Posted on 2013-12-08
8
Medium Priority
?
1,981 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
  • 2
8 Comments
 
LVL 35

Assisted Solution

by:sarabande
sarabande earned 800 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 1200 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 86

Assisted Solution

by:jkr
jkr earned 1200 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 1200 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 35

Accepted Solution

by:
sarabande earned 800 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

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

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

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
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 viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
Suggested Courses

762 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