'Converting an uint8_t[] to an IP address string [duplicate]
I am currently learning C. My ecosystem consists of an Espressif ESP-32 micro controller and Eclipse CDT IDE.
I am trying to convert an uint8_t[]
to a human readable IPv4 address string
. I came up with the following code so far:
void app_main() {
uint8_t[] ip = {192, 168, 0, 99};
dump_ip(ip);
}
void dump_ip(const uint8_t *in) {
// ip addresses consist of three dots + terminator '\0'
int size = 4;
// count amount of chars needed for specific ip address
for(int i=0; i<4; i++) {
if(in[i]==0) {
size ++;
} else {
size += ((int)log10(in[i]))+1;
}
}
// allocate memory on heap for an ip address of length 'size'
char *ip_str = (char*)malloc(size*sizeof(char));
// copy ip address parts to char array
int pos = 0;
for(int i=0; i<4; i++) {
if(in[i]==0) {
ip_str[pos] = '0';
pos++;
} else {
char b[4];
itoa(in[i], b, 10);
for(int j=0; j<3; j++) {
if(b[j]!='0') {
ip_str[pos] = b[j];
pos++;
}
}
}
// add dot between ip address parts
if(i<3) {
ip_str[pos] = '.';
pos++;
}
}
// add terminator at end of string
ip_str[pos] = '\0';
// print to uart interface
uart_send(ip_str);
// release allocated heap memory
free(ip_str);
}
I get the following results when testing with different IP arrays:
uint8_t[] ip = {192, 168, 0, 99}; => "192.168.0.99" => OK
uint8_t[] ip = {192, 168, 1, 99}; => "192.168.1" => FAILED
uint8_t[] ip = {192, 168, 10, 99}; => "192.168.1" => FAILED
uint8_t[] ip = {10, 10, 10, 10}; => "1" => FAILED
// etc. etc. etc.
What am I doing wrong? Is there some more elegant way to accomplish this?
Solution 1:[1]
Just snprintf
it.
void app_main() {
uint8_t ip[] = {192, 168, 0, 99};
char buf[3 * 4 + 3 * 1 + 1];
snprintf(buf, sizeof(buf), "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
uart_send(buf);
}
uint8_t[] ip
is not valid C, the []
comes after the variable name.
- The
sprintf
andsnprintf
will print the formatted string into the memory pointed to by the first arg. - The
snprintf
takes additional maximum size argument as the second arg. - The
uint8_t
variables are auto-casted toint
when passing in variable arguments list - thus you can print them using%d
printf modifier. - Then you have human readable, null terminated string.
Solution 2:[2]
The best answer is simply to use snprintf
as suggested by Kamil Cuk.
However if you're still wondering why your code didn't work, the answer is on this line:
if(b[j]!='0') {
you are only copying characters that aren't zero, which includes null chars. So when a segment of the IP contains less than 3 characters you will be copying a null into the string. The fix is very simple:
if(b[j]!='\0') {
which makes me think it may well have just been a typo!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | ach |
Solution 2 | lxop |