I'm programming on a MCU with C and I need to parse a null-terminated string which contains an IP address into 4 single bytes. I made an example with C++:
#include <iostream>
int main()
{
char *str = "192.168.0.1\0";
while (*str != '\0')
{
if (*str == '.')
{
*str++;
std::cout << std::endl;
}
std::cout << *str;
*str++;
}
std::cout << std::endl;
return 0;
}
This code prints 192, 168, 0 and 1 each byte in a new line. Now I need each byte in a single char, like char byte1, byte2, byte3 and byte4 where byte1 contains 1 and byte4 contains 192... or in a struct IP_ADDR and return that struct then, but I dont know how to do it in C. :(
You can do it character-by-character, as does the C++ version in your question.
/* ERROR CHECKING MISSING */
#include <ctype.h>
#include <stdio.h>
int main(void) {
char *str = "192.168.0.1", *str2;
unsigned char value[4] = {0};
size_t index = 0;
str2 = str; /* save the pointer */
while (*str) {
if (isdigit((unsigned char)*str)) {
value[index] *= 10;
value[index] += *str - '0';
} else {
index++;
}
str++;
}
printf("values in \"%s\": %d %d %d %d\n", str2,
value[0], value[1], value[2], value[3]);
return 0;
}
for(int i = 0, r = 0; i < 4; str += r + 1, i++) {
sscanf(str, "%d%n", &b[i], &r);
}
or
sscanf(str, "%d.%d.%d.%d", b, b + 1, b + 2, b + 3);
a nice way to do this in C is to use the string tokenizer. In the example code below the bytes are saved in the bytes array and are also printed with the printf function. Hope it helps
#include <string.h>
int main()
{
char str[] = "192.168.0.1";
unsigned char bytes[4];
int i = 0;
char* buff = malloc(10);
buff = strtok(str,".");
while (buff != NULL)
{
//if you want to print its value
printf("%s\n",buff);
//and also if you want to save each byte
bytes[i] = (unsigned char)atoi(buff);
buff = strtok(NULL,".");
i++;
}
free(buff);
return 0;
}
I'd like to provide more strict version for parsing ipv4 address
typedef struct ipv4_type {
uint8_t data[4];
} ipv4;
ipv4_error ipv4_parse ( const uint8_t * string, uint8_t string_length, ipv4 * result )
{
bool at_least_one_symbol = false;
uint8_t symbol, string_index = 0, result_index = 0;
uint16_t data = 0;
while ( string_index < string_length ) {
symbol = string[string_index];
if ( isdigit ( symbol ) != 0 ) {
symbol -= '0';
data = data * 10 + symbol;
if ( data > UINT8_MAX ) {
// 127.0.0.256
return ERROR_IPV4_DATA_OVERFLOW;
}
at_least_one_symbol = true;
} else if ( symbol == '.' ) {
if ( result_index < 3 ) {
if ( at_least_one_symbol ) {
result->data[result_index] = data;
data = 0;
result_index ++;
at_least_one_symbol = false;
} else {
// 127.0..1
return ERROR_IPV4_NO_SYMBOL;
}
} else {
// 127.0.0.1.2
return ERROR_IPV4_INPUT_OVERFLOW;
}
} else {
// 127.*
return ERROR_IPV4_INVALID_SYMBOL;
}
string_index ++;
}
if ( result_index == 3 ) {
if ( at_least_one_symbol ) {
result->data[result_index] = data;
return 0;
} else {
// 127.0.0.
return ERROR_IPV4_NOT_ENOUGH_INPUT;
}
} else {
// result_index will be always less than 3
// 127.0
return ERROR_IPV4_NOT_ENOUGH_INPUT;
}
}
来源:https://stackoverflow.com/questions/9211601/parsing-ip-adress-string-in-4-single-bytes