问题描述:
1. 问题涉及知识点.
- 字符串处理
2. 自己解法.
- 这个题在描述的时候说的就很不清晰
- 子网掩码和ip地址不合格,只统计一次.
- 255.255.255.255是不合格的子网掩码
- 五类ip地址中包含私有地址.不对立.
- 下面的处理就比较简单,一个条件一个条件分析.
- 输入问题,做一个无限收入,使用arraylist收集结构.最后一起处理.
package com.chaoxiong.niuke.huawei;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* Create by tianchaoxiong on 18-4-20.
*/
public class HuaWei_18 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 收集.
List<String> stringList =new ArrayList<String>();
while (scanner.hasNext()){
String string = scanner.next();
stringList.add(string);
}
// int N = 4;
// for (int i = 0; i < N; i++) {
// String string = scanner.next();
// stringList.add(string);
// }
// 处理.
int ipA = 0;
int ipB = 0;
int ipC = 0;
int ipD = 0;
int ipE = 0;
int errorIpMask = 0;
int privateIp = 0;
for (String each:stringList) {
// 1 把ip和掩码分开.
String []strArr = each.split("~");
// 判断ip是否合法
boolean isPassIP = isPassIP(strArr[0]);
boolean isPassMask = isPassMask(strArr[1]);
// System.out.println(isPassMask);
if(!isPassIP||!isPassMask){
errorIpMask++;
}
if(isPassIP&&isPassMask){
// return 1:A,2:B,3:C,4:D,5:E,0:P.
int level = getIpLevel(strArr[0]);
// System.out.println("处理的iP "+strArr[0]);
// System.out.println("找到的等级"+level);
if(level==1)
ipA++;
if(level==2)
ipB++;
if(level==3)
ipC++;
if(level==4)
ipD++;
if(level==5)
ipE++;
boolean isPassprivateIp = isPassprivateIp(strArr[0]);
if(isPassprivateIp)
privateIp++;
}
}
System.out.println(ipA+" "+ipB+" "+ipC+" "+ipD+" "+ipE+" "+errorIpMask+" "+privateIp);
}
private static boolean isPassprivateIp(String s) {
String []subStr = s.split("\\.");
int tmp = Integer.parseInt(subStr[0]);
switch (tmp){
case 10:
return true;
case 172:
if(Integer.parseInt(subStr[1])>=16&&Integer.parseInt(subStr[1])<=31){
return true;
}
case 192:
if(Integer.parseInt(subStr[1])==168){
return true;
}
}
return false;
}
private static int getIpLevel(String s) {
// return 1:A,2:B,3:C,4:D,5:E. 0不非法0开头或者127开头
return calcLevel(s);
}
private static int calcLevel(String s) {
String []subStr = s.split("\\.");
int tmp = Integer.parseInt(subStr[0]);
if(tmp>=1&&tmp<=126)
return 1;
else {
if (tmp >= 128 && tmp <= 191)
return 2;
else {
if (tmp >= 192 && tmp <= 223)
return 3;
else {
if (tmp >= 224 && tmp <= 239)
return 4;
else {
if (tmp >= 240 && tmp <= 255)
return 5;
}
}
}
}
return 0;
}
private static boolean isPassMask(String s) {
// 转换成二进制,前面全是1,后面全是0.
// 转成32的一个0/1数组,统计第一次出现0之前的1的总共的1的个数是否相等.
boolean bool = isPassIP(s);
if(!bool)
return false;
String []subStr = s.split("\\.");
int []flagArr =new int[32];
int []flagArrValue = new int[8];
for (int i = 0; i < 8; i++) {
flagArrValue[i] = (int) Math.pow(2, (7 - i));
}
int flag = 0;
for (String each:subStr ) {
getFlagArr(flag,each,flagArr,flagArrValue);
flag++;
}
return calcOneNum(flagArr);
}
private static boolean calcOneNum(int[] flagArr) {
int startOneNum = 0;
for(int each:flagArr){
if (each==0)
break;
else startOneNum++;
}
int allOneNum = 0;
for(int each:flagArr){
if(each==1)
allOneNum++;
}
return (!(allOneNum==32))&&allOneNum==startOneNum;
}
private static void getFlagArr(int flag, String key, int[] flagArr, int[] flagArrValue) {
// flag = 0 表示处理的是第一字段,也就是0到7位;flag = 1 表示处理第二个字段也就是8到15;
int intKey = Integer.parseInt(key);
while (intKey > 0) {
int tmp = getLowNear(intKey, flag * 8, flagArr, flagArrValue);
intKey = intKey - tmp;
}
}
private static int getLowNear(int key, int start, int[] flagArr, int[] flagArrValue) {
for (int i = 0; i < flagArrValue.length; i++) {
if ( key >= flagArrValue[i] ) {
flagArr[start + i] = 1;
return flagArrValue[i];
}
}
return 0;
}
private static boolean isPassIP(String s) {
// 1 都要小于等于255
// 2 都要大于等于0
// 3 不能有空
String []subStr = s.split("\\.");
for (String each:subStr ) {
if(each.trim().equals(""))
return false;
int tmp = Integer.parseInt(each);
if(tmp<0)
return false;
if(tmp>255)
return false;
}
return true;
}
}
3. 优质答案.
null
4. 本题总结.
本体难点在于
1. 题目的输入处理.
2. 子网掩码的正确性判断.
3. 题意较为难以理解.