HJ_18有效的IP地址与掩码

前言

我在考试2.17那天,进度只来得及推到HJ18IP地址那个题。因为我花费了将近两天去了解,熟悉动态规划,进度就不太快,加上从16开始,直到20题都是中等或困难,于我而言,这些题我都需要仔细琢磨的。

复习前几天还焦虑的睡不着,后面就被这个强度打败,晚上回去都看不动了,很快就睡着。因为鄙人身体一向不好,精力不足,学生时代也饱受困扰,成绩均不理想,这波就是不服气又想冲一把。

我的结果是out,hr说300分。

考试当天三个题,读题就废了好大功夫,第一题我懵住好一会儿,那个猜字谜感觉要四个循环嵌套才行,然后在纸上比划时候突然想到阿斯码,第一题做完我信心满满,结果一提交用例就通过83.3%,我不服气,硬要找原因,后面时间浪费严重。

因为我其实是准备放弃第三题的嘛,前面读题感觉超级复杂。第二题是啥给忘了我感觉还算简单,但是还是不能通过全部用例,裂开,有了前面浪费时间的经验我就不管了,直接推第三题。结果看着看着,我画完表格分析感觉自己有思路,可惜没时间,就简单写了个最基础的东西,能通过3%用例。

有些可惜结果不好,但是我不后悔这次尝试,感觉收获很多,以及转变了自己的思想。以前觉得算法只会涉及到复杂的问题如背包等,我不会,也用不到就不想刷。但这波我背包搞懂了,而且发现算法题也有对新手友好的。然后我觉得我可以恶补基础,多写代码,重学数据结构、高数线代、英语等课程,高数英语我大学学的时候感觉理解不透彻,没关系,我从高中开始补,从哪里跌倒就从哪里爬起来。

一、描述

描述
请解析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就是一个非法的掩码)
(注意二进制下全是1或者全是0均为非法子网掩码)

注意:

  1. 类似于【0...】和【127...】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时请忽略
  2. 私有IP地址和A,B,C,D,E类地址是不冲突的

输入描述:
多行字符串。每行一个IP地址和掩码,用~隔开。

请参考帖子https://www.nowcoder.com/discuss/276处理循环输入的问题。
输出描述:
统计A、B、C、D、E、错误IP地址或错误掩码、私有IP的个数,之间以空格隔开。

示例1
输入:
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

说明:
10.70.44.68255.254.255.0的子网掩码非法,19…0.255.255.255.0的IP地址非法,所以错误IP地址或错误掩码的计数为2;
1.0.0.1~255.0.0.0是无误的A类地址;
192.168.0.2~255.255.255.0是无误的C类地址且是私有IP;
所以最终的结果为1 0 1 0 0 2 1
示例2
输入:
0.201.56.50~255.255.111.255
127.201.56.50~255.255.111.255

输出:
0 0 0 0 0 0 0

说明:
类似于【0...】和【127...】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时请忽略

二、代码与分析

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HJ17_IPAddr
{
    class Program
    {
        /*
         * 计算有效的IP地址与子网掩码
         */
        public static Dictionary<string, string> dic = new Dictionary<string, string>();
        public static Dictionary<string, int> res = new Dictionary<string, int>();

        public static void Main(string[] args)
        {
            string line;
            // 结果数组初始化
            res.Add("A", 0);
            res.Add("B", 0);
            res.Add("C", 0);
            res.Add("D", 0);
            res.Add("E", 0);
            res.Add("error", 0);
            res.Add("private", 0);
            while (!string.IsNullOrWhiteSpace((line = System.Console.ReadLine())))
            {
                try
                {
                    // 注意 while 处理多个 case
                    string[] tokens = line.Split('~');
                    // 先读取IP与子网掩码                
                    if (!dic.ContainsKey(tokens[0]))
                    {
                        dic.Add(tokens[0], tokens[1]);
                    }
                    //System.Console.WriteLine(tokens[0] + tokens[1]);
                    // 读取完毕,开始判断

                    // 用res放不同的key存储各个数量                       
                    // 先判断IP
                    if (checkIP(tokens[0]))
                    {
                        string ip1 = tokens[0].Split('.')[0];
                        if (int.Parse(ip1) == 0 || int.Parse(ip1) == 127)
                        {
                            // 开头0与127忽略
                            continue;
                        }
                        // 检验掩码
                        if (checkYan(tokens[1]))
                        {
                            // ip合法,掩码合法
                            // 先判断私有
                            if (checkPrivate(tokens[0]))
                            {
                                if (res.ContainsKey("private"))
                                {
                                    res["private"] += 1;
                                }
                                else
                                {
                                    res.Add("private", 1);
                                }
                            }
                            // A类
                            int first = int.Parse(tokens[0].Split('.')[0]);
                            if (first >= 1 && first <= 126)
                            {
                                if (res.ContainsKey("A"))
                                {
                                    res["A"] += 1;
                                }
                                else
                                {
                                    res.Add("A", 1);
                                }
                            }
                            // B类
                            if (first >= 128 && first <= 191)
                            {
                                if (res.ContainsKey("B"))
                                {
                                    res["B"] += 1;
                                }
                                else
                                {
                                    res.Add("B", 1);
                                }
                            }
                            // C类
                            if (first >= 192 && first <= 223)
                            {
                                if (res.ContainsKey("C"))
                                {
                                    res["C"] += 1;
                                }
                                else
                                {
                                    res.Add("C", 1);
                                }
                            }
                            // D类
                            if (first >= 224 && first <= 239)
                            {
                                if (res.ContainsKey("D"))
                                {
                                    res["D"] += 1;
                                }
                                else
                                {
                                    res.Add("D", 1);
                                }
                            }
                            // E类
                            if (first >= 240 && first <= 255)
                            {
                                if (res.ContainsKey("E"))
                                {
                                    res["E"] += 1;
                                }
                                else
                                {
                                    res.Add("E", 1);
                                }
                            }
                        }
                        else
                        {
                            // 记录掩码不合法
                            if (res.ContainsKey("error"))
                            {
                                res["error"] += 1;
                            }
                            else
                            {
                                res.Add("error", 1);
                            }
                        }
                    }
                    else
                    {
                        // 记录IP不合法
                        if (res.ContainsKey("error"))
                        {
                            res["error"] += 1;
                        }
                        else
                        {
                            res.Add("error", 1);
                        }
                    }
                }
                catch (Exception e)
                {
                    System.Console.WriteLine(e.Message);
                }


            }
            Console.Write(res["A"] + " " + res["B"] + " " + res["C"] + " " + res["D"] + " " + res["E"] + " " + res["error"] + " " + res["private"] + " ");
            Console.WriteLine();
            Console.ReadLine();
        }
        // 检验IP
        public static bool checkIP(string IPstr)
        {
            // 合法返回true,不合法返回false
            string[] IP = IPstr.Split('.');
            if (IP.Length != 4)
            {
                // 不合法,长度不够
                return false;
            }
            foreach (string ss in IP)
            {
                if (string.IsNullOrWhiteSpace(ss))
                {
                    // 不合法,对应位置为空
                    return false;
                }
                else if (int.Parse(ss) < 0 || int.Parse(ss) > 255)
                {
                    //超出范围
                    return false;
                }
            }
            return true;
        }
        // 检验私有
        public static bool checkPrivate(string IPstr)
        {
            string[] IP = IPstr.Split('.');
            // 第一类私有
            if (int.Parse(IP[0]) == 10)
            {
                return true;
            }
            // 第二类私有
            if (int.Parse(IP[0]) == 172 && int.Parse(IP[1]) <= 31 && int.Parse(IP[1]) >= 16)
            {
                return true;
            }
            // 第三类私有
            if (int.Parse(IP[0]) == 192 && int.Parse(IP[1]) == 168)
            {
                return true;
            }
            return false;
        }
        // 检验掩码
        public static bool checkYan(string Yanstr)
        {
            if (!checkIP(Yanstr))
            {
                // 掩码也是ip,要先符合ip规则
                return false;
            }
            // 全1或全0返回false
            if (Yanstr == "255.255.255.255" || Yanstr == "0.0.0.0")
            {
                return false;
            }
            string[] yan = Yanstr.Split('.');
            string[] NewYan = new string[yan.Length];
            // 依次转二进制,并按照8位高位补零
            for (int i = 0; i < yan.Length; i++)
            {
                NewYan[i] = Convert.ToString(int.Parse(yan[i]), 2);
                if (NewYan[i].Length < 8)
                {
                    NewYan[i] = NewYan[i].PadLeft(8, '0');
                }
            }
            // 拼接起来查找最后一个1和第一个0的位置,不符合的一律非法
            string last = string.Join("", NewYan);
            int addrlast1 = last.LastIndexOf('1');
            int addrFirst0 = last.IndexOf('0');
            if (addrlast1 + 1 != addrFirst0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
    }
}

三、总结

1.这道题呢,不是那种费脑子得难,而是考验模拟流程,繁琐过程设计精细。于我而言,我的计算机网络掌握的不太好,看了官方解题我才发现,子网掩码它首先也得是个合法IP,然后再判断。以及题目给出的0和127开头后面*原来是泛指,我以前那个位置没有数字是字符然后不合法呢,这个以后记住以下。

2.代码流程:主方法循环读取字符串并判断,检验IP时候注意处理空或长度不够,以及校验每一位数字,不可以<0,不可以>255。

3.检验完ip,true继续往下,忽略0和127,false记录错误数,检验掩码注意掩码也首先是合法ip,然后排除全一与全零,拆分每个字符转二进制并八位补零。补完了查找最后一个1位置与第一个0位置,校验关系可得合不合法。

4.掩码为true往下走,false记录错误数量,接下来先校验私有ip与ABCD类,这个没啥说的就按照要求写即可。需要注意的是,我刚开始精力不足,校验ip出了些小失误,今天精力好了就完全解决了。

5.用到了dictionary,split,join,padleft,indexof,lastindexof,还有个要注意的要是全都不合法结果字典就没东西了,所以初始化了我都给赋值0.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值