HJ18. 识别有效的IP地址和掩码并进行分类统计
描述
请解析IP地址和对应的掩码,进行分类识别。要求按照A/B/C/D/E类地址归类,不合法的地址和掩码单独归类。
所有的IP地址划分为 A,B,C,D,E五类
A类地址从1.0.0.0到126.255.255.255;
B类地址从128.0.0.0到191.255.255.255;
C类地址从192.0.0.0到223.255.255.255;
D类地址从224.0.0.0到239.255.255.255;
E类地址从240.0.0.0到255.255.255.255
私网IP范围是:
从10.0.0.0到10.255.255.255
从172.16.0.0到172.31.255.255
从192.168.0.0到192.168.255.255
输入描述
多行字符串。每行一个IP地址和掩码,用~隔开。
请参考帖子https://www.nowcoder.com/discuss/276处理循环输入的问题。输出描述
统计A、B、C、D、E、错误IP地址或错误掩码、私有IP的个数,之间以空格隔开。
示例1
输入:
10.70.44.68~255.254.255.0 1.0.0.1~255.0.0.0 192.168.0.2~255.255.255.0 19..0.~255.255.255.0
输出:
1 0 1 0 0 2 1
说明:
10.70.44.68~255.254.255.0的子网掩码非法,19..0.~255.255.255.0的IP地址非法,所以错误IP地址或错误掩码的计数为2; 1.0.0.1~255.0.0.0是无误的A类地址; 192.168.0.2~255.255.255.0是无误的C类地址且是私有IP; 所以最终的结果为1 0 1 0 0 2 1示例2
输入:
0.201.56.50~255.255.111.255 127.201.56.50~255.255.111.255
输出:
0 0 0 0 0 0 0
说明:
类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时请忽略C 解法, 执行用时: 2ms, 内存消耗: 288KB, 提交时间: 2022-07-11
#include <stdio.h> int main(void) { char str[50]; int illegal_f; int len,i,tmp_i,ip_i,j; int ymtmp; int A=0,B=0,C=0,D=0,E=0,illegal=0,P=0; while(fgets(str,50,stdin)!=NULL){ int ip[8]={0}; len=strlen(str)-1; str[len]=0; illegal_f=0; for(i=0,tmp_i=0,ip_i=0;i<len;i++){ if(('.'==str[i])||('~'==str[i])||(len-1==i)){ if(len-1==i){ i++; } if((3<i-tmp_i)||(i==tmp_i)){ illegal_f=1; break; } else{ for(j=tmp_i;j<i;j++){ ip[ip_i]=ip[ip_i]*10+(int)(str[j]-'0'); } if((255<ip[ip_i])||(0>ip[ip_i])){ illegal_f=1; break; } if(7>ip_i){ ip_i++; } } tmp_i=i+1; } } //+++++++++++++掩码合法性确认++++++++++++++++++++++++++++++++++++++ if(0==illegal_f){ //如果已判断为非法IP,则不需要再判断掩码的合法性了。 if((0==ip[4])&&(0==ip[5])&&(0==ip[6])&&(0==ip[7])){ //掩码全0:非法。 illegal_f=1; } else if((255==ip[4])&&(255==ip[5])&&(255==ip[6])&&(255==ip[7])){//掩码全255:非法。 illegal_f=1; } else{ ymtmp=0; for(i=7;3<i;i--){ for(ip_i=0;8>ip_i;ip_i++,ip[i]/=2){ if(0!=ymtmp){ if(0==ip[i]%2){ illegal_f=1; break; } } else{ ymtmp=ip[i]%2; } } if(0!=illegal_f){ break; } } } } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++IP类型统计+++++++++++++++++++++++++++++++++++++++++ if((0!=ip[0])&&(127!=ip[0])){ if(0!=illegal_f){ //非法IP illegal++; } else if((1<=ip[0])&&(126>=ip[0])){ //A类 A++; if(10==ip[0]){ //私有 P++; } } else if((128<=ip[0])&&(191>=ip[0])){ //B类 B++; if(172==ip[0]){ //私有 if((16<=ip[1])&&(31>=ip[1])){ P++; } } } else if((192<=ip[0])&&(223>=ip[0])){ //C类 C++; if(192==ip[0]){ //私有 if(168==ip[1]){ P++; } } } else if((224<=ip[0])&&(239>=ip[0])){ //D类 D++; } else if((240<=ip[0])&&(255>=ip[0])){ //E类 E++; } } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ } printf("%d %d %d %d %d %d %d",A,B,C,D,E,illegal,P); return 0; }
C 解法, 执行用时: 2ms, 内存消耗: 288KB, 提交时间: 2021-10-08
#include <stdio.h> #include <string.h> #include <ctype.h> char repeat_code(char *s, int *record) { if( !s ) return 0; int len = strlen(s), i = 0, j = 0, val = 0, idx = 0; while(i < len) { if( isdigit( s[i] ) ){ val = val*10 + s[i]-'0'; } else if(s[i] == '.'){ if(j==i || idx==3 || i+1==len || val>255) return 0; record[ idx++ ] = val; val = 0; j = i+1; } else return 0; ++i; } if(idx!=3 || val>255) return 0; record[3] = val; return 1; } char judge_mask(int *mask) { unsigned val = 0; for(int i=0; i<4; ++i) val |= mask[i]<<(3-i)*8; return !(!val || val==0xFFFFFFFF || (val|val-1)!=0xFFFFFFFF); } int main(void) { int ip[4], mask[4], cnt[5] = {0}, Err_cnt = 0, private_cnt = 0; memset(ip, -1, 4*sizeof(int)); memset(mask, -1, 4*sizeof(int)); char s[88]; while(scanf("%s", s) != EOF) { int idx = 0; while(s[idx] && s[idx]!='~') ++idx; if( s[idx] ){ s[idx] = '\0'; } else{ ++Err_cnt; goto rpt; } char ip_flag = repeat_code(s, ip); char mask_flag = repeat_code(s+idx+1, mask); if(!ip[0] || ip[0]==127) goto rpt; if(!ip_flag || !mask_flag || !judge_mask(mask)){ ++Err_cnt; goto rpt; } if(ip[0] < 127){ ++cnt[0]; if(ip[0] == 10) ++private_cnt; } else if(ip[0] < 192){ ++cnt[1]; if(ip[0]==172 && ip[1]>=16 && ip[1]<=31) ++private_cnt; } else if(ip[0] < 224){ ++cnt[2]; if(ip[0]==192 && ip[1]==168) ++private_cnt; } else if(ip[0] < 240) ++cnt[3]; else ++cnt[4]; rpt: memset(ip, -1, 4*sizeof(int)); memset(mask, -1, 4*sizeof(int)); } printf("%d %d %d %d %d %d %d\n", cnt[0], cnt[1], cnt[2], cnt[3], cnt[4], Err_cnt, private_cnt); return 0; }