華為線上程式設計題系列-18-識別有效的IP地址和掩碼並進行分類統計
阿新 • • 發佈:2019-01-10
問題描述:
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. 本題總結.
本體難點在於
- 題目的輸入處理.
- 子網掩碼的正確性判斷.
- 題意較為難以理解.