最近在做lldp的snmp返回值时需要做这样的转换处理:C语言将点分十进制的IP字符串转成4个整数。
这里用两种方式:
1.sscanf格式化处理
2.用 inet_aton函数将ip字符串转成32位的整形,然后再根据bit转成对应的4个整数。
man命令可以确认下sscanf和inet_aton的返回值,以确认处理成功还是失败。
字节序问题:inet_aton后统一用网络字节序,避免出错。
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"; // 定义变量存储解析结果 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"; // 定义变量存储解析结果 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; }
哪个效率高点?
这里用的是固定的字符串跑的测试,不太严谨。。。可以考虑随机生成1~255的数字组成ip字符串,然后再跑下测试。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <time.h> #define TEST_COUNT 1000000 // 测试次数 // 使用 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"; // 定义变量存储解析结果 int a, b, c, d; // 记录失败的次数 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 方式失败次数: %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 方式失败次数: %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 方式失败次数: 0 inet_aton 方式耗时: 0.027499 秒 inet_aton 方式失败次数: 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 // 测试次数 // 生成一个随机的合法 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() { // 初始化随机数种子 srand(time(NULL)); // 定义变量存储解析结果 int a, b, c, d; // 记录失败的次数 int sscanf_fail_count = 0; int inet_aton_fail_count = 0; // 动态分配堆空间存储 IP 地址数组 char (*ip_array)[16] = malloc(TEST_COUNT * sizeof(*ip_array)); if (ip_array == NULL) { printf("内存分配失败!\n"); return 1; } // 随机生成 IP 地址数组 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 方式失败次数: %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 方式失败次数: %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 方式失败次数: 0 inet_aton 方式耗时: 0.043936 秒 inet_aton 方式失败次数: 0 inet_aton 方式更快,效率高出 2.65 倍 */
以上就是利用C语言将点分十进制的IP字符串转成4个整数的详细内容,更多关于C语言IP字符串转成4个整数的资料请关注脚本之家其它相关文章!
来源链接:https://www.jb51.net/program/3340072e3.htm
© 版权声明
本站所有资源来自于网络,仅供学习与参考,请勿用于商业用途,否则产生的一切后果将由您(转载者)自己承担!
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
THE END
暂无评论内容