1

I have a string that represents an hexadecimal number:

std::string hex = "3371";

I want to convert it to a char array:

char hex[2] {0x33, 0x71};

Is there any convenient way to do it? I can use c++11 features, if it may help.

Motivation: I need to save an integer (4 bytes), using 2 bytes char array. The way how I thought it can be done is to convert it to string using std::hex, and then convert the string to the char array, but this is the point where I cannot continue.. If there is another simple way - I would like to hear :)

Important: I can assume that the hex number is less than 0xFFFF, and a positive number.

6
  • How to turn a hex string into an unsigned char array? stackoverflow.com/questions/3221170/… Commented Nov 9, 2017 at 14:47
  • 2
    Use std::istringstream and std::hex. Commented Nov 9, 2017 at 14:47
  • That C answer is not a duplicate. There is scope for an elegant C++11 solution. Commented Nov 9, 2017 at 14:49
  • "I need to save an integer (4 bytes), using 2 bytes char array" So you want to put 4 bytes into 2? You want to compress the data? Or do you mean 4 decimal digits? Commented Nov 9, 2017 at 14:52
  • convert it to int, and do some bit operations. Commented Nov 9, 2017 at 14:59

2 Answers 2

4

Just use std::stoi():

std::string hex = "3371";
uint16_t num = std::stoi( hex, nullptr, 16 );
uint8_t array[sizeof(num)];
memcpy( array, &num, sizeof( num ) );

note order of bytes will depend of endianness of your platform. If you need network order (as shown on your example) use htons() function:

uint16_t num = htons( std::stoi( hex, nullptr, 16 ) );
Sign up to request clarification or add additional context in comments.

2 Comments

Nice! and if I want to do the same, but with long? (i.e. save long number on char array with size 4)?
Then use std::stol() and htonl()
-1

I found out a better way to convert a number to char array, as I needed. This solution works only for unsigned types!

template <typename T> bool ToByteArray(T num, unsigned char* ret, size_t size) {
  if (ret == nullptr) {
      std::cout << "Error in: " << __func__ << ": nullptr" << std::endl;
      return false;
  }
  // drop the right-most bytes and convert to new right most byte.
  for (int i = 0; i < size; i++) {
      ret[i] = (int)((num >> (24 - 8*i)) & 0xFF);
  }
  return true;
}

This is more elegant way to do it.

If you want to convert it back - you might use:

long FormatBlock(const unsigned char* arr, size_t size) {
  long num = 0;
  for (int i = 0; i < size; i++) {
      num += ((long)arr[i] << (24 - i*8));
  }
  return num;
}

5 Comments

This is really not more elegant. It does not use C++11 features (as requested in the question), it uses old C-style character arrays and pointers. Despite using a template (why?), this looks more like C code.
1. template is there because I wan't this function to work with every type (int, short, long, etc). 2. I agree that this is a c code, but I prefer using it because it is generic for every type. The solution which Slava gave works only for integer.
Using c++11 features is not a must. If there is a better way to solve the problem - it doesn't matter if c++11 features are in use or not
"I wan't this function to work with every type (int, short, long, etc)." you will get surprises with negative values.
OK, I will add: unsigned values (I will not have data with negative values)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.