#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. spring配置数据库连接池druid

    连接池原理 连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象.使用完毕后,用户也并非将连 ...

  2. 演示Spring框架的JDBC模板的简单操作

    1. 步骤一:创建数据库的表结构 create database spring_day03; use spring_day03; create table t_account( id int prim ...

  3. 一个方便的java分页算法

    一个好用的java分页算法,代码如下,只需要分页参数继承Pageable类就可以很方便分页了 package cn.com.base.common.pagination; /** * 分页基类 * * ...

  4. SSL - 简介

    一.密码技术 要了解SSL协议,首先要了解:加密算法.消息摘要算法(又称为哈希算法Hash),数字签名等概念.这些技术每个都可以写出一整本的书,它们结合在一起,提供了保密性.完整性和身份验证的功能. ...

  5. PAT 1074 宇宙无敌加法器(20)(代码+思路+测试点分析)

    1074 宇宙无敌加法器(20 分)提问 地球人习惯使用十进制数,并且默认一个数字的每一位都是十进制的.而在 PAT 星人开挂的世界里,每个数字的每一位都是不同进制的,这种神奇的数字称为"P ...

  6. 合成冷色黑暗恐怖魔法师图片的PS教程

    教程主要使用Photoshop合成黑暗风格的魔法师施法场景,整体的场景效果以冷色风格为主,加上素材的叠加完成最终效果图,希望朋友可以喜欢.效果图: 先把背景拖进去,用工具吧字母弄掉. 加一个调色图层 ...

  7. OAuth 2.0 学习

    OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版. 本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为R ...

  8. 如何用Mockplus快速做一个手风琴菜单?

    手风琴菜单是一种比较常用的菜单形式,利用原型工具来做这种菜单通常要用到中继器.即使是功能强大的Axure,想实现该效果也比较麻烦.但如果你对Mockplus有所了解,你一定知道,利用Mockplus的 ...

  9. cmd 命令阻塞继续执行下面的命令的办法

    例如在dos下查询硬盘序列号: 首先输入:diskpart-->select disk 0--> detail disk. 如果要在java下面直接查询可以写成一个bat文件写成下面形式: ...

  10. eclipse怎样检出SVN项目

    首先确定你的eclipse安装了svn插件.查看eclipse是否安装插件的方法:打开eclipse->文件->新建->其他 ,在弹出的选择向导窗口中如果能搜索到svn,说明ecli ...