2012-02-09 220 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; 
    } 
}