leetcode751题,IP 到 CIDR。之前介绍过简单的C数据结构-位运算处理,但是这道题新鲜的东西很多,值得再写一篇。
题目意思就是取IP后联系N个地址,但是表达方法要用CIDR。
真的想不出来真的想不出来真的想不出来,作者太牛了,戳这里看作者题解!
整个神奇的地方有:
1、sscanf可以转字符串为整数,作为初始计算点。
2、对整数取二进制下最后一个1的位置,这个位置如果比n小,那么可以生成一串地址,然后检查与n的关系继续循环。获取二进制下最后一个1的位置方法是x&-x
3、通过sprintf转整数为拼接字符串。
4、申请指针空间居然是ret = (char *)realloc(ret, sizeof(char) * (count + 1));–但是这个函数不够安全
1、字符串转整数处理
unsigned long charToLong(char *ip)
{
unsigned long a, b, c, d;
unsigned long ret;
sscanf_s(ip, "%lu.%lu.%lu.%lu", &a, &b, &c, &d);
ret = (a << 24) | (b << 16) | (c << 8) | (d);
return ret;
}
2、进行功能处理
while (n > 0) {
prefix = 0;
bestlow = iplong & (-1) * iplong;
while (bestlow > n) {
bestlow = bestlow >> 1;
}
oneloc = bestlow >> 1;
while (oneloc) {
oneloc = oneloc >> 1;
prefix++;
}
ret = (char **)realloc(ret, sizeof(char*) * (count + 1));
ret[count] = (char*)malloc(sizeof(char)*IPMAX);
longToChar(iplong, 32 - prefix, ret[count]);
n -= bestlow;
iplong += bestlow;
count++;
}
3、字符串转整数
void longToChar(unsigned int iplong, int prefix, char *ret)
{
unsigned long a, b, c, d;
d = iplong & 0xff;
c = (iplong >> 8) & 0xff;
b = (iplong >> 16) & 0xff;
a = (iplong >> 24) & 0xff;
sprintf_s(ret, IPMAX, "%lu.%lu.%lu.%lu/%d", a, b, c, d, prefix);
return;
}