2

I'm testing a piece of code that performs a hash operation (sha256) of a binary file and I've got something like this:

for(i = 0; i < SHA256_DIGEST_LENGTH; i++) printf("%02x", c[i]);

This prints something like:

12b64492d18aa37d609f27cb02ce5ba381068d1ef5625193df68451c650a2b8d

I'm asking how can I do to get the string shown below into a string variable in C++.

thanks

1
  • 5
    If you like printf, there's sprintf. If you like iostreams, there's stringstream. Commented Jul 11, 2017 at 14:51

3 Answers 3

6
#include <iomanip>
#include <sstream>
#include <string>
std::ostringstream oss;
for(int i = 0; i < SHA256_DIGEST_LENGTH; ++i) 
{
      oss << std::hex << std::setw(2) << std::setfill('0') << +c[i];
}
auto str = oss.str();
Sign up to request clarification or add additional context in comments.

1 Comment

Why auto rather than string?
1

For printing out hex values, you can use std::hex format; for setting width and fill character, use std::setw and std::setfill, which are part of <iomanip>. As you do not show the data type of c, I suppose/suggest to use an unsigned integral type, e.g. unsigned char. I slightly adapted the code to make it self contained):

#define SHA256_DIGEST_LENGTH 256

#include <iostream>
#include <sstream>
#include <iomanip>

int main() {

    unsigned char c[SHA256_DIGEST_LENGTH];
    for (unsigned int i=0; i<SHA256_DIGEST_LENGTH; i++)
        c[i]=i;

    std::stringstream ss;
    for(int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
        ss << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)c[i];
    }

    std::cout << ss.str();
}

Output:

000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff

2 Comments

This just prints the loop index, not the characters in the source array that the OP wants to convert...
@underscore_d: right; I just wanted to demonstrate the use of std::hex, and as OP does not specify the type of c, I rewrote that part. But: adapted answer now to make a suggestion on the type of c.
0

Just for comparison, here's the sprintf version:

#include <stdio.h>
#include <string>

std::string ss;
ss.resize(SHA256_DIGEST_LENGTH * 2 + 1); // includes space for terminating NUL
int used = 0;
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
    used += sprintf(&ss[used], "%02x", c[i]);
ss.resize(used);

Note that there's no harm in making the buffer larger than necessary initially because the final exact size is used, but if there's any possibility the buffer is too small then one must use snprintf and also pass the buffer space remaining (ss.size() - used).

3 Comments

I would use a char[] to receive the formatted data, then construct a string from the char[]
@RemyLebeau: There's no advantage to that, std::string is a smart-pointer wrapper for a char[], and even if you use a statically-sized local array, you still end up stuck with an extra copy. The way I show is better. For even more efficiency, scrap the sprintf call (which has to parse a format string) and just do two char assignments, corresponding to high- and low-nibble, directly into the std::string.
I guess technically a raw allocated array has the advantage that you can obtain space uniitialised then write what you want to it - whereas C++ containers require you toresize() and thus set some known value in the new capacity before just overwriting it, or reserve() then emplace_/push_back() piece by piece, making the library check capacity, increment size, etc each time. Still, I doubt it matters usually, so the extra safety and readability of the C++ versions win in such cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.