南华大学20级软卓选拔(右鸽邀你判ip)

开始讲解之前,我先说一下我的感受,虽然这道题只是一道模拟题目,并没有考察算法,但是作者写出来的时候是十分开心的,因为这道题目利用是我第一道基本直接利用STL内的函数写出来的题目,所以作者觉得意义重大,所以就拿出来分享给大家。

题目如下:

右鸽最近在学计算机⽹络原理,所以想着把学到的知识跟你分享⼀下。

IPv6(Internet Protocol Version 6) 即互联⽹协议第六版, IPv6 的出现就是为了替代 IPv4 ,主要原因是 IPv4 的地址不够⽤。随着科技的发展,我们的⽣活⽔平不断提⾼,很多空调,⾳响,电视机都要上⽹,导致⽹络上IP地址不够⽤,所以升级成 IPv6 ,有点夸张的是, IPv6 就可以满⾜让每⼀个沙⼦都有编号地址可以上⽹。
下⾯简要说明⼀下 IPv4 地址和 IPv6 地址的特点。

IPv4 地址由⼗进制数和点("..")来表⽰,每个地址包含4个⼗进制数,其范围为 0 - 2550−255, ⽤("..")分割。⽐如172.16.254.1172.16.254.1 。
同时,IPv4 地址内的数不会有前导 00 。⽐如,地址 172.16.254.01172.16.254.01 是不合法的。

IPv6 地址由 88 组 1616 进制的数字来表⽰,每组表⽰ 1616 ⽐特。这些组数字通过 ("::")分割。
⽐如, 2001:0db8:85a3:0000:0000:8a2e:0370:73342001:0db8:85a3:0000:0000:8a2e:0370:7334 是⼀个有效的地址。
⽽且,我们可以加⼊⼀些以 00 开头的数字(即允许有前导00的情况),字母可以使⽤⼤写,也可以是⼩写。
所以, 2001:db8:85a3:0:0:8A2E:0370:73342001:db8:85a3:0:0:8A2E:0370:7334 也是⼀个有效的 IPv6 地址 (即忽略 00 开头,忽略⼤⼩写)。
然⽽,我们不能因为某个组的值为 00 ,⽽使⽤⼀个空的组,以⾄于出现 (::::) 的情况。
⽐如,2001:0db8:85a3::8A2E:0370:73342001:0db8:85a3::8A2E:0370:7334 是⽆效的 IPv6 地址。
同时,在 IPv6 地址中,每组中的数字超过4位也是不被允许的,因为这样他就超过 1616 ⽐特了(即使超过的位是 00 也不被允许)。
⽐如, 02001:0db8:85a3:0000:0000:8a2e:0370:733402001:0db8:85a3:0000:0000:8a2e:0370:7334 是⽆效的,因为 0200102001 超过了 44 位。

右鸽不想让你养成⽩嫖的不良习惯,于是想让聪明的你即学即⽤,帮右鸽编写程序来验证输⼊的字符串是否是有效的 IPv4 或 IPv6 地址。

输入:

输⼊⼀个整数 n(1≤n≤1000) 接下来的 n ⾏,每⾏输⼊⼀个需要判断的字符串

输出:

对于每⼀个字符串输出⼀⾏。
如果输⼊的字符串是有效的 IPv4 ,则输出 IPv4 ;
如果输⼊的字符串是有效的 IPv6 ,则输出 IPv6 ;
如果输⼊的字符串不合法,则输出 Invalid 。

样例输入:

5
172.16.0.1
172.16.0.01
2001:0db8:85a3:0:0000:8A2E:0370:7334
2001:0db8:85a3:0:0000:8A2E:0370:733w
02001:0db8:85a3:0:0000:8a2e:0370:7334

样例输出:

IPv4
Invalid
IPv6
Invalid
Invalid

这道题的一个难点就是需要判断的条件太多,并且需要对字符串和整形数据进行转换,这里就可以用到一个函数stoi(),这个函数很好记忆,s即string,to就是到达的意思,i就是int整形数据的意思,里面的参数就是一个字符串,在解决好了转换问题,那么我们怎么将每一段的数据抽取出来呢?我们注意到每个地址都有“.” 或者“:”符号,因此我们可以利用string类的成员函数find()找到这个标志的位置,再利用string类的成员函数substr()获取字串,在对这个字串加以判断,最后达到我们想要的结果。

tips:这里有个小细节是需要自己发现的,就是判断ipv6的时候还要对里面的字母加以判断,因为是十六进制,所以字母不会超过F或者f,作者刚开始就漏掉了这一点,不过后面想到了。

这道题目如果不灵活运用这些函数的话,那么代码量将会很大,大概是用函数方法的两倍代码量

AC代码:

#include <iostream>
#include <string>
using namespace std;
string b[1001];     //该数组用于储存结果
bool judge(string str)//判断ipv6是否有字符超过十六进制的使用范围
{
	for (int i = 0; i < str.size(); i++)
	{
		if (str[i] > 70 && str[i] <= 90 || str[i] > 111 && str[i] <= 122)
			return true;
	}
	return false;
}
int main()
{
	int n, j = 0;
	string a;
	cin >> n;
	while (n--) //n次访问
	{
		cin >> a;
		int pos = a.find('.');   //每次判断前先判断字符串类型
		int pos1 = a.find(':');
		if (pos != -1)   //如果是ipv4
		{
			while (pos != -1)  
			{
				pos = a.find('.');  //更新'.'的位置
				string str = a.substr(0, pos);
				if (a[0] == '0' && str.size() > 1 || stoi(str) > 255 )
				{
					b[j] = "Invalid";  
					j++;
					pos = 0; //将pos置为0防止多次判断
					break;
				}
				else
				{
					a = a.erase(0, pos + 1); //更新字符串
				}
			}
			if (pos == -1) // 如果将前三组数据判断完后,那么判断最后一组数据
			{
				if (a[0] == '0' && a.size() > 1 || stoi(a) > 255)
				{
					b[j] = "Invalid";
					j++;
				}
				else
				{
					b[j] = "IPv4";
					j++;
				}
			}
		}
		else if (pos1 != -1)// 如果改字符串是ipv6,其实到这里和判断ipv4差不多,只是条件不太一样
		{
			while (pos1 != -1)
			{
				pos1 = a.find(':'); //更新':'的位置
				string str = a.substr(0, pos1);
				if (str.size() > 4 || a[pos1 + 1] == ':' || judge(str))
				{
					b[j] = "Invalid";
					j++;
					pos1 = 0;
					break;
				}
				else
				{
					a = a.erase(0, pos1 + 1);
				}
			}
			if (pos1 == -1) //判断最后一组数据
			{
				if (a.size() > 4 || judge(a))
				{
					b[j] = "Invalid";
					j++;
				}
				else
				{
					b[j] = "IPv6";
					j++;
				}
			}
		}
	}
	for (int i = 0; i < j; i++)
	{
		cout << b[i] << endl;  //将结果遍历输出
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值