CSP-2021 T3 网络连接 题解
Zirnc
2021-11-01 13:50:07
我爱大模拟!
其实这道题就是细心一点就能过,考场上给的大样例非常友好,我就是靠它一个一个找出错误然后修改的...最后没想到满分了
一些关键点:
- 除了数字、`.` 和 `:` 以外的字符
- `.` 和 `:` 的出现顺序和次数
- 数字的数量
- 数字有没有前导零
- 数字有没有越界
- ......
解决方案:
- 遍历一遍判断
- 用两个变量记录出现次数,用一个大小为 3 的数组记录每个 `.` 出现的位置
- 。。。
- 代码中 `checkPrevZero()`
- 还没将字符串转成数字前可以先判断这段数字长度是否大于 3 或 5,转化成数字之后再细化判断是否大于 255 或 65535,可以在整个过程中避免使用 long long 防止爆炸(这个坑似乎也是大样例告诉我的)。
可以使用一些字符串库函数来简化代码。
下面奉上原汁原味的考场代码,具体注释都在里面:
```cpp
#include <bits/stdc++.h>
using namespace std;
int n;
// 判断前导零
bool checkPrevZero(const string number) {
// 单独一个 0 是不算非法的。
if (number.length() > 1 && number[0] == '0') return true;
return false;
}
// string 转 int
int strToInt(const string number) {
int t = 0;
for (int i = 0; i < number.length(); i++) {
t *= 10;
t += number[i]-'0';
}
return t;
}
bool check(const string addr) {
int cntDot = 0, cntMao = 0; // 点的出现次数和冒号的出现次数
int dotIdx[3], maoIdx; // 点出现的位置和冒号出现的位置
if (!(addr[0] >= '0' && addr[0] <= '9') || !(addr[addr.length()-1] >= '0' && addr[addr.length()-1] <= '9')) return false;
for (int i = 0; i < addr.length(); i++) {
if (addr[i] == '.') {
if (cntDot > 2) return false; // 多于三个点
if (!(addr[i-1] >= '0' && addr[i-1] <= '9')) return false;
cntDot++;
dotIdx[cntDot-1] = i;
} else if (addr[i] == ':') {
if (cntMao > 1) return false; // 多于一个冒号
if (!(addr[i-1] >= '0' && addr[i-1] <= '9')) return false;
cntMao++;
maoIdx = i;
} else if (!(addr[i] >= '0' && addr[i] <= '9')) { // 啥也不是
return false;
}
}
if (!(cntDot == 3 && cntMao == 1)) return false; // 检查点和冒号的数量
if (maoIdx < dotIdx[2]) return false; // 如果冒号的位置在某一个点前面
// 分离出五个数字
string n1 = addr.substr(0, dotIdx[0]),
n2 = addr.substr(dotIdx[0]+1, dotIdx[1]-dotIdx[0]-1),
n3 = addr.substr(dotIdx[1]+1, dotIdx[2]-dotIdx[1]-1),
n4 = addr.substr(dotIdx[2]+1, maoIdx-dotIdx[2]-1),
n5 = addr.substr(maoIdx+1, addr.length()-maoIdx-1);
if (checkPrevZero(n1) || checkPrevZero(n2) || checkPrevZero(n3) || checkPrevZero(n4) || checkPrevZero(n5)) return false; // 判断前导零
if (n1.length() > 3 || n2.length() > 3 || n3.length() > 3 || n4.length() > 3 || n5.length() > 5) return false; // 判断越界
int a = strToInt(n1), b = strToInt(n2), c = strToInt(n3), d = strToInt(n4), e = strToInt(n5);
if (a > 255 || b > 255 || c > 255 || d > 255 || e > 65535) return false; // 判断越界
return true;
}
int serversNum = 0;
map<string, int> servers;
int main()
{
cin >> n;
string op, ad;
for (int i = 0; i < n; i++) {
cin >> op >> ad;
if (!check(ad)) {
cout << "ERR\n";
continue;
}
if (op == "Server") {
if (servers[ad] != 0) {
cout << "FAIL\n";
continue;
}
servers[ad] = i+1;
cout << "OK\n";
} else if (op == "Client") {
if (servers[ad] == 0) {
cout << "FAIL\n";
continue;
}
cout << servers[ad] << endl;
}
}
return 0;
}
```