{ }codelper
定义函数拼接构建字符串64 位整数P0200

用韩文读数

像支票上写的金额那样,生成把一个非负整数用韩文(谚文)读出来的字符串。
数字 1 到 9 依次读作 일、이、삼、사、오、육、칠、팔、구。
0 读作 "영"。
不是 0 的数按下面的规则读,读的过程中不写 "영"。
先从右端起每四位分成一组。
从右往左依次是没有单位的组、만 组、억 组、조 组。
一组(1 到 9999)按千位、百位、十位、个位的顺序读。
在千位、百位、十位上,数字为 0 就跳过该位,为 1 只写 "천"、"백"、"십",为 2 到 9 就在数字名称后加上 "천"、"백"、"십"。
个位为 0 就跳过,否则只写数字名称。
值为 0 的组连同单位整个跳过。
值不为 0 的组,读完后加上单位(조、억、만)。
但是 만 组的值为 1 时,只写 "만" 而不写 "일만"。
억 组和 조 组的值为 1 时写 "일억"、"일조"。
从左起把所有组不加空格地连在一起。
第一行给出数的个数 n,接下来 n 行每行给出一个数。
对每个数输出一行读出来的字符串。
试着写一个读 1 到 9999 的函数,再写一个在每组重复调用它、读出整个数的函数。

输入
1 ≤ n ≤ 1,000,0 ≤ 数 ≤ 999,999,999,999,999
输出
n 行:每个数的韩文读法
样例 1 · stdin
7
0
11
10000
10001
110000
100000000
1234567890123
stdout
영
십일
만
만일
십일만
일억
일조이천삼백사십오억육천칠백팔십구만백이십삼
main.py
输入(stdin)

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

$ 就绪

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

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

同一规则要用四次(조、억、만 和其余部分),所以关键是写一个读 1 到 9999 的函数,在每组重新调用。
定义函数的方法:Python def read_group(n):,JS function readGroup(n),TS 要写类型,如 function readGroup(n: number): string,Java、C# 用类里的 static 方法,C 的函数必须在使用之前出现(否则要写原型声明)。
Craykon 不用关键字,写成 readGroup(n) { … 返回 out; },函数里也能读外面的数字名称列表。
字符串拼接也不同:Python、JS、Craykon 用 +,Java、C# 用 StringBuilder,C++ 用 std::string 的 +=,C 用 strcat 拼接字节,而一个韩文字在 UTF-8 中占 3 字节,缓冲区要留足。
999 万亿超过 int(约 21 亿),所以 Java、C# 用 long,C、C++ 用 long long 读入。
JS、TS、Craykon 的数在 2^53(约 9,007 万亿)以内整数是精确的,999 万亿没问题;商用 Python //、JS Math.floor、Craykon 数学.商 求得。
六个陷阱:① 读出 십、백、천 前面的 1,10 会变成 "일십",100 变成 "일백"。
② 만 组为 1 时是 "만" 而不是 "일만"(10001 是 "만일")。
③ 但不能把省略 1 的规则也用在 억、조 上。
1억 是 "일억",1조 是 "일조"。
④ 给值为 0 的组加上单位,1억 会变成 "일억만"。
⑤ 0 的每一组都是空的,会输出空行,所以要单独返回 "영"。
⑥ 用 Java Integer.parseInt 读入,从 2147483648 起会抛异常。

Pythonmain.py · 33 行
DIGIT = ["", "일", "이", "삼", "사", "오", "육", "칠", "팔", "구"]  def read_group(n):    """1 ~ 9999를 읽는다. 십·백·천 앞의 1은 읽지 않는다(십, 백, 천)"""    out = ""    for unit, size in (("천", 1000), ("백", 100), ("십", 10)):        d = n // size % 10        if d == 1:            out += unit        elif d > 1:            out += DIGIT[d] + unit    return out + DIGIT[n % 10]  def read_number(x):    if x == 0:        return "영"    out = ""    for unit, size in (("조", 10 ** 12), ("억", 10 ** 8), ("만", 10 ** 4), ("", 1)):        g = x // size % 10000        if g == 0:            continue  # 빈 묶음은 단위까지 통째로 건너뛴다        if g == 1 and unit == "만":            out += "만"  # 10000은 "일만"이 아니라 "만"        else:            out += read_group(g) + unit    return out  n = int(input())for _ in range(n):    print(read_number(int(input())))
JavaScriptmain.js · 31 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const DIGIT = ["", "일", "이", "삼", "사", "오", "육", "칠", "팔", "구"]; // 1 ~ 9999를 읽는다. 십·백·천 앞의 1은 읽지 않는다(십, 백, 천)function readGroup(n) {  let out = "";  for (const [unit, size] of [["천", 1000], ["백", 100], ["십", 10]]) {    const d = Math.floor(n / size) % 10;    if (d === 1) out += unit;    else if (d > 1) out += DIGIT[d] + unit;  }  return out + DIGIT[n % 10];} // 999조까지는 2^53보다 작아서 Number로도 정확하다function readNumber(x) {  if (x === 0) return "영";  let out = "";  for (const [unit, size] of [["조", 1e12], ["억", 1e8], ["만", 1e4], ["", 1]]) {    const g = Math.floor(x / size) % 10000;    if (g === 0) continue; // 빈 묶음은 단위까지 통째로 건너뛴다    if (g === 1 && unit === "만") out += "만"; // 10000은 "일만"이 아니라 "만"    else out += readGroup(g) + unit;  }  return out;} const n = Number(lines[0]);const out = [];for (let i = 1; i <= n; i++) out.push(readNumber(Number(lines[i])));console.log(out.join("\n"));
TypeScriptmain.ts · 35 行
import { readFileSync } from "node:fs"; const lines: string[] = readFileSync(0, "utf8").split("\n");const DIGIT: string[] = ["", "일", "이", "삼", "사", "오", "육", "칠", "팔", "구"]; // 1 ~ 9999를 읽는다. 십·백·천 앞의 1은 읽지 않는다(십, 백, 천)function readGroup(n: number): string {  let out = "";  const places: [string, number][] = [["천", 1000], ["백", 100], ["십", 10]];  for (const [unit, size] of places) {    const d = Math.floor(n / size) % 10;    if (d === 1) out += unit;    else if (d > 1) out += DIGIT[d] + unit;  }  return out + DIGIT[n % 10];} // 999조까지는 2^53보다 작아서 number로도 정확하다function readNumber(x: number): string {  if (x === 0) return "영";  let out = "";  const groups: [string, number][] = [["조", 1e12], ["억", 1e8], ["만", 1e4], ["", 1]];  for (const [unit, size] of groups) {    const g = Math.floor(x / size) % 10000;    if (g === 0) continue; // 빈 묶음은 단위까지 통째로 건너뛴다    if (g === 1 && unit === "만") out += "만"; // 10000은 "일만"이 아니라 "만"    else out += readGroup(g) + unit;  }  return out;} const n = Number(lines[0]);const out: string[] = [];for (let i = 1; i <= n; i++) out.push(readNumber(Number(lines[i])));console.log(out.join("\n"));
JavaMain.java · 43 行
import java.io.*; public class Main {    static final String[] DIGIT = {"", "일", "이", "삼", "사", "오", "육", "칠", "팔", "구"};    static final String[] PLACE = {"천", "백", "십"};    static final int[] PLACE_SIZE = {1000, 100, 10};    static final String[] GROUP = {"조", "억", "만", ""};    static final long[] GROUP_SIZE = {1_000_000_000_000L, 100_000_000L, 10_000L, 1L};     // 1 ~ 9999를 읽는다. 십·백·천 앞의 1은 읽지 않는다(십, 백, 천)    static String readGroup(int n) {        StringBuilder sb = new StringBuilder();        for (int i = 0; i < 3; i++) {            int d = n / PLACE_SIZE[i] % 10;            if (d == 1) sb.append(PLACE[i]);            else if (d > 1) sb.append(DIGIT[d]).append(PLACE[i]);        }        return sb.append(DIGIT[n % 10]).toString();    }     // 999조는 int(약 21억)를 넘으니 long으로 받는다    static String readNumber(long x) {        if (x == 0) return "영";        StringBuilder sb = new StringBuilder();        for (int i = 0; i < 4; i++) {            int g = (int) (x / GROUP_SIZE[i] % 10000);            if (g == 0) continue; // 빈 묶음은 단위까지 통째로 건너뛴다            if (g == 1 && GROUP[i].equals("만")) sb.append("만"); // 10000은 "일만"이 아니라 "만"            else sb.append(readGroup(g)).append(GROUP[i]);        }        return sb.toString();    }     public static void main(String[] args) throws IOException {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(br.readLine().trim());        StringBuilder out = new StringBuilder();        for (int i = 0; i < n; i++) {            out.append(readNumber(Long.parseLong(br.readLine().trim()))).append('\n');        }        System.out.print(out);    }}
C#Main.cs · 48 行
using System;using System.Text; class Program{    static readonly string[] Digit = { "", "일", "이", "삼", "사", "오", "육", "칠", "팔", "구" };    static readonly (string Unit, int Size)[] Places = { ("천", 1000), ("백", 100), ("십", 10) };    static readonly (string Unit, long Size)[] Groups = { ("조", 1_000_000_000_000L), ("억", 100_000_000L), ("만", 10_000L), ("", 1L) };     // 1 ~ 9999를 읽는다. 십·백·천 앞의 1은 읽지 않는다(십, 백, 천)    static string ReadGroup(int n)    {        var sb = new StringBuilder();        foreach (var (unit, size) in Places)        {            int d = n / size % 10;            if (d == 1) sb.Append(unit);            else if (d > 1) sb.Append(Digit[d]).Append(unit);        }        return sb.Append(Digit[n % 10]).ToString();    }     // 999조는 int(약 21억)를 넘으니 long으로 받는다    static string ReadNumber(long x)    {        if (x == 0) return "영";        var sb = new StringBuilder();        foreach (var (unit, size) in Groups)        {            int g = (int)(x / size % 10000);            if (g == 0) continue; // 빈 묶음은 단위까지 통째로 건너뛴다            if (g == 1 && unit == "만") sb.Append("만"); // 10000은 "일만"이 아니라 "만"            else sb.Append(ReadGroup(g)).Append(unit);        }        return sb.ToString();    }     static void Main()    {        int n = int.Parse(Console.ReadLine()!.Trim());        var output = new StringBuilder();        for (int i = 0; i < n; i++)        {            output.Append(ReadNumber(long.Parse(Console.ReadLine()!.Trim()))).Append('\n');        }        Console.Write(output);    }}
C++main.cpp · 43 行
#include <array>#include <iostream>#include <string>#include <utility> const std::array<std::string, 10> DIGIT = {"", "일", "이", "삼", "사", "오", "육", "칠", "팔", "구"}; // 1 ~ 9999를 읽는다. 십·백·천 앞의 1은 읽지 않는다(십, 백, 천)std::string readGroup(int n) {    const std::array<std::pair<std::string, int>, 3> places = {{{"천", 1000}, {"백", 100}, {"십", 10}}};    std::string out;    for (const auto& [unit, size] : places) {        int d = n / size % 10;        if (d == 1) out += unit;        else if (d > 1) out += DIGIT[d] + unit;    }    return out + DIGIT[n % 10];} // 999조는 int(약 21억)를 넘으니 long long으로 받는다std::string readNumber(long long x) {    if (x == 0) return "영";    const std::array<std::pair<std::string, long long>, 4> groups = {{{"조", 1000000000000LL}, {"억", 100000000LL}, {"만", 10000LL}, {"", 1LL}}};    std::string out;    for (const auto& [unit, size] : groups) {        int g = static_cast<int>(x / size % 10000);        if (g == 0) continue; // 빈 묶음은 단위까지 통째로 건너뛴다        if (g == 1 && unit == "만") out += "만"; // 10000은 "일만"이 아니라 "만"        else out += readGroup(g) + unit;    }    return out;} int main() {    std::ios::sync_with_stdio(false);    int n;    long long x;    std::cin >> n;    for (int i = 0; i < n; i++) {        std::cin >> x;        std::cout << readNumber(x) << "\n";    }}
Cmain.c · 55 行
#include <stdio.h>#include <string.h> // 한글 한 글자는 UTF-8로 3바이트다. 문자열은 그냥 바이트로 이어 붙인다static const char *DIGIT[] = {"", "일", "이", "삼", "사", "오", "육", "칠", "팔", "구"};static const char *PLACE[] = {"천", "백", "십"};static const int PLACE_SIZE[] = {1000, 100, 10};static const char *GROUP[] = {"조", "억", "만", ""};static const long long GROUP_SIZE[] = {1000000000000LL, 100000000LL, 10000LL, 1LL}; // 1 ~ 9999를 읽어 out 끝에 붙인다. 십·백·천 앞의 1은 읽지 않는다(십, 백, 천)void read_group(int n, char *out) {    for (int i = 0; i < 3; i++) {        int d = n / PLACE_SIZE[i] % 10;        if (d == 1) {            strcat(out, PLACE[i]);        } else if (d > 1) {            strcat(out, DIGIT[d]);            strcat(out, PLACE[i]);        }    }    strcat(out, DIGIT[n % 10]);} // 999조는 int(약 21억)를 넘으니 long long으로 받는다void read_number(long long x, char *out) {    out[0] = '\0';    if (x == 0) {        strcpy(out, "영");        return;    }    for (int i = 0; i < 4; i++) {        int g = (int)(x / GROUP_SIZE[i] % 10000);        if (g == 0) continue; // 빈 묶음은 단위까지 통째로 건너뛴다        if (g == 1 && i == 2) {            strcat(out, "만"); // 10000은 "일만"이 아니라 "만"        } else {            read_group(g, out);            strcat(out, GROUP[i]);        }    }} int main(void) {    int n;    long long x;    char out[256]; // 가장 긴 것도 한글 40글자 남짓(120바이트)    scanf("%d", &n);    for (int i = 0; i < n; i++) {        scanf("%lld", &x);        read_number(x, out);        puts(out);    }    return 0;}
Craykonmain.cray · 57 行
숫자이름 = ["", "일", "이", "삼", "사", "오", "육", "칠", "팔", "구"]; // 1 ~ 9999를 읽는다. 십·백·천 앞의 1은 읽지 않는다(십, 백, 천)네자리읽기(n){    out = "";    자리이름 = ["천", "백", "십"];    자리크기 = [1000, 100, 10];    循环 (i = 0; i < 3; i++)    {        d = 数学.商(n, 자리크기[i]) % 10;        如果 (d == 1)        {            out = out + 자리이름[i];        }        否则 如果 (d > 1)        {            out = out + 숫자이름[d] + 자리이름[i];        }    }    返回 out + 숫자이름[n % 10];} // 999조까지는 2^53보다 작아서 수가 정확하다수읽기(x){    如果 (x == 0)    {        返回 "영";    }    out = "";    묶음이름 = ["조", "억", "만", ""];    묶음크기 = [1000000000000, 100000000, 10000, 1];    循环 (i = 0; i < 4; i++)    {        g = 数学.商(x, 묶음크기[i]) % 10000;        如果 (g == 0)        {            继续; // 빈 묶음은 단위까지 통째로 건너뛴다        }        如果 (g == 1 && 묶음이름[i] == "만")        {            out = out + "만"; // 10000은 "일만"이 아니라 "만"        }        否则        {            out = out + 네자리읽기(g) + 묶음이름[i];        }    }    返回 out;} n = 控制台.读行().转数字();循环 (k = 0; k < n; k++){    控制台.输出(수읽기(控制台.读行().转数字()));}