C 解析4个单字节的ip地址字符串

C 解析4个单字节的ip地址字符串,c,parsing,pic18,c18,C,Parsing,Pic18,C18,我正在用C在MCU上编程,我需要将包含IP地址的空终止字符串解析为4个字节。我用C++做了一个例子: #include <iostream> int main() { char *str = "192.168.0.1\0"; while (*str != '\0') { if (*str == '.') { *str++; std::

我正在用C在MCU上编程,我需要将包含IP地址的空终止字符串解析为4个字节。我用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;
}
#包括
int main()
{
char*str=“192.168.0.1\0”;
而(*str!='\0')
{
如果(*str=='。)
{
*str++;

std::cout在C中实现这一点的一个好方法是使用字符串标记器。在下面的示例代码中,字节保存在字节数组中,并且也使用printf函数打印。希望对您有所帮助

#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;
}
#包括
int main()
{
字符str[]=“192.168.0.1”;
无符号字符字节[4];
int i=0;
char*buff=malloc(10);
buff=strtok(str,“.”);
while(buff!=NULL)
{
//如果要打印其值
printf(“%s\n”,浅黄色);
//如果你想保存每个字节
字节[i]=(无符号字符)atoi(buff);
buff=strtok(空,“.”);
i++;
}
免费(buff);
返回0;
}

<代码> > p>你可以按字符来做,就像你的问题中的C++版本一样。

/* 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;
}
/*缺少错误检查*/
#包括
#包括
内部主(空){
char*str=“192.168.0.1”,*str2;
无符号字符值[4]={0};
尺寸指数=0;
str2=str;/*保存指针*/
while(*str){
if(isdigit((无符号字符)*str)){
数值[指数]*=10;
值[索引]+=*str-'0';
}否则{
索引++;
}
str++;
}
printf(“在\%s\”中的值:%d%d%d\n”,str2,
值[0]、值[1]、值[2]、值[3]);
返回0;
}

我想为解析ipv4地址提供更严格的版本

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;
    }
}
typedef结构ipv4\u类型{
uint8_t数据[4];
}ipv4;
ipv4\u错误ipv4\u解析(常量uint8\u t*字符串、uint8\u t字符串长度、ipv4*结果)
{
bool至少一个符号=false;
uint8\u t符号,字符串索引=0,结果索引=0;
uint16_t数据=0;
while(字符串索引<字符串长度){
符号=字符串[字符串索引];
如果(isdigit(符号)!=0){
符号-='0';
数据=数据*10+符号;
如果(数据>UINT8_最大值){
// 127.0.0.256
返回错误\u IPV4\u数据\u溢出;
}
至少有一个符号=真;
}else if(符号='。){
如果(结果_指数<3){
如果(至少一个符号){
结果->数据[结果索引]=数据;
数据=0;
结果_指数++;
至少有一个符号=false;
}否则{
// 127.0..1
返回错误\u IPV4\u无\u符号;
}
}否则{
// 127.0.0.1.2
返回错误\u IPV4\u输入\u溢出;
}
}否则{
// 127.*
返回错误\u IPV4\u无效\u符号;
}
string_index++;
}
如果(结果_索引==3){
如果(至少一个符号){
结果->数据[结果索引]=数据;
返回0;
}否则{
// 127.0.0.
返回错误\u IPV4\u输入不足\u;
}
}否则{
//结果_索引将始终小于3
// 127.0
返回错误\u IPV4\u输入不足\u;
}
}

此代码不打印“字节”使用值
192
..:它打印字符…3个字符代表
1
9
2
…哦…刚刚实现了用户的要求。通过使用couts查看代码,我以为他只想打印字符。他实际上希望字节在字符串文本的末尾显式添加\0非常奇怪。通过初始化char*a=“foo\0”,您可以创建一个包含5个字符的字符串文字,其结尾有两个nul字节。tyvm的工作原理类似于一个符咒:)编辑:哦,等等,我的pic18也没有这个功能:(为什么你看不到你首先使用的pic微控制器支持C标准库的string.h头中的哪一个函数,然后告诉我们?sscanf和strtok(分别是perreal和my answer)是c标准库函数。我们必须知道有多少是可供您使用的。这是库:对不起,我是stackoverflow新手,因为我用pic18和c18标记了它。你们知道库,但后来我意识到我也用链接pdf的Cpage 131标记了它。strtokpgm、strtokpgmram、strtokrampgm都受支持。所以我的答案可以使用。你检查过了吗?(这是第三个)sscanf已知速度慢,在某些实现中甚至有bug。你应该避免使用它。如果我注释
=malloc(10);
则此选项有效,因此只剩下
char*buff;
了。如果我不注释,我会得到一个错误,“从void*到char*的转换无效”TyVMIT不按你的想法工作。如果你弄错了,它是错误的。如果你得到这个错误,那就是编译C++代码而不是C代码。确保1)要么改正编译器的标志2)如果它是C++,你只需要把它改为:char *buff =(char)Maloc(10)。;不,它的工作方式与您想象的不同。您正在使用malloc分配一个10字节的缓冲区。在下一行中,您将buff指向另一个位置。您分配的10字节缓冲区已丢失。C中没有垃圾收集。(在这个小程序中,这可能无关紧要,但在基于它的函数中,在一个程序中多次调用……)然后,在程序结束时,你试图释放-什么???当buff==NULL时你到达那里!这个也可以,tyvm!我花了一段时间,直到我明白了这个
*=10
+=*str-'0'
是如何做到的!:p初始化(
无符号字符值[4]={0};
)是很重要的。别忘了。此代码在某些格式错误的字符串上会失败:“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa。。。
/* 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;
}
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;
    }
}