利用C语言将点分十进制的IP字符串转成4个整数

 更新时间:2025年01月10日 10:08:54   作者:国服卤蛋儿  
这篇文章主要为大家详细介绍了如何利用C语言实现将点分十进制的IP字符串转成4个整数,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下

最近在做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个整数的资料请关注脚本之家其它相关文章!

相关文章

  • C++实现LeetCode(38.计数和读法)

    C++实现LeetCode(38.计数和读法)

    这篇文章主要介绍了C++实现LeetCode(38.计数和读法),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C语言版三子棋游戏实现代码

    C语言版三子棋游戏实现代码

    这篇文章主要为大家详细介绍了C语言版三子棋游戏的实现代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • C++内存管理详细解析

    C++内存管理详细解析

    这篇文章主要给大家分享的是C++内存管理的详细内容学习,下面文章围绕C++内存管理的相关资料展开具体学习内容,需要的朋友可以参考一下,希望对你有所帮助
    2021-11-11
  • c/c++ 标准库 bind 函数详解

    c/c++ 标准库 bind 函数详解

    bind是一组用于函数绑定的模板。在对某个函数进行绑定时,可以指定部分参数或全部参数,也可以不指定任何参数,还可以调整各个参数间的顺序。这篇文章主要介绍了c/c++ 标准库 bind 函数 ,需要的朋友可以参考下
    2018-09-09
  • C++11运算符重载和向量类重载实例详解(<<,>>,+,-,*等)

    C++11运算符重载和向量类重载实例详解(<<,>>,+,-,*等)

    这篇文章主要给大家介绍了关于C++11运算符重载和向量类重载的相关资料,主要包括<<,>>,+,-,*等,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2021-07-07
  • C++实现LeetCode(20.验证括号)

    C++实现LeetCode(20.验证括号)

    这篇文章主要介绍了C++实现LeetCode(20.验证括号),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • 如何判断一个数是否为2的幂次方?若是,并判断出来是多少次方?

    如何判断一个数是否为2的幂次方?若是,并判断出来是多少次方?

    本篇文章是对如何判断一个数是否为2的幂次方?若是,并判断出来是多少次方的实现方法,进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • 浅谈c++中的异常处理机制

    浅谈c++中的异常处理机制

    C++异常处理机制通过try/catch/throw结构处理运行时错误,本文就来介绍一下c++中的异常处理机制,具有一定的参考价值,感兴趣的可以了解一下
    2025-02-02
  • C语言实现数据结构迷宫实验

    C语言实现数据结构迷宫实验

    这篇文章主要为大家详细介绍了C语言实现数据结构迷宫实验,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-03-03
  • Microsoft Visual C++ 6.0开发环境搭建教程

    Microsoft Visual C++ 6.0开发环境搭建教程

    这篇文章主要为大家详细介绍了Microsoft Visual C++ 6.0开发环境搭建教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04

最新评论