{ }codelper
读取一行字符P0161

货架标签校验字符

仓库货架标签上写着由英文字母和数字组成的代码。
标签是手抄的,所以可能混有小写字母,空格和 '-' 也可能出现在任何位置。
第一行给出标签数 n,接下来 n 行每行给出一个标签。
对每个标签,去掉所有空格和 '-',把小写字母改成大写,得到代码。
代码的每个字符有一个值:'0'~'9' 为 0~9,'A'~'Z' 为 10~35。
把代码中从左数第 i 个(从 1 开始数)字符的值乘以 i,全部相加,设这个和除以 36 的余数为 r。
校验字符在 r 为 0~9 时是数字 '0'~'9',r 为 10~35 时是 'A'~'Z'(10 是 'A',35 是 'Z')。
对每个标签,把代码、'-'、校验字符连在一起输出一行。

输入
第一行 n(1 ≤ n ≤ 1000)。
接下来 n 行的标签不含换行为 1~80 个字符,只由英文大小写字母、数字、空格和 '-' 组成。
行首行尾可能有空格,每个标签至少有一个字母或数字
输出
n 行,每行 "代码-校验字符"
样例 1 · stdin
3
sh-04 b
  q7-X  
9
stdout
SH04B-P
Q7X-V
9-9
main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 8 种语言题解

比较两件事。
① 整行读取含空格的行:Python input()・sys.stdin.readline(),JS・TS 一次读完再 split("\n"),Java BufferedReader.readLine(),C# Console.ReadLine(),C fgets,C++ std::getline,Craykon 控制台.读行()。
C++ cin >> s、Java Scanner.next()、C scanf("%s") 遇到空格就断开,会把 sh-04 b 读成两段。
数字和整行混着读也有陷阱:C scanf("%d")、C++ cin >> n、Java Scanner.nextInt() 会留下第一行末尾的换行,紧接着的 fgets・getline・nextLine() 就读到一个空行。
把第一行也按行读入再转成数字就安全了。
② 字符与数字互转:C・C++・Java・C# 的 char 本身是数,c - '0'、c - 'A' + 10 直接得到值。
反过来把数变回字符时,'A' + r - 10 是 int,直接交给 Java StringBuilder.append、C# StringBuilder.Append 或 C++ std::cout <<,追加的是 25 而不是 P。
要用 (char)(C++ 用 static_cast<char>)转换。
C 的 printf("%c", ...) 接收 int 并按字符输出。
Python・JS・TS・Craykon 没有字符类型,要经过编码:Python ord・chr(或 int(c, 36) 直接得到 0~35),JS・TS charCodeAt・String.fromCharCode,Craykon 字符.编码・字符.从编码。
JS 里 "7" - "0" 是 7,但对字母不适用:对所有字符都用 charCodeAt(0) - 48,'B' 会变成 18 而不是 11。
另外不先转成大写的话,'b' - 'A' + 10 是 43。

Pythonmain.py · 22 行
import sys  def value(c):    # '0'~'9' → 0~9, 'A'~'Z' → 10~35 (글자 코드의 차이로 계산)    if c.isdigit():        return ord(c) - ord("0")    return ord(c) - ord("A") + 10  def check_char(r):    if r < 10:        return chr(ord("0") + r)    return chr(ord("A") + r - 10)  n = int(sys.stdin.readline())for _ in range(n):    line = sys.stdin.readline().rstrip("\n")  # 빈칸이 든 한 줄을 통째로    code = "".join(c.upper() for c in line if c not in " -")    total = sum(value(c) * i for i, c in enumerate(code, 1))    print(f"{code}-{check_char(total % 36)}")
JavaScriptmain.js · 20 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);const ZERO = "0".charCodeAt(0);const A = "A".charCodeAt(0); // '0'~'9' → 0~9, 'A'~'Z' → 10~35const value = (c) => {  const k = c.charCodeAt(0);  return k <= "9".charCodeAt(0) ? k - ZERO : k - A + 10;};const checkChar = (r) => String.fromCharCode(r < 10 ? ZERO + r : A + r - 10); const out = [];for (let i = 1; i <= n; i++) {  const code = lines[i].replace(/[ -]/g, "").toUpperCase();  let total = 0;  for (let j = 0; j < code.length; j++) total += value(code[j]) * (j + 1);  out.push(`${code}-${checkChar(total % 36)}`);}console.log(out.join("\n"));
TypeScriptmain.ts · 23 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const n: number = Number(lines[0]);const ZERO: number = "0".charCodeAt(0);const A: number = "A".charCodeAt(0); // '0'~'9' → 0~9, 'A'~'Z' → 10~35function value(c: string): number {  const k: number = c.charCodeAt(0);  return k <= "9".charCodeAt(0) ? k - ZERO : k - A + 10;}function checkChar(r: number): string {  return String.fromCharCode(r < 10 ? ZERO + r : A + r - 10);} const out: string[] = [];for (let i = 1; i <= n; i++) {  const code: string = lines[i].replace(/[ -]/g, "").toUpperCase();  let total = 0;  for (let j = 0; j < code.length; j++) total += value(code[j]) * (j + 1);  out.push(`${code}-${checkChar(total % 36)}`);}console.log(out.join("\n"));
JavaMain.java · 30 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader; public class Main {    // '0'~'9' → 0~9, 'A'~'Z' → 10~35 (char는 수처럼 뺄 수 있다)    static int value(char c) {        return Character.isDigit(c) ? c - '0' : c - 'A' + 10;    }     static char checkChar(int r) {        return r < 10 ? (char) ('0' + r) : (char) ('A' + r - 10); // int → char로 되돌린다    }     public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(in.readLine().trim());        StringBuilder out = new StringBuilder();        for (int i = 0; i < n; i++) {            String line = in.readLine(); // 빈칸이 든 한 줄을 통째로            StringBuilder code = new StringBuilder();            for (char c : line.toCharArray())                if (c != ' ' && c != '-') code.append(Character.toUpperCase(c));            int total = 0;            for (int j = 0; j < code.length(); j++) total += value(code.charAt(j)) * (j + 1);            out.append(code).append('-').append(checkChar(total % 36)).append('\n');        }        System.out.print(out);    }}
C#Main.cs · 27 行
using System;using System.Text; class Program{    // '0'~'9' → 0~9, 'A'~'Z' → 10~35 (char끼리 빼면 int)    static int Value(char c) => char.IsDigit(c) ? c - '0' : c - 'A' + 10;     static char CheckChar(int r) => r < 10 ? (char)('0' + r) : (char)('A' + r - 10);     static void Main()    {        int n = int.Parse(Console.ReadLine());        var out_ = new StringBuilder();        for (int i = 0; i < n; i++)        {            string line = Console.ReadLine(); // 빈칸이 든 한 줄을 통째로            var code = new StringBuilder();            foreach (char c in line)                if (c != ' ' && c != '-') code.Append(char.ToUpperInvariant(c));            int total = 0;            for (int j = 0; j < code.Length; j++) total += Value(code[j]) * (j + 1);            out_.Append(code).Append('-').Append(CheckChar(total % 36)).Append('\n');        }        Console.Write(out_);    }}
C++main.cpp · 27 行
#include <cctype>#include <iostream>#include <string> // '0'~'9' → 0~9, 'A'~'Z' → 10~35int value(char c) {    return std::isdigit(static_cast<unsigned char>(c)) ? c - '0' : c - 'A' + 10;} int main() {    std::string line;    std::getline(std::cin, line);    int n = std::stoi(line); // cin >> n 뒤에 getline을 쓰면 남은 줄 끝을 빈 줄로 읽는다    std::string out;    for (int i = 0; i < n; i++) {        std::getline(std::cin, line); // 빈칸이 든 한 줄을 통째로        std::string code;        for (char c : line)            if (c != ' ' && c != '-') code += static_cast<char>(std::toupper(static_cast<unsigned char>(c)));        int total = 0;        for (std::size_t j = 0; j < code.size(); j++) total += value(code[j]) * static_cast<int>(j + 1);        int r = total % 36;        char check = static_cast<char>(r < 10 ? '0' + r : 'A' + r - 10); // int → char        out += code + '-' + check + '\n';    }    std::cout << out;}
Cmain.c · 26 行
#include <ctype.h>#include <stdio.h>#include <stdlib.h> /* '0'~'9' → 0~9, 'A'~'Z' → 10~35: C의 char는 작은 정수라 그대로 뺀다 */static int value(char c) {    return isdigit((unsigned char)c) ? c - '0' : c - 'A' + 10;} int main(void) {    char line[128], code[128];    fgets(line, sizeof line, stdin);    int n = atoi(line); /* scanf("%d")를 쓰면 줄 끝 '\n'이 남아 다음 fgets가 빈 줄을 읽는다 */    for (int i = 0; i < n; i++) {        fgets(line, sizeof line, stdin);        int len = 0;        for (char *p = line; *p && *p != '\n'; p++)            if (*p != ' ' && *p != '-') code[len++] = (char)toupper((unsigned char)*p);        code[len] = '\0';        int total = 0;        for (int j = 0; j < len; j++) total += value(code[j]) * (j + 1);        int r = total % 36;        printf("%s-%c\n", code, r < 10 ? '0' + r : 'A' + r - 10);    }    return 0;}
Craykonmain.cray · 39 行
// '0'~'9' → 0~9, 'A'~'Z' → 10~35값(c){    k = 字符.编码(c);    如果 (k <= 字符.编码("9"))    {        返回 k - 字符.编码("0");    }    返回 k - 字符.编码("A") + 10;} 확인글자(r){    如果 (r < 10)    {        返回 字符.从编码(字符.编码("0") + r);    }    返回 字符.从编码(字符.编码("A") + r - 10);} n = 控制台.读行().转数字();循环 (i = 0; i < n; i++){    줄 = 控制台.读行().大写();    코드 = "";    遍历 (c 在 줄)    {        如果 (c != " " && c != "-")        {            코드 = 코드 + c;        }    }    합 = 0;    循环 (j = 0; j < 코드.长度; j++)    {        합 = 합 + 값(코드[j]) * (j + 1);    }    控制台.输出(코드 + "-" + 확인글자(합 % 36));}