CSP-2021 T3 网络连接 题解

Zirnc

2021-11-01 13:50:07

Solution

我爱大模拟! 其实这道题就是细心一点就能过,考场上给的大样例非常友好,我就是靠它一个一个找出错误然后修改的...最后没想到满分了 一些关键点: - 除了数字、`.` 和 `:` 以外的字符 - `.` 和 `:` 的出现顺序和次数 - 数字的数量 - 数字有没有前导零 - 数字有没有越界 - ...... 解决方案: - 遍历一遍判断 - 用两个变量记录出现次数,用一个大小为 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; } ```