I am looking for a fastest way to convert a byte array of arbitrary length to a hexadecimal string. This question has been fully answered here at StackOverflow for C#. Some solutions in C++ can be found here.
Are there any "turnkey" or "ready-made" solutions to a problem? C-style solutions are welcome.
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
#include <iterator>
#include <sstream>
#include <iomanip>
int main()
{
std::vector<unsigned char> v;
v.push_back( 1 );
v.push_back( 2 );
v.push_back( 3 );
v.push_back( 4 );
std::ostringstream ss;
ss << std::hex << std::uppercase << std::setfill( '0' );
std::for_each( v.cbegin(), v.cend(), [&]( int c ) { ss << std::setw( 2 ) << c; } );
std::string result = ss.str();
std::cout << result << std::endl;
return 0;
}
Or, if you've got a compiler that supports uniform initialization syntax and range based for loops you can save a few lines.
#include <vector>
#include <sstream>
#include <string>
#include <iostream>
#include <iomanip>
int main()
{
std::vector<unsigned char> v { 1, 2, 3, 4 };
std::ostringstream ss;
ss << std::hex << std::uppercase << std::setfill( '0' );
for( int c : v ) {
ss << std::setw( 2 ) << c;
}
std::string result = ss.str();
std::cout << result << std::endl;
}
Use boost::alogorithm::hex
std::vector<unsigned char> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
std::string res;
boost::algorithm::hex(v.begin(), v.end(), back_inserter(res));
You can use the C++ Standard Library and or you can use boost::lexical_cast
#include <iostream>
#include <string>
#include <array>
#include <vector>
#include <sstream>
#include <iomanip>
#include <algorithm>
using namespace std;
// use this macro for c++11 feature
#define USE_CPP11
int main(int argc, char* argv[])
{
array<unsigned char, 3> hexArr = {0x01, 0xff, 0x55};
const char separator = ' '; // separator between two numbers
ostringstream os;
os << hex << setfill('0'); // set the stream to hex with 0 fill
#ifdef USE_CPP11
std::for_each(std::begin(hexArr), std::end(hexArr), [&os, &separator] (int i)
{
os << setw(2) << i << separator;
});
#else // c++03
typedef array<unsigned char, 3>::const_iterator const_iterator;
for (const_iterator it = hexArr.begin(); it != hexArr.end(); ++it)
{
os << setw(2) << int(*it) << separator;
}
#endif
os << dec << setfill(' '); // reset the stream to "original"
// print the string
cout << "the string array is: " << os.str() << endl;
return EXIT_SUCCESS;
}
One of the fastest way I know in C++ 11:
template <size_t byteCount>
string BytesArrayToHexString( const std::array<byte, byteCount>& src )
{
static const char table[] = "0123456789ABCDEF";
std::array<char, 2 * byteCount + 1> dst;
const byte* srcPtr = &src[0];
char* dstPtr = &dst[0];
for (auto count = byteCount; count > 0; --count)
{
unsigned char c = *srcPtr++;
*dstPtr++ = table[c >> 4];
*dstPtr++ = table[c & 0x0f];
}
*dstPtr = 0;
return &dst[0];
}
A good compiler should not have any problem to apply SSE optimization on this....
Related
I try to build an std::string in the form of "start:Pdc1;Pdc2;Pdc3;"
With following code I can build the repeated "Pdc" and the incremental string "123" but I'm unable to combine the two strings.
#include <string>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iterator>
#include <numeric>
int main()
{
std::ostringstream ss;
std::string hdr("start:");
std::fill_n(std::ostream_iterator<std::string>(ss), 3, "Pdc;");
hdr.append(ss.str());
std::string v("abc");
std::iota(v.begin(), v.end(), '1');
std::cout << hdr << std::endl;
std::cout << v << std::endl;
std::cout << "Expected output: start:Pdc1;Pdc2;Pdc3;" << std::endl;
return 0;
}
How can I build this string? Preferable without a while or for loop.
The expected output is: start:Pdc1;Pdc2;Pdc3;
std::strings can be concatenated via their operator+ (or +=) and integers can be converted via std::to_string:
std::string res("start:");
for (int i=0;i<3;++i){
res += "Pdc" + std::to_string(i+1) + ";";
}
std::cout << res << "\n";
If you like you can use an algorithm instead of the handwritten loop, but it will still be a loop (your code has 2 loops, but only 1 is needed).
Code to generate your expected string, though with a small for loop.
#include <iostream>
#include <string>
#include <sstream>
std::string cmd(const std::size_t N)
{
std::ostringstream os;
os << "start:";
for(std::size_t n = 1; n <= N; ++n) os << "Pdc" << n << ";";
return os.str();
}
int main()
{
std::cout << cmd(3ul);
return 0;
}
Is it possible to use boost:hash function to generate a file content hash with fixed length like MD5?
Is there a quick solution for this?
If not, what is the simplest way?
No, Boost doesn't implement MD5. Use a crypto/hash library for this.
CryptoC++ is nice in my experience.
OpenSSL implements all the popular digests, here's a sample that uses OpenSSL:
Live On Coliru
#include <openssl/md5.h>
#include <iostream>
#include <iomanip>
// Print the MD5 sum as hex-digits.
void print_md5_sum(unsigned char* md) {
for(unsigned i=0; i <MD5_DIGEST_LENGTH; i++) {
std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(md[i]);
}
}
#include <string>
#include <vector>
#include <fstream>
int main(int argc, char *argv[]) {
using namespace std;
vector<string> const args(argv+1, argv+argc);
for (auto& fname : args) {
MD5_CTX ctx;
MD5_Init(&ctx);
ifstream ifs(fname, std::ios::binary);
char file_buffer[4096];
while (ifs.read(file_buffer, sizeof(file_buffer)) || ifs.gcount()) {
MD5_Update(&ctx, file_buffer, ifs.gcount());
}
unsigned char digest[MD5_DIGEST_LENGTH] = {};
MD5_Final(digest, &ctx);
print_md5_sum(digest);
std::cout << "\t" << fname << "\n";
}
}
boot has such functionality. At lest now: https://www.boost.org/doc/libs/master/libs/uuid/doc/uuid.html
#include <iostream>
#include <algorithm>
#include <iterator>
#include <boost/uuid/detail/md5.hpp>
#include <boost/algorithm/hex.hpp>
using boost::uuids::detail::md5;
std::string toString(const md5::digest_type &digest)
{
const auto charDigest = reinterpret_cast<const char *>(&digest);
std::string result;
boost::algorithm::hex(charDigest, charDigest + sizeof(md5::digest_type), std::back_inserter(result));
return result;
}
int main ()
{
std::string s;
while(std::getline(std::cin, s)) {
md5 hash;
md5::digest_type digest;
hash.process_bytes(s.data(), s.size());
hash.get_digest(digest);
std::cout << "md5(" << s << ") = " << toString(digest) << '\n';
}
return 0;
}
Live Example
How can I convert this code from C into C++ ?
char out[61]; //null terminator
for (i = 0; i < 20; i++) {
snprintf(out+i*3, 4, "%02x ", obuf[i])
}
I can't find any alternative for snprintf.
Use stringstream class from <sstream>.
E.g.:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
using namespace std;
int main()
{
stringstream ss;
for (int i = 0; i < 20; i++) {
ss << setw(3) << i;
}
cout << "Resulting string: " << endl;
cout << ss.str() << endl;
printf("Resulting char*: \n%s\n", ss.str().c_str() );
return 0;
}
This code is valid C++11, if you have #include <cstdio> and type std::snprintf (or using namespace std;).
No need to "fix" what isn't broken.
You can use Boost.Format.
#include <boost/format.hpp>
#include <string>
std::string out;
for (size_t i=0; i<20; ++i)
out += (boost::format("%02x") % int(obuf[i])).str();
You can convert this code from C to C++ easily with standard library's std::stringstream and iomanip I/O stream manipulators:
#include <sstream>
#include <iomanip>
...
std::ostringstream stream;
stream << std::setfill('0') << std::hex;
for (const auto byte : obuf)
stream << std::setw(2) << byte;
const auto out = stream.str();
Java has this easy method to count the tokens that you tokenize:
import java.util.*;
public class Program
{
public static void main(String[] args)
{
String str =
"This is/some text/that I am/parsing/using StringTokenizer/.";
StringTokenizer strTok =
new StringTokenizer(str, "/", false);
System.out.println("Count...");
System.out.println(strTok.countTokens());
}
}
Output:Count...6
Is there any easy way to do in C++?
You could use std::istringstreamclass along with function std::getline. For example
#include <iostream>
#include <sstream>
#include <string>
int main()
{
char s[] = "This is/some text/that I am/parsing/using StringTokenizer/.";
std::istringstream is( s );
size_t count = 0;
std::string line;
while ( std::getline( is, line, '/' ) ) ++count;
std::cout << "There are " << count << " tokens" << std::endl;
}
The output is
There are 6 tokens
Or
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main()
{
char s[] = "This is/some text/that I am/parsing/using StringTokenizer/.";
std::istringstream is( s );
std::vector<std::string> v;
std::string line;
while ( std::getline( is, line, '/' ) ) v.push_back( line );
std::cout << "There are " << v.size() << " tokens" << std::endl;
}
To build again the string from the vector you could use for example the following code
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main()
{
char s[] = "This is/some text/that I am/parsing/using StringTokenizer/.";
std::istringstream is( s );
std::vector<std::string> v;
std::string line;
while ( std::getline( is, line, '/' ) ) v.push_back( line );
std::cout << "There are " << v.size() << " tokens" << std::endl;
std::string s1;
bool first = true;
for ( const std::string &t : v )
{
if ( first ) first = false;
else s1 += '/';
s1 += t;
}
std::cout << s1 << std::endl;
}
Or you could use standard algorithm std::replace declared in header <algorithm> to replace one delimeter to another in the original string.
If your compiler does not support the range based for loop then you can write instead
for ( std::vector<std::string>::size_type i = 0; i < v.size(); i++ )
{
if ( i != 0 ) s1 += '/';
s1 += v[i];
}
You could try this:
std::vector<std::string> v(std::istream_iterator<std::string>(std::cin), {});
std::cout << "Count..." << v.size() << "\n";
This will of course tokenize at spaces, not at arbitrary separators. To split on arbitary separators, we need std::getline, but now we don't have an easy istream_iterator. Thankfully, this is a solved problem. So we write:
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
namespace detail
{
template <char Sep = '\n'>
class Line : public std::string
{
friend std::istream & operator>>(std::istream & is, Line & line)
{
return std::getline(is, line, Sep);
}
};
}
int main()
{
std::vector<std::string> v(std::istream_iterator<detail::Line<'/'>>(std::cin), {});
std::cout << "Count..." << v.size() << "\n";
for (auto const & s : v) std::cout << s << "\n";
}
If you want to tokenize an existing string rather than the standard input, use a string stream, i.e. replace std::cin with iss, where we have:
#include <sstream>
std::istringstream iss(my_input_string);
Declaration of a method are following:
//some.h
void TDES_Decryption(BYTE *Data, BYTE *Key, BYTE *InitalVector, int Length);
I am calling this method from the following code:
//some.c
extern "C" __declspec(dllexport) bool _cdecl OnDecryption(LPCTSTR stringKSN, LPCTSTR BDK){
TDES_Decryption(m_Track1Buffer, m_cryptoKey, init_vector, len);
return m_Track1Buffer;
}
Where as data type of m_Track1Buffer is BYTE m_Track1Buffer[1000];
Now i want to make some changes in above method i.e. want to return the String in hex instead of Byte. How should i convert this m_Track1buffer to Hex string
As you have mentioned c++, here is an answer. Iomanip is used to store ints in hex form into stringstream.
#include <iomanip>
#include <sstream>
#include <string>
std::string hexStr(const uint8_t *data, int len)
{
std::stringstream ss;
ss << std::hex;
for( int i(0) ; i < len; ++i )
ss << std::setw(2) << std::setfill('0') << (int)data[i];
return ss.str();
}
This code will convert byte array of fixed size 100 into hex string:
BYTE array[100];
char hexstr[201];
int i;
for (i=0; i<ARRAY_SIZE(array); i++) {
sprintf(hexstr+i*2, "%02x", array[i]);
}
hexstr[i*2] = 0;
Here is a somewhat more flexible version (Use uppercase characters? Insert spaces between bytes?) that can be used with plain arrays and various standard containers:
#include <string>
#include <sstream>
#include <iomanip>
template<typename TInputIter>
std::string make_hex_string(TInputIter first, TInputIter last, bool use_uppercase = true, bool insert_spaces = false)
{
std::ostringstream ss;
ss << std::hex << std::setfill('0');
if (use_uppercase)
ss << std::uppercase;
while (first != last)
{
ss << std::setw(2) << static_cast<int>(*first++);
if (insert_spaces && first != last)
ss << " ";
}
return ss.str();
}
Example usage (plain array):
uint8_t byte_array[] = { 0xDE, 0xAD, 0xC0, 0xDE, 0x00, 0xFF };
auto from_array = make_hex_string(std::begin(byte_array), std::end(byte_array), true, true);
assert(from_array == "DE AD C0 DE 00 FF");
Example usage (std::vector):
// fill with values from the array above
std::vector<uint8_t> byte_vector(std::begin(byte_array), std::end(byte_array));
auto from_vector = make_hex_string(byte_vector.begin(), byte_vector.end(), false);
assert(from_vector == "deadc0de00ff");
Using stringstream, sprintf and other functions in the loop is simply not C++. It's horrible for performance and these kind of functions usually get called a lot (unless you're just writing some things into the log).
Here's one way of doing it.
Writing directly into the std::string's buffer is discouraged because specific std::string implementation might behave differently and this will not work then but we're avoiding one copy of the whole buffer this way:
#include <iostream>
#include <string>
#include <vector>
std::string bytes_to_hex_string(const std::vector<uint8_t> &input)
{
static const char characters[] = "0123456789ABCDEF";
// Zeroes out the buffer unnecessarily, can't be avoided for std::string.
std::string ret(input.size() * 2, 0);
// Hack... Against the rules but avoids copying the whole buffer.
auto buf = const_cast<char *>(ret.data());
for (const auto &oneInputByte : input)
{
*buf++ = characters[oneInputByte >> 4];
*buf++ = characters[oneInputByte & 0x0F];
}
return ret;
}
int main()
{
std::vector<uint8_t> bytes = { 34, 123, 252, 0, 11, 52 };
std::cout << "Bytes to hex string: " << bytes_to_hex_string(bytes) << std::endl;
}
how about using the boost library like this (snippet taken from http://theboostcpplibraries.com/boost.algorithm ):
#include <boost/algorithm/hex.hpp>
#include <vector>
#include <string>
#include <iterator>
#include <iostream>
using namespace boost::algorithm;
int main()
{
std::vector<char> v{'C', '+', '+'};
hex(v, std::ostream_iterator<char>{std::cout, ""});
std::cout << '\n';
std::string s = "C++";
std::cout << hex(s) << '\n';
std::vector<char> w{'4', '3', '2', 'b', '2', 'b'};
unhex(w, std::ostream_iterator<char>{std::cout, ""});
std::cout << '\n';
std::string t = "432b2b";
std::cout << unhex(t) << '\n';
}