Talk is cheap, show me the code.
请解析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
子网掩码为前面是连续的1,然后全是0。(例如:255.255.255.32就是一个非法的掩码)
本题暂时默认以0开头的IP地址是合法的,比如0.1.1.2,是合法地址
输入描述:
多行字符串。每行一个IP地址和掩码,用~隔开。
输出描述:
统计A、B、C、D、E、错误IP地址或错误掩码、私有IP的个数,之间以空格隔开。
输入例子:
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
题目有些地方没有讲清楚,害我花了很多时间去揣摩意思。首先要确定ip以0开头和以127开头都是正确的输入,不过不属于任何一类而已,然后判断掩码正确与否时除了必须1都在0前面,还要注意255.255.255.255是错误的掩码。另外还要注意私网ip其实也是ABCDE类中某一类,两类都要加一。
解题方式1:
全部代码按逻辑来,不投机取巧。
#include
#include
#include
#include
using namespace std;
int main()
{
int aNum = 0, bNum = 0, cNum = 0, dNum = 0, eNum = 0, errNum = 0, priNum = 0;
int ip[4] = {0}, code[4] = {0};
string line;
while (cin >> line)
{
string ipstr, codestr;
bool ipflag = false, codeflag = false;
istringstream is(line);
getline(is, ipstr, '~');
string s;
int i = 0;
istringstream is1(ipstr);
while (getline(is1, s, '.'))
{
if (s == "")
{
break;
} else {
int temp = atoi(s.c_str());
if (temp < 0 || temp > 255)
{
break;
} else {
if (i < 4)
ip[i] = temp;
i++;
}
}
}
if (i != 4)
{
errNum += 1;
continue;
} else {
ipflag = true;
}
getline(is, codestr, '~');
istringstream is2(codestr);
string s1;
int j = 0;
while (getline(is2, s1, '.'))
{
int temp = atoi(s1.c_str());
if (s1 == "")
break;
else {
if (temp < 0 || temp > 255)
{
break;
} else {
bitset<8> bs(temp);
int t = -1;
for (int i = bs.size() - 1; i >= 0; i--)
{
if (bs[i] == 0)
{
t = i;
break;
}
}
for (int i = t - 1; i >= 0; i--)
{
if (bs[i] != 0)
{
temp = -1;
break;
}
}
if (temp == -1)
break;
else {
code[j] = temp;
j++;
}
}
}
}
if (j != 4)
{
errNum++;
continue;
} else {
j = 0;
while (j < 4 && code[j] == 255)
{
j++;
}
for (int i = j + 1; i < 4; i++)
{
if (code[i] != 0)
{
j = -1;
break;
}
}
if (j == -1 || code[3] == 255)
{
errNum++;
continue;
} else {
codeflag = true;
}
}
if (ipflag && codeflag)
{
if (ip[0] >= 1 && ip[0] <= 126)
{
aNum++;
if (ip[0] == 10)
priNum++;
} else if (ip[0] >= 128 && ip[0] <= 191) {
bNum++;
if (ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31)
priNum++;
} else if (ip[0] >= 192 && ip[0] <= 223) {
cNum++;
if (ip[0] == 192 && ip[1] == 168)
priNum++;
} else if (ip[0] >= 224 && ip[0] <= 239) {
dNum++;
} else if (ip[0] >= 240 && ip[0] <= 255) {
eNum++;
}
}
}
cout << aNum << " " << bNum << " " << cNum << " " << dNum << " " << eNum << " " << errNum << " " << priNum << endl;
return 0;
}
虽然全部逻辑实现,但是逻辑不算直观,思路是先判断输入的ip是否有效,有效则存储在ip数组中,然后判断掩码每个数字是不是符合规范的,每个数字都符合规范就把掩码都存储在code数组中,再判断整个32位掩码是不是符合规范的,这里特别要注意出去255.255.255.255的情况,如果ip和掩码都符合规范,再进行分类,同时属于私网和公网某类的两类都需要计数加一。
解题方式2:
下面这种方式判断掩码是否正确是通过列举出8位的所有可能值一次判断的,虽然很直观,但不是很满意。
#include
#include
#include
#include
using namespace std;
int stringtoint(string str){
stringstream ss;
ss<>x;
return x;
}
vector toint(string str){
vector res;
string temp;
int ele;
for(int i=0;i res){
if(res.size()!=4)
return false;
if(res[0]==255){
if(res[1]==255){
if(res[2]==255){
if(res[3]==254||res[3]==252||res[3]==248||res[3]==240||res[3]==224||res[3]==192||res[3]==128||res[3]==0){
return true;
}
else{
return false;
}
}
else{
if(res[2]==254||res[2]==252||res[2]==248||res[2]==240||res[2]==224||res[2]==192||res[2]==128||res[2]==0){
if(res[3]==0){
return true;
}
else{
return false;
}
}
}
}
else{
if(res[1]==254||res[1]==252||res[1]==248||res[1]==240||res[1]==224||res[1]==192||res[1]==128||res[1]==0){
if(res[3]==0&&res[2]==0){
return true;
}
else{
return false;
}
}
}
}
else{
if(res[0]==254||res[0]==252||res[0]==248||res[0]==240||res[0]==224||res[0]==192||res[0]==128){
if(res[3]==0&&res[2]==0&&res[1]==0){
return true;
}
}
else{
return false;
}
}
return false;
}
int main(){
string str;
int* res=new int[7];
for(int j=0;j<7;j++)
res[j]=0;
while(cin>>str){
string ipstring;
string maskstring;
vector ip,mask;
int i=0;
for(;str[i]!='~';i++){
ipstring.push_back(str[i]);
}
i++;
for(;i=0&&ip[1]<=255&&ip[2]>=0&&ip[2]<=255&&ip[3]>=0&&ip[3]<=255){
if(ip[0]>=1&&ip[0]<=126){
res[0]++;
if(ip[0]==10)
res[6]++;
}
else if(ip[0]>=128&&ip[0]<=191){
res[1]++;
if(ip[0] == 172 && ip[1] >= 16 && ip[1] <= 32)
res[6]++;
}
else if(ip[0]>=192&&ip[0]<=223){
res[2]++;
if(ip[0] == 192 && ip[1] == 168)
res[6]++;
}
else if(ip[0]>=224&&ip[0]<=239){
res[3]++;
}
else if(ip[0]>=240&&ip[0]<=255){
res[4]++;
}
}
}
else{
res[5]++;
}
}
cout<
解题方式3:
这种方式分层比较清晰,虽然也是通过列举法来判断掩码,但是代码可读性最强。
#include
#include
#include
using namespace std;
void split(string& str, vector& strs){
int pos=str.find('.');
while(pos>=0){
strs.push_back(str.substr(0, pos));
str=str.substr(pos+1, str.length()-pos-1);
pos=str.find('.');
}
strs.push_back(str);
}
bool checkNum(string& str){
if(str.size()==0 || str.size()>3)
return false;
for(int i=0; i'9')
return false;
}
int num=atoi(str.c_str());
if(num>=0 && num<=255)
return true;
return false;
}
bool checkIP(vector& segs){
if(segs.size()!=4)
return false;
for(int i=segs.size()-1; i>=0; i--){
if(!checkNum(segs[i]))
return false;
}
//if(atoi(segs[0])==127)
// return false;
return true;
}
bool checkMask(vector& segs){
if(segs.size()!=4)
return false;
bool start=false;
for(int i=0; i& ip, vector& counter){
int n1=atoi(ip[0].c_str());
int n2=atoi(ip[1].c_str());
if(n1>=1 && n1<=126){
if(n1==10)
counter[6]++;
counter[0]++;
}else if(n1>=128 && n1<=191){
if(n1==172 && n2>=16 && n2<=31)
counter[6]++;
counter[1]++;
}else if(n1>=192 && n1<=223){
if(n1==192 && n2==168)
counter[6]++;
counter[2]++;
}else if(n1>=224 && n1<=239)
counter[3]++;
else if(n1>=240 && n1<=255)
counter[4]++;
}
int main(){
vector counter(7, 0);
int W=0, P=0;
string str;
while(cin>>str){
int pos=str.find('~');
string ip=str.substr(0, pos);
string mask=str.substr(pos+1, str.length()-pos-1);
vector ip_segs, mask_segs;
split(ip, ip_segs);
split(mask, mask_segs);
if(!checkIP(ip_segs) || !checkMask(mask_segs))
counter[5]++;
else
classify(ip_segs, counter);
}
cout<