利用C語言將點分十進制的IP字符串轉(zhuǎn)成4個整數(shù)
最近在做lldp的snmp返回值時需要做這樣的轉(zhuǎn)換處理:C語言將點分十進制的IP字符串轉(zhuǎn)成4個整數(shù)。
這里用兩種方式:
1.sscanf格式化處理
2.用 inet_aton函數(shù)將ip字符串轉(zhuǎn)成32位的整形,然后再根據(jù)bit轉(zhuǎn)成對應(yīng)的4個整數(shù)。
man命令可以確認(rèn)下sscanf和inet_aton的返回值,以確認(rèn)處理成功還是失敗。
字節(jié)序問題:inet_aton后統(tǒng)一用網(wǎng)絡(luò)字節(jié)序,避免出錯。
sscanf
#include <stdio.h> // 1 succeed, 0 failed int parse_ip_sscanf(const char *ip_str, int *a, int *b, int *c, int *d) { return sscanf(ip_str, "%d.%d.%d.%d", a, b, c, d) == 4; } int main() { // 定義點分十進制的 IP 字符串 const char *ip_str = "192.168.1.1"; // 定義變量存儲解析結(jié)果 int a, b, c, d; if (0 == parse_ip_sscanf(ip_str, &a, &b, &c, &d)) { printf("parse_ip_sscanf failed\n"); } else { printf("parse done: %d %d %d %d\n", a, b, c, d); } return 0; }
inet_aton + ntol
#include <stdio.h> #include <arpa/inet.h> #define u8 unsigned char // 1 succeed, 0 failed int parse_ip_inet_aton(const char *ip_str, int *a, int *b, int *c, int *d) { u8 *p = NULL; in_addr_t ip_int; if (inet_aton(ip_str, (struct in_addr *)&ip_int) == 0) { return 0; // 解析失敗 } p = (u8 *)&ip_int; *a = p[0]; *b = p[1]; *c = p[2]; *d = p[3]; return 1; // 解析成功 } int main() { // 定義點分十進制的 IP 字符串 const char *ip_str = "192.168.1.1"; // 定義變量存儲解析結(jié)果 int a, b, c, d; if (0 == parse_ip_inet_aton(ip_str, &a, &b, &c, &d)) { printf("parse_ip_sscanf failed\n"); } else { printf("parse done: %d %d %d %d\n", a, b, c, d); } return 0; }
哪個效率高點?
這里用的是固定的字符串跑的測試,不太嚴(yán)謹(jǐn)。。??梢钥紤]隨機生成1~255的數(shù)字組成ip字符串,然后再跑下測試。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <time.h> #define TEST_COUNT 1000000 // 測試次數(shù) // 使用 sscanf 解析 IP 地址 int parse_ip_sscanf(const char *ip_str, int *a, int *b, int *c, int *d) { return sscanf(ip_str, "%d.%d.%d.%d", a, b, c, d) == 4; } // 使用 inet_aton 解析 IP 地址 int parse_ip_inet_aton(const char *ip_str, int *a, int *b, int *c, int *d) { in_addr_t ip_int; if (inet_aton(ip_str, (struct in_addr *)&ip_int) == 0) { return 0; // 解析失敗 } ip_int = ntohl(ip_int); *a = (ip_int >> 24) & 0xFF; *b = (ip_int >> 16) & 0xFF; *c = (ip_int >> 8) & 0xFF; *d = ip_int & 0xFF; return 1; // 解析成功 } int main() { // 定義點分十進制的 IP 字符串 const char *ip_str = "192.168.1.1"; // 定義變量存儲解析結(jié)果 int a, b, c, d; // 記錄失敗的次數(shù) int sscanf_fail_count = 0; int inet_aton_fail_count = 0; // 測試 sscanf 方式 clock_t start = clock(); for (int i = 0; i < TEST_COUNT; i++) { if (0 == parse_ip_sscanf(ip_str, &a, &b, &c, &d)) { sscanf_fail_count++; } } clock_t end = clock(); double sscanf_time = (double)(end - start) / CLOCKS_PER_SEC; printf("sscanf 方式耗時: %.6f 秒\n", sscanf_time); printf("sscanf 方式失敗次數(shù): %d\n", sscanf_fail_count); // 測試 inet_aton 方式 start = clock(); for (int i = 0; i < TEST_COUNT; i++) { if (0 == parse_ip_inet_aton(ip_str, &a, &b, &c, &d)) { inet_aton_fail_count++; } } end = clock(); double inet_aton_time = (double)(end - start) / CLOCKS_PER_SEC; printf("inet_aton 方式耗時: %.6f 秒\n", inet_aton_time); printf("inet_aton 方式失敗次數(shù): %d\n", inet_aton_fail_count); // 比較兩種方式的效率 if (sscanf_time < inet_aton_time) { printf("sscanf 方式更快,效率高出 %.2f 倍\n", inet_aton_time / sscanf_time); } else { printf("inet_aton 方式更快,效率高出 %.2f 倍\n", sscanf_time / inet_aton_time); } return 0; } /* sscanf 方式耗時: 0.104025 秒 sscanf 方式失敗次數(shù): 0 inet_aton 方式耗時: 0.027499 秒 inet_aton 方式失敗次數(shù): 0 inet_aton 方式更快,效率高出 3.78 倍 */
修改ip隨機生成一百萬次,測試:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <time.h> #define TEST_COUNT 1000000 // 測試次數(shù) // 生成一個隨機的合法 IP 地址字符串 void generate_random_ip(char *ip_str) { sprintf(ip_str, "%d.%d.%d.%d", rand() % 256, rand() % 256, rand() % 256, rand() % 256); } // 使用 sscanf 解析 IP 地址 int parse_ip_sscanf(const char *ip_str, int *a, int *b, int *c, int *d) { return sscanf(ip_str, "%d.%d.%d.%d", a, b, c, d) == 4; } // 使用 inet_aton 解析 IP 地址 int parse_ip_inet_aton(const char *ip_str, int *a, int *b, int *c, int *d) { in_addr_t ip_int; if (inet_aton(ip_str, (struct in_addr *)&ip_int) == 0) { return 0; // 解析失敗 } ip_int = ntohl(ip_int); *a = (ip_int >> 24) & 0xFF; *b = (ip_int >> 16) & 0xFF; *c = (ip_int >> 8) & 0xFF; *d = ip_int & 0xFF; return 1; // 解析成功 } int main() { // 初始化隨機數(shù)種子 srand(time(NULL)); // 定義變量存儲解析結(jié)果 int a, b, c, d; // 記錄失敗的次數(shù) int sscanf_fail_count = 0; int inet_aton_fail_count = 0; // 動態(tài)分配堆空間存儲 IP 地址數(shù)組 char (*ip_array)[16] = malloc(TEST_COUNT * sizeof(*ip_array)); if (ip_array == NULL) { printf("內(nèi)存分配失?。n"); return 1; } // 隨機生成 IP 地址數(shù)組 for (int i = 0; i < TEST_COUNT; i++) { generate_random_ip(ip_array[i]); } // 測試 sscanf 方式 clock_t start = clock(); for (int i = 0; i < TEST_COUNT; i++) { if (!parse_ip_sscanf(ip_array[i], &a, &b, &c, &d)) { sscanf_fail_count++; } } clock_t end = clock(); double sscanf_time = (double)(end - start) / CLOCKS_PER_SEC; printf("sscanf 方式耗時: %.6f 秒\n", sscanf_time); printf("sscanf 方式失敗次數(shù): %d\n", sscanf_fail_count); // 測試 inet_aton 方式 start = clock(); for (int i = 0; i < TEST_COUNT; i++) { if (!parse_ip_inet_aton(ip_array[i], &a, &b, &c, &d)) { inet_aton_fail_count++; } } end = clock(); double inet_aton_time = (double)(end - start) / CLOCKS_PER_SEC; printf("inet_aton 方式耗時: %.6f 秒\n", inet_aton_time); printf("inet_aton 方式失敗次數(shù): %d\n", inet_aton_fail_count); // 比較兩種方式的效率 if (sscanf_time < inet_aton_time) { printf("sscanf 方式更快,效率高出 %.2f 倍\n", inet_aton_time / sscanf_time); } else { printf("inet_aton 方式更快,效率高出 %.2f 倍\n", sscanf_time / inet_aton_time); } return 0; } /* sscanf 方式耗時: 0.116505 秒 sscanf 方式失敗次數(shù): 0 inet_aton 方式耗時: 0.043936 秒 inet_aton 方式失敗次數(shù): 0 inet_aton 方式更快,效率高出 2.65 倍 */
以上就是利用C語言將點分十進制的IP字符串轉(zhuǎn)成4個整數(shù)的詳細(xì)內(nèi)容,更多關(guān)于C語言IP字符串轉(zhuǎn)成4個整數(shù)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++實現(xiàn)LeetCode(38.計數(shù)和讀法)
這篇文章主要介紹了C++實現(xiàn)LeetCode(38.計數(shù)和讀法),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07c/c++ 標(biāo)準(zhǔn)庫 bind 函數(shù)詳解
bind是一組用于函數(shù)綁定的模板。在對某個函數(shù)進行綁定時,可以指定部分參數(shù)或全部參數(shù),也可以不指定任何參數(shù),還可以調(diào)整各個參數(shù)間的順序。這篇文章主要介紹了c/c++ 標(biāo)準(zhǔn)庫 bind 函數(shù) ,需要的朋友可以參考下2018-09-09C++11運算符重載和向量類重載實例詳解(<<,>>,+,-,*等)
這篇文章主要給大家介紹了關(guān)于C++11運算符重載和向量類重載的相關(guān)資料,主要包括<<,>>,+,-,*等,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-07-07如何判斷一個數(shù)是否為2的冪次方?若是,并判斷出來是多少次方?
本篇文章是對如何判斷一個數(shù)是否為2的冪次方?若是,并判斷出來是多少次方的實現(xiàn)方法,進行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05C語言實現(xiàn)數(shù)據(jù)結(jié)構(gòu)迷宮實驗
這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)數(shù)據(jù)結(jié)構(gòu)迷宮實驗,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-03-03Microsoft Visual C++ 6.0開發(fā)環(huán)境搭建教程
這篇文章主要為大家詳細(xì)介紹了Microsoft Visual C++ 6.0開發(fā)環(huán)境搭建教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04