题意梳理
核心规则
合法地址格式强制要求:严格形如 a.b.c:d:e 拆分结构是a.b.c.d:e,必须恰好 3 个. ,1 个: ;
数值范围:0<=a,b,c,d<=255,0<=e<=65535
禁止多余前导零(如099、01非法,单独0合法)
Server 逻辑
地址非法 → 输出ERR
地址合法且未被之前 Server 占用 → 存入map<地址串,编号>,输出OK
地址合法但已存在同地址 Server → 输出FAIL
Server 逻辑
地址非法 → 输出ERR
地址合法且未被之前 Server 占用 → 存入map<地址串,编号>,输出OK
地址合法但已存在同地址 Server → 输出FAIL
地址处理
普通写法要手动分割字符串、逐段遍历判断前导零,代码冗长易错;
此时可以用两次格式化函数一步到位:(绝对不是因为懒)
sscanf按%d.%d.%d.%d:%d读取 5 个整数:
若格式不对,读取数量≠5 直接判非法;顺便完成数值范围校验
sprintf把读取到的合法整数重新格式化拼接成标准字符串:
整数格式化自动去除前导零!比如原串192.168.001.1:80,读整数再拼接会变成192.168.1.1:80
直接对比原字符串和重拼接后的字符串,不一致就说明原串有前导零,直接非法!
完整AC代码
#include <bits/stdc++.h>
using namespace std;
map<string,int> server;//地址与编号
bool check(string s)
{
int cnt1=0,cnt2=0;
for(int i=0;i<s.size();i++)
{
if(s[i]=='.') cnt1++;
if(s[i]==':') cnt2++;
}
if(cnt1!=3||cnt2!=1) return false;
int a,b,c,d,e;
if(sscanf(s.c_str(),"%d.%d.%d.%d:%d",&a,&b,&c,&d,&e)!=5) return false;
if(a<0||a>255||b<0||b>255||c<0||c>255||d<0||d>255||e<0||e>65535) return false;
char buf[50];
sprintf(buf,"%d.%d.%d.%d:%d",a,b,c,d,e);
if(s!=string(buf)) return false;//检查前导0。
return true;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
string op,ad;
cin>>op>>ad;
if(check(ad))
{
if(op=="Server")
{
if(server.count(ad))
{
cout<<"FAIL"<<endl;
}
else
{
server[ad]=i;
cout<<"OK"<<endl;
}
}
else
{
if(server.count(ad))
{
cout<<server[ad]<<endl;
}
else
{
cout<<"FAIL"<<endl;
}
}
}
else
{
cout<<"ERR"<<endl;
}
}
return 0;
}
网硕互联帮助中心![打卡信奥刷题(3491)用C++实现信奥题 P10734 [NOISG 2019 Prelim] Experimental Charges-网硕互联帮助中心](https://www.wsisp.com/helps/wp-content/uploads/2026/08/20260805014046-6a72949eaf30f-220x150.png)




评论前必须登录!
注册