1

I am trying to do the following:

I have an assembled ostringstream object that contains a hex payload to be transmitted. Say, it might be

03125412349876543210af     (this is representing the data using hex convention in my string)

This string is representing 11 bytes, so for example the last byte to be transmitted is 0xaf (two characters giving me 8 bits of actual data).

I wish to read each pair of characters, for example the '03' pair of characters in the string and convert that into a uint8_t element which I will push onto a vector of uint8_t elements. Essentially I will create a new vector of uint8_t elements based on the contents of the string, then transmit the vector.

My test program below works OK for 'int' but does not give me what I want for uint8_t. Is there an elegant and/or straightforward way to do what I am trying to do that anyone can suggest?

(Note: example 3 was to see what happens if a non-hex-legal value was used. In example 1, a value like 34r0 would convert 34(hex) to an equivalent int and ignore the r and everything following it).

#include <iostream>
#include <sstream>
#include <string>
using namespace std;

int main()
{
    cout << "Hello world!" << endl;

    // example 1: making a hex string an int - works
    std::stringstream str1;
    std::string s1 = "5f";
    str1 << s1;
    int value1;
    str1 >> std::hex >> value1;
    cout << value1 << endl; // produces 95 - perfect

    cout << "~~~~~~~~~" << endl;

    // example 2: making a hex string a uint8 - not the result I want
    std::stringstream str2;
    std::string s2 = "5f";
    str2 << s2;
    uint8_t value2;
    str2 >> std::hex >> value2;
    cout << value2 << endl; // produces 5 - not what I want!

    cout << "~~~~~~~~~~~" << endl;

    // example 3: using non-hex values
    std::stringstream str3;
    std::string s3 = "wx";
    str3 << s3;
    uint8_t value3;
    str3 >> std::hex >> value3;
    cout << value3 << endl; // produces w - not what I want!

    // this does not work either
    uint8_t value4;
    cout << "~~~~~~~~~~~~~~" << endl;
    value4 = (uint8_t)value1;
    cout << value4 << endl; // produces - - not what I want!

    cout << "............." << endl;


    return 0;
}

The output from this test program looks like the below:

Hello world!
95
~~~~~~~~~
5
~~~~~~~~~~~
w
~~~~~~~~~~~~~~
_
.............

Process returned 0 (0x0)   execution time : 0.022 s
Press any key to continue.

Example 1 works OK, but using int - this is not what I need.

Spangas
  • 15
  • 2

2 Answers2

0

In example 2 you are extracting a uint8_t, 8 bits, so one char from the string, the 5.

In example 3 is the same, you extract the first char, so the w.

For the last example, it prints a char (8 bits), 95 is the ASCII - character. If you want to show the number, cast the value to int.

value4 = (uint8_t)value1;
cout << (int)value4 << endl;
Manuel
  • 2,526
  • 1
  • 13
  • 17
  • Hi Manuel, yes, thanks you are correct casting value4 to into before streaming produces 95 (the correct value). So I can do this in two steps (assign then cast). Still, I can't help thinking there should be a more elegant way to convert a hex string to bits. – Spangas Jul 11 '20 at 21:44
  • Hi Manuel, yes, thanks you are correct casting value4 to int before streaming produces 95 (the correct value). So I can do this in two steps (assign then cast). Still, I can't help thinking there should be a more elegant way to convert a hex string to bits. – Spangas Jul 11 '20 at 22:00
  • @Spangas I've upvoted the question because in fact, I didn't know we can convert strings from hex to other type with the `>>` operator. As an aside note, it seems the `>>` conversion will work with the right side parameter, so it takes as many bytes as they fit in the parameter: 8, 16, 32, 64 bits. – Manuel Jul 12 '20 at 15:22
0

Thanks to Manuel for his answer. This is one way to solve the problem. I'd still like to know if there is a more elegant way to do this.

#include <iostream>
#include <sstream>
#include <string>
using namespace std;

int main()
{
    cout << "Hello world!" << endl;

    // example 1: making a hex string an int - works
    std::stringstream str1;
    std::string s1 = "5f";
    str1 << s1;
    int value1;
    str1 >> std::hex >> value1;
    cout << "value 1 as int: " << value1 << endl; // produces 95 int - OK but an int
    uint8_t value2;
    value2 = (uint8_t)value1;
    cout << "value 2 as uint8: " << (int)value2 << endl; // produces 01011111 = 95 or '-' - correct

    return 0;
}

Which produces:

Hello world!
value 1 as int: 95
value 2 as uint8: 95

Process returned 0 (0x0)   execution time : 0.022 s
Press any key to continue.
Spangas
  • 15
  • 2
  • `std::string s = "5f0066"; int num = std::stoi(s, 0, 16);` being `16` the base you want to convert from. There is also [other](https://en.cppreference.com/w/cpp/string/basic_string/stol) converters to longer values. – Manuel Jul 12 '20 at 15:26