Solved

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

Posted on 2013-12-08
8
1,454 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 32

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
 
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
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 

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 32

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

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

757 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now