Solved

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

Posted on 2013-12-08
8
1,626 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
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
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

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

789 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