1.测试用例
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21.1.1.111//测试开头为点的情况 .1.1.1//长度不够+开头为点 1.1.1.//结尾为点+长度不够 11.11.11.//结尾为点 11..11.1//中间存在连续点 ..111.111//开始存在连续点 111.111..//结尾存在连续点 1.11111.11111.1111//数值不合法,长度不合法 1.257.1.1//数值不合法 122.524.13.1//数值不合法 1.1.1.256//数值不合法 111.112.113//数值元数和点数不对 111.112//数值元数和点数不对 111.//数值元数和点数不对 01.3.2.56//开头有非法的零 -100.22.45.134//非法字符 1.1.1.1//合法 2.3.5.1//合法 111.111.1.255//合法 0.1.3.4//合法 114.114.114.114//合法
注:notepad++中,把//[S]*rn替换为rn可去除注释
2.修改后的代码
复制代码
3.新版官方代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125//#define __IP_DEBUG__ int Char_Num_Check(const char c);/*字符是否为数字*/ int Section_Legal_Check(const int sec);/*地址段是否合法*/ inline int Char_Num_Check(const char c) {return (c >= '0' && c <= '9');} inline int Section_Legal_Check(const int sec) {return (sec >= 0 && sec <= 255);} /************************************************** IP合法性鉴别函数 功能:判断一个IP是否合法并打印出不合法的原因 原因包括:1.字符串长度非法 2.非法数字规则(零在最高位) 3.非法的取值(不在0~255之间) 4.非法的点(连续的点) 5.非法的地址段/点数目 **************************************************/ enum NextCharType { NUM=1, DOT=0, NUMORDOT=-1 }; int is_valid_ip(const char *ip) { int section = 0; int DotCount = 0;//实现点计数 int NumCount=0;//实现section计数 int num_dot=NUM;//此时应接收数字还是点,1表示应该接收数字,0表示应该接收点,-1表示任意 int count=3;//用于计算每个数字段的位数,避免单个数字段过长 int flag_num=0;//读取过数字就置为1,方便后续检验合法性 if(strlen(ip)>15||strlen(ip)<7)//预判,ip太短或太长 { #ifdef __IP_DEBUG__ printf("illegal length!n"); #endif return 0; } while (*ip) { while(*ip!='.'&&*ip!='') { if (Char_Num_Check(*ip)) { flag_num=1; if(count==3&&*ip=='0')//最高位是0,下一位一定是点或者 { count=0; num_dot=DOT; ip++; break; } else { num_dot=NUMORDOT;//最高位不为0时,下一位可能是数字或者点 section = section * 10 + (*ip - '0');//计入,最高位为0时由于section已经为0,不用此步 count--;//可用的数字位数减1 ip++; if(count==0)//可用数字位耗尽,下一位必定为点或者 { num_dot=DOT; break; } } } else//出现非法字符 { #ifdef __IP_DEBUG__ printf("illegal char!n"); #endif return 0; } } if(*ip=='.')//为点 { //避免出现连续点 if(num_dot==NUM) { #ifdef __IP_DEBUG__ printf("illegal dots!n"); #endif return 0; } else { num_dot=NUM;//点后面必定是数字 } DotCount++;//点计入 count=3;//后续最多出现3位数字 ip++; if (DotCount > 3) { #ifdef __IP_DEBUG__ printf("too many dots!n"); #endif return 0; } } //section结束,校验、重置并计数 if(flag_num)//确实经过了读取数字的while循环 { if (Section_Legal_Check(section))//校验section合法性并清零 { section = 0; } else//非法section值 { #ifdef __IP_DEBUG__ printf("illegal section value!n"); #endif return 0; } flag_num=0; NumCount++; } } if (3 == DotCount&&NumCount==4)//点数目为3,数字段数目为4 { return 1; } else { #ifdef __IP_DEBUG__ printf("illegal section/dot number!n"); #endif return 0; } }
复制代码
1
2
3
4
5
6
7
8
9
10#ifndef INADDR_NONE #define INADDR_NONE 0xffffffff #endif int inet_aton(const char *cp, struct in_addr *addr) { addr->s_addr = inet_addr(cp); return (addr->s_addr == INADDR_NONE) ? 0 : 1; }
4.测试程序
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> int main(int argc,char*argv[]) { FILE*fp; char buf[1000]; struct in_addr *in_ad; in_ad=malloc(sizeof(struct in_addr)); if(NULL==(fp=fopen(argv[1],"r")))//只读方式打开文件 { #ifdef __IP_DEBUG__ printf("error in open file!n"); #endif exit(1); } while(!feof(fp)) { memset(buf, 0, 15);//IPV4地址最大15字节,故不需要全部清零 fgets(buf, sizeof(buf) - 1, fp); // 包含了n buf[strlen(buf)-2]='';//修改buf尾部,去除rn printf("buf=%sn", buf); #ifdef __IP_DEBUG__ printf("length=%dn", (int)strlen(buf)); #endif //对比结果:修改后VS93版VS官方新版 //自己的 if(is_valid_ip(buf)) printf("PASS!n"); else printf("FAIL!n"); if(inet_aton(buf,in_ad)) printf("PASS!n"); else printf("FAIL!n"); if(inet_aton2(buf,in_ad)) printf("PASS!n"); else printf("FAIL!n"); printf("%sn",inet_ntoa(*in_ad));//打印地址 in_ad->s_addr=0;//清零 } fclose(fp); return 0; }
5.测试结果
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110buf=.1.1.111 FAIL! FAIL! PASS! 0.1.1.111 buf=.1.1.1 FAIL! FAIL! PASS! 0.1.1.1 buf=1.1.1. FAIL! FAIL! PASS! 1.1.1.0 buf=11.11.11. FAIL! FAIL! PASS! 11.11.11.0 buf=11..11.1 FAIL! FAIL! PASS! 11.0.11.1 buf=..111.111 FAIL! FAIL! PASS! 0.0.111.111 buf=111.111.. FAIL! FAIL! PASS! 111.111.0.0 buf=1.11111.11111.1111 FAIL! FAIL! FAIL! 0.0.0.0 buf=1.257.1.1 FAIL! FAIL! FAIL! 0.0.0.0 buf=122.524.13.1 FAIL! FAIL! FAIL! 0.0.0.0 buf=1.1.1.256 FAIL! FAIL! FAIL! 0.0.0.0 buf=111.112.113 FAIL! PASS! PASS! 111.112.113.0 buf=111.112 FAIL! PASS! PASS! 111.112.0.0 buf=111. FAIL! FAIL! PASS! 111.0.0.0 buf=01.3.2.56 FAIL! PASS! PASS! 1.3.2.56 buf=-100.22.45.134 FAIL! FAIL! FAIL! 0.0.0.0 buf=1.1.1.1 PASS! PASS! PASS! 1.1.1.1 buf=2.3.5.1 PASS! PASS! PASS! 2.3.5.1 buf=111.111.1.255 PASS! PASS! PASS! 111.111.1.255 buf=0.1.3.4 PASS! PASS! PASS! 0.1.3.4 buf=114.114.114.114 PASS! PASS! PASS! 114.114.114.114 buf= FAIL! FAIL! PASS! 0.0.0.0
可以看出,93版程序有很多误判,填充规则也不太符合常识(段数不够时,扩充最后一个地址段,高位填零),新版和修改后的版本主要是存在一些歧异,本身都不能算错:
1.地址段不够的,用零填充。
2.最高位的零会被忽略。
3.如果出现连续的点,则认为两个点之间默认填充0。
源码及测例下载链接:
传送门
最后
以上就是称心白开水最近收集整理的关于IPV4地址合法性判别(2)的全部内容,更多相关IPV4地址合法性判别(2)内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复