#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. popupMenu-----弹出菜单

    import android.os.Bundle; import android.app.Activity; import android.graphics.Color; import android ...

  2. dede自定义标签

    在dede安装目录下的include/taglib下创建标签文件,比如mytest.lib.php.(必须以.lib.php为后缀) <?php if(!defined('DEDEINC')) ...

  3. Asia Stock Exchanges[z]

    Asia Stock Exchanges July 7, 2009 This article is to summarise the trading rules of some Asia stocke ...

  4. geoserver 的缓存技术

    geoserver提到的缓存工具共有两个:tilecache和geowebcache.geowebcache是java写的,整合进geoserer中. tilecache则是python写的一个小程序 ...

  5. mysql水平分区

    解决问题:单表数据量过大 ALTER TABLE boc_url_log PARTITION BY RANGE (ulid) ( PARTITION log_1 VALUES LESS THAN () ...

  6. apache的错误日志分析

  7. Laravel图表扩展包推荐:Charts

     2016年11月15日 ·  2283次 ·  4条 ·  laravel,package,charts 介绍 在项目开发中,创建图表通常是一件痛苦的事情.因为你必须将数据转换为图表库支持的格式传输 ...

  8. tomcat6.0 配置不同端口访问不同项目

    <?xml version='1.0' encoding='utf-8'?> <!-- Licensed to the Apache Software Foundation (ASF ...

  9. Devexpress VCL Build v2014 vol 14.2.5 发布

    和xe8 几乎同一天出来,但是目前官方不支持xe8. The following sections list all minor and major changes in DevExpress VCL ...

  10. Nginx安装SSL安全证书

    1. 在Nginx的安装目录下的config目录下创建cert目录,并且将下载的证书全部文件拷贝到cert目录中.如果申请证书时是自己创建的CSR文件,请将对应的私钥文件放到cert目录下并且命名为2 ...