long ip2long( char *ip )
{
long ip2long = 0;
char B1[4], B2[4], B3[4], B4[4];
int D1, D2, D3, D4 = 0;
sscanf(ip, "%s.%s.%s.%s", B1, B2, B3, B4);
D1 = atoi(B1);
D2 = atoi(B2);
D3 = atoi(B3);
D4 = atoi(B4);
if(D1 > 255 || D2 > 255 || D3 > 255 || D4 > 255)
return 0;
ip2long = D1*256*256*256+D2*256*256+D3*256+D4;
return ip2long;
}
输入数据:127.1.1.2
为什么D1 == 127,但D2,D3和D4 == 0?
---更新--- 现在代码是
unsigned long ip2long( char *ip )
{
unsigned long ip2long = 0;
unsigned int D1, D2, D3, D4 = 0;
sscanf(ip, "%u.%u.%u.%u", &D1, &D2, &D3, &D4);
if(D1 > 255 || D2 > 255 || D3 > 255 || D4 > 255)
return 0;
ip2long = D1*256*256*256+D2*256*256+D3*256+D4;
return ip2long;
}
迪是好的,但还有另一个麻烦:127.1.1.2的结果是2130772226而不是2130772225,结果195.98.157.132是-1016947324 ... 为什么呢?
---更新2 --- 多数民众赞成,%d instread%u。
Kornel Kisielewicz感谢您讲述inet_addr函数:)
对不起我的英语不好= \
问题已经结束。
答案 0 :(得分:7)
正如fizzer所说,%s
消耗整个字符串 - 在这种情况下危险地将其复制到S1的末尾。如果将sscanf()结果与4进行比较,那将会有一个很大的线索!不要认为事情会起作用,特别是在从程序外部解析输入时。 atoi
会忽略尾随垃圾,因此即使使用%[^.]
字符串格式会在一段时间内停止,它也会通过忽略192,3.2x.3.1
和,3
来处理x
之类的垃圾值
fizzer对("...%d...", &D1...)
的建议是一个好的开始,但你仍然必须将结果与4进行比较,否则像“hello”这样的无效字符串只会使D1,D2,D3和D4保持不变。将接受负值。请注意,只有D4设置为0 - 其他值不受该行上的尾随= 0
的影响,并且可能包含堆栈中的旧垃圾值,这些值可能会或可能不会通过后面的255检查。
综上所述:
unsigned long ip2ulong(char *ip)
{
unsigned u1, u2, u3, u4;
return sscanf(ip, "%u.%u.%u.%u", &u1, &u2, &u3, &u4) == 4 &&
u1 <= 255 && u2 <= 255 && u3 <= 255 && u4 <= 255
? u1*256*256*256 + u2*256*256 + u3*256 + u4 : 0;
}
答案 1 :(得分:5)
第一个%s消耗整个输入,然后atoi仅转换初始数字。改为使用%d,并传入&amp; D1,&amp; D2等相应的参数。
然后考虑对Di使用无符号整数,对于格式转换使用%u,对结果使用unsigned long。长可能窄至32位,并且由此产生的符号差异可能会令人惊讶。
答案 2 :(得分:5)