C ++ converts mac id string to uint8_t array

I want to read the mac id from the command line and convert it to an array of values uint8_t

in order to use it in a struct. I cannot get it to work. I have a string vector to mark up mac id o :

and I want to use stringstream

to transform them with no luck. What am I missing?

int parseHex(const string &num){
  stringstream ss(num);
  ss << std::hex;
  int n;
  ss >> n;  
  return n;
}

uint8_t tgt_mac[6] = {0, 0, 0, 0, 0, 0};
  v = StringSplit( mac , ":" );
  for( int j = 0 ; j < v.size() ; j++ ){
    tgt_mac[j] = parseHex(v.at(j)); 
  }

      

+1


source to share


4 answers


I don't like answering it this way, but sscanf()

- this is probably the shortest way to parse a MAC address. It handles zero / non-zero padding, width checking, flag folding and all the other things that nobody likes with. Anyway, here's my not that C ++ version:



void
parse_mac(std::vector<uint8_t>& out, std::string const& in) {
    unsigned int bytes[6];
    if (std::sscanf(in.c_str(),
                    "%02x:%02x:%02x:%02x:%02x:%02x",
                    &bytes[0], &bytes[1], &bytes[2],
                    &bytes[3], &bytes[4], &bytes[5]) != 6)
    {
        throw std::runtime_error(in+std::string(" is an invalid MAC address"));
    }
    out.assign(&bytes[0], &bytes[6]);
}

      

+3


source


First I want to point out that I think @Steven's answer is very good - indeed, I noticed the same thing: the values โ€‹โ€‹are correct, but the output looks awkward. This is usage related since the ostream& operator<<( ostream&, unsigned char )

type uint8_t

you were using is a typedef for unsigned char

(as I found in the linux man pages). Note that on VC ++ the typedef does not exist and you should use instead unsigned __int8

(which will also guide you towards specialization char

).

Then you can test your code like this (output independent):

assert( uint8_t( parseHex( "00" ) ) == uint8_t(0) );
assert( uint8_t( parseHex( "01" ) ) == uint8_t(1) );
//...
assert( uint8_t( parseHex( "ff" ) ) == uint8_t(255) );

      

In addition to Steven's answer, I just want to point out the existence of an algorithm transform

that can further simplify your code.

for( int j = 0 ; j < v.size() ; j++ ){
  tgt_mac[j] = parseHex(v.at(j)); 
}

      



Writes to one line:

std::transform( v.begin(), v.end(), tgt_mac, &parseHex );

      

(And I know this is unrelated to the question ...)

(see codepad.org for how it looks)

+2


source


Your problem may be in the results of the analyzed data. The <operator makes decisions about how to display data based on the datatype passed to it, and uint8_t can be interpreted as char. Make sure you pass array values โ€‹โ€‹to int when printing, or investigate in the debugger.

Sample program:

uint8_t tgt_mac[6] = {0};
std::stringstream ss( "AA:BB:CC:DD:EE:11" );
char trash;

for ( int i = 0; i < 6; i++ )
{
    int foo;
    ss >> std::hex >> foo >> trash;
    tgt_mac[i] = foo;
    std::cout << std::hex << "Reading: " << foo << std::endl;
}

std::cout << "As int array: " << std::hex
    << (int) tgt_mac[0]
    << ":"
    << (int) tgt_mac[1]
    << ":"
    << (int) tgt_mac[2]
    << ":"
    << (int) tgt_mac[3]
    << ":"
    << (int) tgt_mac[4]
    << ":"
    << (int) tgt_mac[5]
    << std::endl;
std::cout << "As unint8_t array: " << std::hex
    << tgt_mac[0]
    << ":"
    << tgt_mac[1]
    << ":"
    << tgt_mac[2]
    << ":"
    << tgt_mac[3]
    << ":"
    << tgt_mac[4]
    << ":"
    << tgt_mac[5]
    << std::endl;

      

Gives the following result (cygwin g ++)

Reading: aa
Reading: bb
Reading: cc
Reading: dd
Reading: ee
Reading: 11
As int array: aa:bb:cc:dd:ee:11
As unint8_t array: ยช:ยป:I:Y:รฎ:โ—„

      

+1


source


I think you are using std :: hex in the wrong place:

#include <sstream>
#include <iostream>

int main()
{
    std::string     h("a5");
    std::stringstream   s(h);
    int x;

    s >> std::hex >> x;
    std::cout << "X(" << x << ")\n";
}

      

0


source







All Articles