Convert IP or MAC address from string to byte array (Arduino or C)
Solution 1
If you are trying to get from a string like "100.150.200.250"
to a byte array like { 100, 150, 200, 250 }
, you need to extract the string representation for each number and convert (parse) them into a binary representation before storing them in the byte array.
The way you are trying to do this, you are just converting the first four bytes from the string, i.e. "100."
, to the binary representation of each character, which turns out to be { 49, 48, 48, 0 }
. You can look that up in an ASCII table.
Also remember that, as you are storing this on a byte array, it will only support values from 0 to 255.
As you are programming on small microcontroller, I would advise against using the String
class. You might run into trouble when your programs get bigger and you start using lots of strings. Try to learn how to use character arrays instead and you will avoid running into memory issues. Remember the Arduino has just 2KB of RAM!
Here is a function you can use to make that conversion using the strtoul()
function:
void parseBytes(const char* str, char sep, byte* bytes, int maxBytes, int base) {
for (int i = 0; i < maxBytes; i++) {
bytes[i] = strtoul(str, NULL, base); // Convert byte
str = strchr(str, sep); // Find next separator
if (str == NULL || *str == '\0') {
break; // No more separators, exit
}
str++; // Point to next character after separator
}
}
You can then call it like this to convert an IP address (base 10):
const char* ipStr = "50.100.150.200";
byte ip[4];
parseBytes(ipStr, '.', ip, 4, 10);
Or like this to convert a MAC address (base 16):
const char* macStr = "90-A2-AF-DA-14-11";
byte mac[6];
parseBytes(macStr, '-', mac, 6, 16);
Solution 2
You could also use sscanf
, and by the way detect invalid inputs using its return value:
byte ip[4];
if (sscanf(mString.c_str(), "%hhu.%hhu.%hhu.%hhu", ip, ip+1, ip+2, ip+3) != 4) {
Serial.print("invalid IP: ");
Serial.println(mString);
}
However, sscanf
may not be implemented in the library for all boards, for example on esp8266 it's yet to be released in version 2.4.0.
Also, the %hhu
specifier for unsigned char
may be not supported in some versions, but you can use %u
, read it to an unsigned long
and check if the value isn't greater than 255.
Related videos on Youtube
Davide
Updated on September 16, 2022Comments
-
Davide over 1 year
I would convert myString "100.200.300.400" to byte array [4]. I'm a "bit" confused, this is right or need i to use a foreach for reading a single number?
String myString = "100.200.300.400"; byte myByteArray[4]; myString.getBytes(myByteArray,4);
Finally I want to print to the array to serial. This should be right.
for (i=0; i<4; i++) { Serial.print(myByteArray[i]); Serial.print("."); //delimiter }
Were I am going wrong? I got 49,48,48,0 !
-
Eugene Sh. about 8 years49 is the Ascii for the character "1", 48 is for "0" and so on. So you are getting what would be expected.
-
David Hoelzer about 8 yearsIf you're trying to convert that to a byte array, it sounds like you just want the numbers. The problem is that you have two numbers greater than 255 and you can't store a number that large into a single byte.
-
Eugene Sh. about 8 yearsYou need to parse this string. Look at
atoi
function. And the Arduino'sString
object has some useful methods: arduino.cc/en/Reference/StringObject
-
-
Davide about 8 yearsif i have a MAC Address like "90-A2-AF-DA-14-11" could i use the same function? I think not because i don't need the byte conversion (MAC address il already hexadecimal). Wrong?
-
Luis Chavier about 8 years@Davide I changed the function a bit to handle different number bases and added an example with a MAC address.