0

I have a string (std::string) which contains a MAC address in C++, e.g.:

10:10:0F:A0:01:00

I need to convert it to an array of bytes (unsigned char*).

The bytes have to be written from left to right. Does anybody have a function or efficient algorithm for this?

6
  • 1
    haha @herohuyongtao. i don't think that's what he means... Commented Sep 26, 2014 at 6:28
  • You can use std::istringstream along with the hex I/O manipulator, and use : as delimiter, to read in the equivalent numbers into a 6 byte array. Commented Sep 26, 2014 at 6:28
  • ok, sorry, I forgot to mention that the ":"-chars should be removed:-) Commented Sep 26, 2014 at 6:31
  • Do you have a code-example for the std::isstringstream with hex I/O manipulator and : as delimiter, I think it's really waht I need but can't find an example. Commented Sep 26, 2014 at 6:33
  • I actually have an example here that shows how to skip bad input, should also work for your case. Though there are other possible solutions (e.g. std::getline() allows to specify an alternate delimiter). Commented Sep 26, 2014 at 6:47

3 Answers 3

3

Sorry for necroposting, but just to help others who may still be searching for the answer, there is a standard C way that still can be used in C++ without any reinvention of the wheel. Just man ether_aton or click here.

Sign up to request clarification or add additional context in comments.

Comments

0

This'll work. You've tagged this as C++ so I've scrupulously avoided the shorter solution that's possible using the sscanf C method. using namespace std is used here only to shorten the quoted code.

#include <iostream>
#include <sstream>

main() {

  unsigned char octets[6];
  unsigned int value;
  char ignore;

  using namespace std;

  istringstream iss("10:10:0F:A0:01:00",istringstream::in);

  iss >> hex;

  for(int i=0;i<5;i++) {
    iss >> value >> ignore;
    octets[i]=value;
  }
  iss >> value;
  octets[5]=value;

  // validate

  for(int i=0;i<sizeof(octets)/sizeof(octets[0]);i++)
    cout << hex << static_cast<unsigned int>(octets[i]) << " ";

  cout << endl;
}

Comments

0

I know that this is old, but I've got a similar routine for Bluetooth addresses. I added a regex filter to make sure the text is the correct format before I parse it.

The reverse order of bytes in this was important because it matches what's produced by the function in the Bluetooth library: int str2ba(const char *str, bdaddr_t *ba);

My new Bluetooth code talks to Bluetooth using an alternate method, but I wanted to keep the internal structure of the Bluetooth address matching.

#include <iomanip>
#include <iostream>
#include <regex>

#ifndef bdaddr_t
/* BD Address */
typedef struct {
    uint8_t b[6];
} __attribute__((packed)) bdaddr_t;
#endif // !bdaddr_t

const std::regex BluetoothAddressRegex("((([[:xdigit:]]{2}:){5}))[[:xdigit:]]{2}");

bdaddr_t string2ba(const std::string& TheBlueToothAddressString)
{ 
    bdaddr_t TheBlueToothAddress({ 0 });
    if (std::regex_match(TheBlueToothAddressString, BluetoothAddressRegex))
    {
        std::stringstream ss(TheBlueToothAddressString);
        std::string byteString;
        int index(5);
        // Because I've verified the string format with regex I can safely run this loop knowing it'll get 6 bytes
        while (std::getline(ss, byteString, ':'))
            TheBlueToothAddress.b[index--] = std::stoi(byteString, nullptr, 16);
    }
    return(TheBlueToothAddress); 
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.