2012-02-09 47 views
2

我正在使用C语言编程一个MCU,我需要解析一个以空字符结尾的字符串,其中包含一个IP地址为4个单字节。我用C++做了一个例子:解析4个单字节的IP地址字符串

#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; 
} 

该代码在新行中打印192,168,0和1每个字节。现在我需要在单个字符中的每个字节,如字节1,字节2,字节3和字节4,其中字节1包含1和字节4包含192 ...或在一个结构IP_ADDR并返回该结构然后,但我不知道如何做到这一点C. :(

+2

此代码不能打印“字节”与值'192' ...提供更严格的版本:它打印字符... 3 '1'' 9''''的字符... – pmg 2012-02-09 13:24:08

+0

噢......刚刚意识到用户提出的问题。通过查看cout的代码,我认为他只是想打印它们。他实际上想要的字节 – Lefteris 2012-02-09 13:33:19

+0

明确地在字符串末尾添加\ 0非常奇怪。通过初始化char * a =“foo \ 0”,可以创建一个包含5个字符的字符串文本,最后有两个字节。 – 2012-02-09 13:44:33

回答

4

您可以逐个字符地完成它,就像问题中的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; 
} 
+0

这个也适用,tyvm!花了我一段时间,直到我想到这个'* = 10'和'+ = * str - '0''是怎么做到的! :P – BETSCH 2012-02-13 10:48:47

+0

初始化('unsigned char value [4] = {0};')**重要**。不要忘记它。 – pmg 2012-02-13 11:04:47

+1

此代码在某些格式不正确的字符串上会失败:“aaaaaaaaa”,“999999999”,“999.99999.500AAABBBCCCDDEE.399”等... – pavelkolodin 2014-07-11 09:56:39

2
for(int i = 0, r = 0; i < 4; str += r + 1, i++) { 
    sscanf(str, "%d%n", &b[i], &r); 
} 

sscanf(str, "%d.%d.%d.%d", b, b + 1, b + 2, b + 3); 
+0

tyvm,像一个魅力:)编辑:哦,等等,我的pic18没有这个功能:( – BETSCH 2012-02-09 13:41:52

+0

为什么你不看到C标准库的string.h头内的哪个函数是由pic支持的微控制器你先工作,然后告诉我们? sscanf和strtok(分别为perreal和我的答案)都是c标准库函数。我们必须知道它有多少可用于你 – Lefteris 2012-02-09 13:49:11

+0

Theres the library:[link]( http://kevin.org/frc/C18_libraries.pdf)抱歉,我是新来的stackoverflow,认为是因为我用pic18和c18标记了它们,你们知道这个lib,但后来我意识到我也用C标记了它 – BETSCH 2012-02-09 14:02:32

1

一个很好的方式在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; 
} 
+0

这个工作如果我评论'= malloc(10);'那么只有'char * buff;'仍然存在。如果我不发表评论,我会得到一个错误,“从void *到char *的无效转换”,tyvm – BETSCH 2012-02-13 10:47:04

+0

它不会按照您认为的方式工作。弄乱未分配的指针是错误的。 如果你得到这个错误,这意味着你正在编译C++代码而不是C代码。一定要 1)或者更正编译器的标志 2)如果它是C++,你只需要将行改为:char * buff =(char *)malloc(10); – Lefteris 2012-02-13 10:56:38

1

我想解析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; 
    } 
}