http://ncc.neuq.edu.cn/oj/problem.php?id=1024
需要注意的几种代表性情况:
1)双冒号
双冒号在中间,冒号不超过6个;
双冒号在两边,冒号不超过7个;
如果不存在双冒号那冒号的个数就是固定的了。
2)不存在多个双冒号的情况,如 ::: 是不符合标准的。
采用逆序读取简化字符串,逆序输出到原始IPV6格式(IPV6格式初值"0000:0000:0000:0000:0000:0000:0000:0000"),这样比较简单,不足四个的直接滤过。
#include<iostream>
#include<string>
using namespace std;
int main(){
//freopen("G:/ipv6_1.in", "r", stdin);
int n;
cin>>n;
while(n--){
string ip_simple;
string ip_origin("0000:0000:0000:0000:0000:0000:0000:0000");
cin>>ip_simple;
//首先判断是否符合IPV6标准
string::iterator iter=ip_simple.begin();
int digital_num=0; //the number of digital between two colon,<=4
int colon_num=0;// the number of colon
int hex_flag=1; //hex
int colon_error=0; //双冒号只能出现一次的flag
int double_colon_first=0;
int double_colon_besides=0; //双冒号在两边1
while(iter != ip_simple.end()-1){
if(*iter==':'&&*(iter+1)==':'&&double_colon_first==0) {
double_colon_first=1;
if(iter==ip_simple.end()-2||iter==ip_simple.begin())
double_colon_besides=1;
}
else if(*iter==':'&&*(iter+1)==':'&&double_colon_first==1) colon_error=1;
if(*iter==':')
colon_num++;
iter++;
}
if(*iter==':')
colon_num++;
if(double_colon_first==0){
//如果不存在双冒号那冒号的值就是固定的了
if(colon_num!=7) colon_error=1;
}
else if(colon_num>2+4&&!double_colon_besides) colon_error=1; //双冒号在中间,冒号不超过6个才对
else if(colon_num>2+5&&double_colon_besides) colon_error=1; //双冒号在两边,冒号不超过7个才对
iter=ip_simple.begin();
while(iter != ip_simple.end()){
if(*iter==':') {
digital_num=0;
}
else if((*iter>='0'&&*iter<='9')||(*iter>='A'&&*iter<='Z')||(*iter>='a'&&*iter<='z')){
digital_num++;
if(digital_num>4) break;
}
else {
hex_flag=0;
break;
}
iter++;
}
if(colon_num<2||colon_num>7||digital_num>4||!hex_flag||colon_error){
//cout<<endl;
//cout<<"colon_num:"<<colon_num<<"\t digital_num:"<<digital_num<<"\tcolon_error:"<<colon_error<<endl;
cout<<"INVALID"<<endl;
continue;
}
else
{
//cout<<endl;
//cout<<"colon_num:"<<colon_num<<"\t digital_num:"<<digital_num<<endl;
//cout<<n+1<<":OK"<<endl;
;
}
//进行还原,逆序进行
digital_num=0;
int double_colon=0;//连续的冒号
string::iterator double_colon_flag;//标记双冒号的位置
string::iterator iter_origin=ip_origin.end()-1;
for(string::iterator iter_simple=ip_simple.end()-1;iter_simple>=ip_simple.begin();iter_simple--){
if(*iter_simple!=':'){
//数字,输出4位十六进制数
*iter_origin=*iter_simple;
iter_origin--;
digital_num++;
}
else if(iter_simple!=ip_simple.end()-1&&*(iter_simple+1)==':') {
//连续的冒号
double_colon=1;
double_colon_flag=iter_simple;//标记双冒号的位置
break; //转到下面处理
}
else{
if(digital_num!=4){
for(int i=digital_num+1;i<=4;i++)
iter_origin--; //直接取默认值0
}
iter_origin--;
digital_num=0;
}
}
if(double_colon==1){
//处理连续的冒号
int colon_num_front=0; //连续的冒号之前冒号的个数
int num_num_front=0; //连续的冒号之前数字的个数
for(string::iterator iter_simple=ip_simple.begin();iter_simple<double_colon_flag;iter_simple++){
//计算在连续的冒号之前冒号和数字的个数
if(*iter_simple==':') colon_num_front++;
else num_num_front++;
}
if(colon_num_front==0&&num_num_front==0){
//全是0
;
}
else{
//colon_num_front+1个十六进制的四位数
string::iterator iter_simple=double_colon_flag-1;
iter_origin=ip_origin.begin()+(colon_num_front+1)*4+colon_num_front-1;
digital_num=0;
for(;iter_simple>=ip_simple.begin();iter_simple--){
if(*iter_simple!=':'){
//数字,输出4位十六进制数
*iter_origin=*iter_simple;
iter_origin--;
digital_num++;
}
else{
if(digital_num!=4){
for(int i=digital_num+1;i<=4;i++)
iter_origin--; //直接取默认值0
}
iter_origin--;
digital_num=0;
}
}
}
}
for(string::iterator iter=ip_origin.begin();iter<ip_origin.end();iter++)
cout<<*iter;
cout<<endl;
}
}