#include <stdio.h>
#include <string.h>
#include <math.h> //ipv4地址转换
int ipv4_to_i(const char *ip, unsigned int *ipv4_addr)
{
char str_ip_index[] = {'\0'};
unsigned int ip_int, ip_add = ;
unsigned int j = , a = , i = ; for(i = ; i <= strlen(ip); i++) {
if (ip[i] == '\0' || ip[i] == '.') {
ip_int = atoi(str_ip_index);
if (ip_int > )
return ; ip_add += (ip_int * pow(, a));
a--;
memset(str_ip_index, , sizeof(str_ip_index)); j = ;
continue;
} str_ip_index[j] = ip[i];
j++;
} *ipv4_addr = ip_add; return ;
} /* ipv6 无符号整型数组转化为字符串 */
void ipv6_to_str(char *addr_str, unsigned int ipv6_addr[])
{
/* ipv6地址128位,数组ip维数默认为4 */
/* 输出格式为: A:B:C:D:E:F:G:H. */
int i;
unsigned short msw, lsw;
char *addr_str_end_ptr; addr_str[] = '\0';
addr_str_end_ptr = addr_str;
for (i = ; i < ; i++)
{
msw = ipv6_addr[i] >> ;
lsw = ipv6_addr[i] & 0x0000ffff;
addr_str_end_ptr += sprintf(addr_str_end_ptr, "%X:%X:", msw, lsw);
}
*(addr_str_end_ptr - ) = '\0';
} char * string_white_space_trim(char *str)
{
/* 移除字符串中空格 */
int index;
int new_index;
int str_length; str_length = strlen(str); for (index = , new_index = ; index < str_length; index++)
{
if (!isspace((unsigned char)str[index]))
{
str[new_index] = str[index];
new_index++;
}
} str[new_index] = '\0'; return str;
} int string_char_count(const char *string, char character)
{
/* 计算字符串中,给定字符的数量 */
int i;
int str_length;
int count = ; str_length = strlen(string);
for (i = ; i < str_length; i++)
if (string[i] == character)
count++; return count;
} int ipv6_address_field_type_get(const char * field_str)
{
/* 判断ipv6地址域类型 */
int i = ;
int length;
int type;
unsigned int ipv4_addr; /* 通过长度判断 */
/* 16进制数字域: 1-4 */
/* "::"域:0 */
/* ipv4地址域: 7-15 */ length = strlen(field_str); if ( == length)
{
type = ;
}
else if (length <= )
{
// 确保每个数字为16进制
for (i = ; i < length; i++)
if (!isxdigit((unsigned char)field_str[i]))
return -;
type = ;
}
else if((length >= ) && (length <= ))
{
//确保是有效的ipv4地址
if (ipv4_to_i(field_str, &ipv4_addr))
type = ;
else
type = -;
}
else
{
type = -;
} return type;
} int ipv6_to_i(const char *addr_str, int length, unsigned int ipv6_addr_ptr[])
{
/***************************************************************************/
/* 功能:解析ipv6地址字符串,转换为无符号整形,存入4个无符号整形的一维数组 */
/* ipv6地址 128位,prefix length: */
/* - 64 for EUI-64 addresses */
/* - 128 for non-EUI-64 addresses */
/* 输入:ipv6地址字符串,地址位数,默认为128位 */
/* 输出:返回解析成功或失败;指向4个无符号整形的一维数组的指针 */
/****************************************************************************/ char addr_str_copy[];
int i, num_fields;
//unsigned int *ret_addr_ptr;
unsigned short int addr_field_arr[];
int addr_index;
char *ith_field; // 指向地址当前域
int ith_field_type; // 地址域类型
char *next_field;
int double_colon_field_index = -; // 字符串地址中"::"的位置
unsigned int ipv4_address; // ipv6地址中的ipv4部分
unsigned int msw, lsw;
int error = ; //复制一份,以便操作
strcpy(addr_str_copy, addr_str); // 移除字符串中的空格字符
string_white_space_trim(addr_str_copy); /* IPv6地址可能几种格式: */
/* 1) 2006:DB8:2A0:2F3B:34:E35:45:1 用16进制表示每个域的值(16位) */
/* 2) 2006:DB8::E34:1 , "::" 代表0,且只能出现一次 */
/* 3) 2002:9D36:1:2:0:5EFE:192.168.12.9 带有ipv4地址 */ // 计算字符串中冒号,字符串中地址域数比冒号多一个
num_fields = string_char_count(addr_str_copy, ':') + ; // 域最大数量为length/16 + 2
// 如 ::0:0:0:0:0:0:0:0.
if (num_fields > ((length >> ) + ))
{
ipv6_addr_ptr = NULL;
return ;
} // 初始化
ith_field = addr_str_copy; for (i = , addr_index = ; i < num_fields; i++)
{
// 获得下一个域的指针
next_field = strchr(ith_field, ':'); /* 若当前是最后一个域, next_field 是 NULL */
/* 否则,替换':'为'\0', 字符串可以结束,从而ith_field指向当前域 */
/* next_field指向下一个域头部 */
if (NULL != next_field)
{
*next_field = '\0';
++next_field;
} // 发现这个域的类型
ith_field_type = ipv6_address_field_type_get(ith_field); switch (ith_field_type)
{
case :
// 域类型为16进制表示 if (addr_index >= (length >> ))
{
error = ;
break;
}
// 字符串转换为16进制
addr_field_arr[addr_index] = (unsigned short)strtoul(ith_field, NULL, );
++addr_index;
break; case :
// 域类型为 "::" // 若出现在字符串的开头或结尾,忽略
if (( == i) || (i == num_fields - ))
{
break;
} // 若出现大于一次,错误
if (double_colon_field_index != -)
{
error = ;
break;
} // 记下位置
double_colon_field_index = addr_index; break; case :
// 域类型为ipv4地址 // 确保在地址中还有两个未设置的域
if (addr_index >= )
{
error = ;
break;
} // ipv4地址解析
ipv4_to_i(ith_field, &ipv4_address); // 存储高16位
addr_field_arr[addr_index] = (unsigned short)(ipv4_address >> ); // 存储低16位
addr_field_arr[addr_index + ] = (unsigned short)(ipv4_address & 0x0000ffff); addr_index += ; break;
default:
error = ;
break;
} if (error)
{
ipv6_addr_ptr = NULL;
return ;
} ith_field = next_field;
} // 计算的域不是8,并且没有"::",错误
if ((addr_index != (length >> )) && (- == double_colon_field_index))
{
ipv6_addr_ptr = NULL;
return ;
} if ((addr_index != (length >> )) && (- != double_colon_field_index))
{
// 设置相应"::"对应addr_field_arr中位置为0
memmove(addr_field_arr + (double_colon_field_index + (length >> ) - addr_index),
addr_field_arr + double_colon_field_index, (addr_index - double_colon_field_index) * );
memset(addr_field_arr + double_colon_field_index, , ((length >> ) - addr_index) * );
} for (i = ; i < ; i++)
{
msw = addr_field_arr[ * i];
lsw = addr_field_arr[ * i + ]; (ipv6_addr_ptr)[i] = (msw << | lsw);
} return ;
} int main(void)
{
char addr[] = {""};
unsigned int ip_v4 = ;
unsigned int ipv6[] = {, , , };
unsigned int ipv61[] = {, , , }; char *ipv6_str1 = "1:2:3:4:5:6:7:8";
char *ipv6_str2 = "1:2:3:4:5:6:7:8::";
char *ipv6_str3 = "::1:2:3:4:5:6:7:8";
char *ipv6_str4 = "1:2:3:4:5:6:192.168.1.100";
char *ipv6_str5 = "1:2::5:6:7:8";
char *ipv6_str6 = "1::3:4:5:6:7:8";
char *ipv6_str7 = "1::4:5:6:7:8";
char *ipv6_str8 = "1::8"; unsigned int ipv6_addr[];
unsigned int ipv4_addr;
unsigned int ipv6_addr_sum = ;
int flag;
int i; ipv6_to_str(addr, ipv61);
printf("ipv6: %s\n", addr); flag = ipv4_to_i("192.168.1.100", &ipv4_addr);
if (flag)
{
printf("ipv4_addr: %u\n", ipv4_addr);
} flag = ipv6_to_i(ipv6_str1, , ipv6_addr);
if (flag)
{
for (i = ; i < ; i++)
{
printf("ipv6_addr: %u\n", ipv6_addr[i]);
ipv6_addr_sum += ipv6_addr[i];
} printf("ipv6_addr_sum: %u\n", ipv6_addr_sum);
} return ;
}

编译运行:

[root@node1 ~]# gcc ddd.c -lm
[root@node1 ~]# ./a.out
ipv6: 1:2:3:4:5:6:7:8
ipv4_addr: 3232235876
ipv6_addr: 65538
ipv6_addr: 196612
ipv6_addr: 327686
ipv6_addr: 458760
ipv6_addr_sum: 1048597

C语言 IPv6 十六进制 转 十进制的更多相关文章

  1. Go语言十六进制转十进制

    Go语言十六进制转十进制 代码Demo import ( "fmt" "strconv" "testing" ) func Test_1(t ...

  2. C语言的本质(2)——二进制、八进制、十六进制与十进制

    二进制是计算技术中广泛采用的一种数制.二进制数据是用0和1两个数码来表示的数.它的基数为2,进位规则是"逢二进一",借位规则是"借一当二",由18世纪德国数理哲 ...

  3. [No000071]C# 进制转换(二进制、十六进制、十进制互转)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  4. C# 进制转换(二进制、十六进制、十进制互转)

    原文地址:https://www.cnblogs.com/icebutterfly/p/8884023.html C# 进制转换(二进制.十六进制.十进制互转)由于二进制数在C#中无法直接表示,所以所 ...

  5. C# 进制转换(二进制、十六进制、十进制互转) 转载 https://www.cnblogs.com/icebutterfly/p/8884023.html

    C# 进制转换(二进制.十六进制.十进制互转)由于二进制数在C#中无法直接表示,所以所有二进制数都用一个字符串来表示例如: 二进制: 1010 表示为 字符串:"1010" int ...

  6. 十六进制转十进制函数_C编程

    /**************************十六进制转十进制函数**************************//*函数原型:uint htd(uint a)/*函数功能:十六进制转十 ...

  7. UTC格式转换 & 十六进制换算为十进制

    UTC格式转换成北京时间格式: /// <summary> /// UTC格式与datatime的转换 /// </summary> /// <param name=&q ...

  8. BCD码、十六进制与十进制互转

    在做嵌入式软件的设计中,常常会遇到十六进制.BCD码与十进制之间的转换,近期做M1卡的应用中,涉及了大量的十六进制.BCD码与十进制之间的转换.通过对BCD码.十六进制 权的理解,轻松的实现了他们之间 ...

  9. C 语言实例 - 二进制与十进制相互转换

    C 语言实例 - 二进制与十进制相互转换 C 语言实例 C 语言实例 二进制转与十进制相互转换. 实例 - 二进制转换为十进制 #include <stdio.h> #include &l ...

随机推荐

  1. Html使用Iframe无刷新上传文件,后台接收

    html代码:我是发送请求到teacher_center.aspx,不是到.ashx一般处理程序里,需要加 runat="server",有空我再试试发送请求到 .ashx 里 & ...

  2. oracle的分析函数over(Partition by...) 及开窗函数

        over(Partition by...) 一个超级牛皮的ORACLE特有函数. oracle的分析函数over 及开窗函数一:分析函数overOracle从8.1.6开始提供分析函数,分析函 ...

  3. url传递数据

    一.post传递数据 $ci = curl_init($url); curl_setopt($ci, CURLOPT_HEADER, 0); curl_setopt($ci, CURLOPT_RETU ...

  4. 乞丐版servlet容器第4篇

    6. NIOConnector 现在为Server添加NIOConnector,添加之前可以发现我们的代码其实是有问题的.比如现在的代码是无法让服务器支持同时监听多个端口和IP的,如同时监听 127. ...

  5. 2018.10.15 bzoj4445: [Scoi2015]小凸想跑步(半平面交)

    传送门 话说去年的省选计算几何难度跟前几年比起来根本不能做啊(虽然去年考的时候并没有学过计算几何) 这题就是推个式子然后上半平面交就做完了. 什么? 怎么推式子? 先把题目的概率转换成求出可行区域. ...

  6. hdu-2955(01背包+逆向思维+审题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2955 思路:注意p和m[i]是被抓的概率,不能直接用,要转换为逃跑的概率,然后将得到的钱视为背包体积再 ...

  7. 解决Docker时区与主机时区不一致的问题

    在Dockerfile里面增加以下红色的部分 FROM hub.chinacloud.com/common/jdk:8MAINTAINER xxx@chinacloud.com.cn RUN mkdi ...

  8. 【转】Paxos算法3-实现探讨

    ——转自:{老码农的专栏} 前两篇Paxos算法的讨论,让我们对paxos算法的理论形成过程有了大概的了解,但距离其成为一个可执行的算法程序还有很长的路要走,原因是很多的细节和错误未被考虑.Googl ...

  9. python面向对象开发的自我理解

    ​详细代码理解可以参考 笨鸟教程博客:http://www.runoob.com/python3/python3-class.html 面向对象经常被提起,那到底什么是面向对象呢? 它的基本概念:类, ...

  10. POJ3273 Monthly Expense 2017-05-11 18:02 30人阅读 评论(0) 收藏

    Monthly Expense Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 25959   Accepted: 10021 ...