P7911 [CSP-J 2021] 网络连接

· · 题解

分析

主要问题为:判断这个地址是否合法。

可以用 sscanf 尝试读入形如 a.b.c.d:e 的字符串,并返回读取结果。

如果读到的数不是 5 个,肯定不合法。

然后再判断 a,b,c,d,e 的范围是否合法。

这个时候,再用 a.b.c.d:e 把这个字符串保存,判断是否跟原来字符串是否相同即可。

例子

输入一个 1.2.3.4:5 ,读取结果为a=1,b=2,c=3,d=4,e=5。

这个时候,再按照 a.b.c.d:e 这个方式去保存,得到 1.2.3.4:5,跟原来字符串相同,则合法。

特殊情况

你也许会问,怎么判断前导 0 呢?

其实,我们已经解决了这个问题。

比如: 输入一个 01.2.3.4:5 ,读取结果为 a=1,b=2,c=3,d=4,e=5。

现在再按照 a.b.c.d:e 这个方式去保存,得到 1.2.3.4:5 ,你会发现跟原来的字符不匹配,因为 a 原来是 01 的,现在变成了 1 。

这样,就完美的解决了前导 0 的情况!

其他

判断字符串是否合法已经解决,那么怎么加入并查找一个地址呢?

可以用一个 map 解决,定义一个 map<string,int> vis,string 存地址,int 存下标。

代码

#include<bits/stdc++.h>
using namespace std;
map<string,int> vis;
int n;
bool check(char s[]){
    int a=-1,b=-1,c=-1,d=-1,e=-1;
    int t=sscanf(s,"%d.%d.%d.%d:%d",&a,&b,&c,&d,&e);//尝试读入,保存至s中
    if(t!=5) return 0;//没有5个肯定不行
    if(a<0||a>255) return 0;
    if(b<0||b>255) return 0;
    if(c<0||c>255) return 0;
    if(d<0||d>255) return 0;
    if(e<0||e>65535) return 0;//判断
    char s2[35];
    sprintf(s2,"%d.%d.%d.%d:%d",a,b,c,d,e);//保存至s2中
    int lens=strlen(s);//接下来判断s2和s是否一样
    bool ok=0;
    for(int i=0;i<lens;i++){
        if(s[i]==s2[i]) ok=1;
        else{
            ok=0;
            break;
        }
    }
    return ok;
}
int main(){
//  freopen("network.in","r",stdin);
//  freopen("network.out","w",stdout); 
    cin>>n;
    for(int i=1;i<=n;i++){
        char op[1005],ad[1005];
        cin>>op>>ad;
        string t(ad);
        if(op[0]=='S'){//服务机
            if(!check(ad)) cout<<"ERR"<<endl;//判断是否合法
            else if(vis.count(t)!=0){//之前有了,输出FAIL
                cout<<"FAIL"<<endl;
            } 
            else{
                cout<<"OK"<<endl;
                vis[t]=i;//保存编号
            }
        }
        else{//客户机
            if(!check(ad)){//判断是否合法
                cout<<"ERR"<<endl; 
            }
            else if(vis.count(t)==0){//如果之前还没有相同地址串的服务机,输出FAIL
                cout<<"FAIL"<<endl;
            }
            else{
                cout<<vis[ad]<<endl;//否则就是可以连接,输出连接编号
            }
        }
    }
}