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));
}
source to share
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]);
}
source to share
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)
source to share
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:รฎ:โ
source to share