题目描述:
互联网协议第六版 (IPv6) 是被设计用于替代 IPv4 的新一代互联网协议。相比 IPv4,IPv6 最大的特点是,IPv6 大幅扩大了地址空间,能够有效解决 IPv4 地址紧张的情况。
IPv6 地址由 128 位二进制数构成,这 128 位二进制数被分成 8 组,每组 16 位。用冒号 分隔法表示 IPv6 地址的方式如下:
xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
其中,xxxx 是 4 位十六进制数,代表地址中一组,其中十六进制数中的字母既可以大写 也可以小写。此外,如果某组十六进制数中有多余的前导 0,那么这些多余的前导 0 可以省 略不写。例如,以下是一个 IPv6 地址的示例:
abcd:1234:aCA9:123:4567:089:0:0000
为了进一步简化书写,有时还会采用 0 位压缩表示法,即如果有一个或多个连续的全 0 组,那么可以将这些连续的全 0 组删去,替换成两个冒号 ‘::’;如果替换的结果中含有多于两 个连续冒号,则将多余的冒号删去直至只有两个连续的冒号。需要注意的是,在同一个 IPv6 地址中,0 位压缩表示最多只能使用 1 次。例如,以下均为合法的带 0 位压缩表示的 IPv6 地 址:
7abc::00ff:fffc 表示 7abc:0:0:0:0:0:ff:fffc
FC::8976:0000:0000:0000:00ff 表示 fc:0:0:8976:0:0:0:ff
2c0f:9981:: 表示 2c0f:9981:0:0:0:0:0:0
:: 表示 0:0:0:0:0:0:0:0
现在,给你一些可能带 0 位压缩表示的 IPv6 地址,你需要将他们转换成完整形式。具体 地说,你需要依次完成以下任务:
1. 恢复被压缩的全 0 组;
2. 补齐被省略的前导 0,直至每组都是 4 位十六进制数;
3. 将所有英文字母转换为小写字母。 例如,上面提到的 5 个 IPv6 地址,它们对应的完整表示分别为
abcd:1234:aca9:0123:4567:0089:0000:0000
7abc:0000:0000:0000:0000:0000:00ff:fffc
00fc:0000:0000:8976:0000:0000:0000:00ff
2c0f:9981:0000:0000:0000:0000:0000:0000
0000:0000:0000:0000:0000:0000:0000:0000
输入描述:
第一行包含一个整数 T (1 ≤ T ≤ 200),表示测试用例的组数。
接下来 T 行,每行一个字符串,表示一个可能带 0 位压缩表示的 IPv6 地址。
保证输入一定是合法的可能带 0 位压缩表示的 IPv6 地址。
输出描述:
依次输出每个 IPv6 地址对应的完整表示。每个地址占一行。
样例输入:
5
abcd:1234:aCA9:123:4567:089:0:0000
7abc::00ff:fffc
FC::8976:0000:0000:0000:00ff
2c0f:9981::
::
样例输出:
abcd:1234:aca9:0123:4567:0089:0000:0000
7abc:0000:0000:0000:0000:0000:00ff:fffc
00fc:0000:0000:8976:0000:0000:0000:00ff
2c0f:9981:0000:0000:0000:0000:0000:0000
0000:0000:0000:0000:0000:0000:0000:0000
模拟题,但是由于代码能力不够强,这道题写了很久。
我是把整个数据分成五部分:
第一部分是开头的四个拘束的输出
第二部分是第一个:到::数据的输出
第三部分是::数据的输出
第四部分是::到最后一个:数据的输出
第五部分是最后四个数据的输出
下面附上一个通过样例的代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<stdio.h>
using namespace std;
char a[60];
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
scanf("%s",a);
int l=strlen(a);
int begin_number=l;
int nod=0;
int first_nod=-1;
int number=0;
for(int i=0;i<l;++i)
{
if(a[i]==':') nod++; //记录:的数量
if(a[i+1]==':') begin_number=i+1; //记录::出现的位置
if(a[i]==':'&&first_nod==-1)
first_nod=i; //记录:第一次出现的位置
}
int zero=8-nod;// 代表::中间补0的数量
for(int i=0;i<4-first_nod;++i)
printf("0");
for(int i=0;i<first_nod;++i)
{
if(a[i]>='A'&&a[i]<='Z')
printf("%c",a[i]+32);
else
printf("%c",a[i]);
} //这里输出的是第一个:前面的内容
for(int i=first_nod;i<begin_number;++i)
{
/*
这里有考虑两种情况,有::和没有::
如果有::需要补0,反之不需要补0
前者的判断只需证明a[i+1]是否等于':'即可
*/
printf(":");//先输出最左边的,然后以:为结点输出
if(a[i+1]==':')//::的情况
{
number++;
for(int k=0;k<zero;++k)
{
printf("0000");
if(k!=zero-1)
printf(":");
}
if(number==nod-1)//如果::出现在最后边,那么要判断::后面的元素,然后输出
{
printf(":");
for(int k=0;k<6-l+i;++k)
printf("0");
for(int k=0;k<l-i-1;++k)
if(a[i+k+2]>='A'&&a[i+k+2]<='Z')
printf("%c",a[i+k+2]+32);
else
printf("%c",a[i+k+2]);
}//补完0之后判断这个:是否是最后一个,如果是的话,输出最后一个:后面的内容
continue;
}
/*
这里的begin_number明明是第一个::出现的位置,可是现在整个for循环的范围却是begin_number;
但是仔细想想,不难想到,排除第一种情况后,剩下的就是没有::,在前面我们给begin_number赋
的初值是l,那么就说得通了
*/
for(int j=i+1;j<l;++j)
{
if(a[j]==':')
{
number++;
int ll=j-i;
for(int k=0;k<5-ll;++k)
printf("0");
for(int k=0;k<ll-1;++k)
{
if(a[i+k+1]>='A'&&a[i+k+1]<='Z')
printf("%c",a[i+k+1]+32);
else
printf("%c",a[i+k+1]);
}
i=j-1;
break;
}
}
if(number==nod-1)
{
i++;
printf(":");
for(int k=0;k<5-(l-i);++k)
printf("0");
for(int k=0;k<l-i-1;++k)
if(a[i+k+1]>='A'&&a[i+k+1]<='Z')
printf("%c",a[i+k+1]+32);
else
printf("%c",a[i+k+1]);
break;
}
}
printf("\n");
}
return 0;
}
/*
5
abcd:1234:aCA9:123:4567:089:0:0000
7abc::00ff:fffc
FC::8976:0000:0000:0000:00ff
2c0f:9981::
::
abcd:1234:aca9:0123:4567:0089:0000:0000
7abc:0000:0000:0000:0000:0000:00ff:fffc
00fc:0000:0000:8976:0000:0000:0000:00ff
2c0f:9981:0000:0000:0000:0000:0000:0000
0000:0000:0000:0000:0000:0000:0000:0000
5
asd:asd:asd:asg:asfg:ef:asf:sf
5
asd:asd::asd:asd
*/
这个代码能通过90+%的测试数据,但是在中间有几十个数据是错误的:
后来发现是有一个地方我在写代码的时候出现了一个失误
这里在标记::位置的时候并没有判断a[i]是否为:,这样就出现了一个BUG,可竟然 通过了那么多样例~~~~~
修改后如下:
这样的话按照原来的思路,就会发现输出数据少了很多。
(原来的思路:这里有考虑两种情况,有::和没有::,如果有::需要补0,反之不需要补0,前者的判断只需证明a[i+1]是否等于':'即可。)
在排出前面判断::位置的BUG之后,很显然,这个想法不是很完善,::后面的那一部分没有输出
这个时候就要分两部分输出
1、::到最后一个:
2、最后一个:后面的内容
AC代码如下:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<iostream>
using namespace std;
char a[60];
int main()
{
int n;
cin>>n;
while(n--)
{
scanf("%s",a);
int l=strlen(a);
int begin_number=l;
int nod=0;
int first_nod=-1;
int end_nod=-1;
int number=0;
for(int i=0; i<l; ++i)
{
if(a[i]==':')
{
nod++; //记录:的数量
end_nod=i;
}
if(a[i]==':'&&a[i+1]==':')
begin_number=i; //记录::出现的位置
if(a[i]==':'&&first_nod==-1)
first_nod=i; //记录:第一次出现的位置
}
int zero=8-nod;// 代表::中间补0的数量
for(int i=0; i<4-first_nod; ++i)
printf("0");
for(int i=0; i<first_nod; ++i)
{
if(a[i]>='A'&&a[i]<='Z')
printf("%c",a[i]+32);
else
printf("%c",a[i]);
}
for(int i=first_nod; i<begin_number; ++i)
{
printf(":");
if(a[i+1]==':')
{
number++;
for(int k=0; k<zero; ++k)
{
printf("0000");
if(k!=zero-1)
printf(":");
}
if(number==nod-1)
{
printf(":");
for(int k=0; k<6-l+i; ++k)
printf("0");
for(int k=0; k<l-i-1; ++k)
if(a[i+k+2]>='A'&&a[i+k+2]<='Z')
printf("%c",a[i+k+2]+32);
else
printf("%c",a[i+k+2]);
}//补完0之后判断这个:是否是最后一个,如果是的话,输出最后一个:后面的内容
continue;
}
for(int j=i+1; j<l; ++j)
{
if(a[j]==':')
{
number++;
int ll=j-i;
for(int k=0; k<5-ll; ++k)
printf("0");
for(int k=0; k<ll-1; ++k)
{
if(a[i+k+1]>='A'&&a[i+k+1]<='Z')
printf("%c",a[i+k+1]+32);
else
printf("%c",a[i+k+1]);
}
i=j-1;
break;
}
}
if(number==nod-1)
{
i++;
printf(":");
for(int k=0; k<5-(l-i); ++k)
printf("0");
for(int k=0; k<l-i-1; ++k)
if(a[i+k+1]>='A'&&a[i+k+1]<='Z')
printf("%c",a[i+k+1]+32);
else
printf("%c",a[i+k+1]);
break;
}
}
if(begin_number!=l)
{
for(int i=0; i<zero; ++i)
{
printf(":0000");
}
for(int i=begin_number+1; i<=end_nod; ++i)
{
int judge=i;
printf(":");
for(int j=i+1; j<=end_nod; ++j)
{
if(a[j]==':')
{
for(int k=0; k<5-(j-i); ++k)
printf("0");
for(int k=0; k<j-i-1; ++k)
{
if(a[i+k+1]>='A'&&a[i+k+1]<='Z')
printf("%c",a[i+k+1]+32);
else
printf("%c",a[i+k+1]);
}
i=j-1;
break;
}
}
if(i==judge)
break;
}
}
if(begin_number!=l)
{
for(int i=0; i<5-(l-end_nod); ++i)
printf("0");
for(int i=0; i<l-end_nod-1; ++i)
{
if(a[end_nod+i+1]>='A'&&a[end_nod+i+1]<='Z')
printf("%c",a[end_nod+i+1]+32);
else
printf("%c",a[end_nod+1+i]);
}
}
if(n!=0)
printf("\n");
}
return 0;
}