TB椰程 TypeBuddy 打字搭子

2021 网络连接 · 方案二 读入后回拼校验

CSP-J 标程 · 复赛真题 · 代码 · cpp · 难度 3/5 · 共 1469 字

拼回去和原串不一样就是非法

  • 2021
  • 字符串

正文

// CSP-J 2021 复赛 T3 · 网络连接(方案二)
// 原题:https://oj.yecheng.tv/p/CSPJ2021C
//
// 方案二 · sscanf 读入 + 回拼校验(写法更短)
// 巧妙的一步:先用 sscanf 按 "%d.%d.%d.%d:%d" 读出五个数,
// 再用 sprintf 把这五个数原样拼回一个字符串,和原串比一比。
// 只要原串里有任何多余前导零(比如 088)、多余分隔符或者多余尾巴,
// 拼回来的串就一定和原串不一样,直接判非法。
// 剩下的就是范围检查:a~d 不超过 255,e 不超过 65535。
// 注意:sscanf 的返回值必须是 5,否则说明格式没对上(例如 192:168:0:1.233)。

#include <bits/stdc++.h>
using namespace std;

bool check(const string& s) {
    int a, b, c, d, e;
    if (sscanf(s.c_str(), "%d.%d.%d.%d:%d", &a, &b, &c, &d, &e) != 5) return false;
    char buf[64];
    sprintf(buf, "%d.%d.%d.%d:%d", a, b, c, d, e);
    if (string(buf) != s) return false;         // 拼回去不一样 = 有多余前导零或杂字符
    if (a < 0 || a > 255 || b < 0 || b > 255) return false;
    if (c < 0 || c > 255 || d < 0 || d > 255) return false;
    if (e < 0 || e > 65535) return false;
    return true;
}

int main() {
    freopen("network.in", "r", stdin);
    freopen("network.out", "w", stdout);

    int n;
    cin >> n;
    map<string, int> server;
    for (int i = 1; i <= n; i++) {
        string op, ad;
        cin >> op >> ad;
        if (!check(ad)) {
            cout << "ERR\n";
        } else if (op == "Server") {
            if (server.count(ad)) cout << "FAIL\n";
            else {
                server[ad] = i;
                cout << "OK\n";
            }
        } else {
            if (server.count(ad)) cout << server[ad] << "\n";
            else cout << "FAIL\n";
        }
    }
    return 0;
}

CSP-J 标程 · 复赛真题的其它内容

打字首页 · 词库画廊 · 编程打字 · 指法入门 · 天梯榜 · 数据分析 · 班级课堂 · 关于我们
椰程 TypeBuddy 打字搭子 —— 键盘指法练习 · 单词记忆 · 班级课堂 · 在线 PK