1082 Read Number in Chinese (25 分) 全网最细 题目详解 翻译 完整代码 PAT甲级真题解析

本题稍难,如果没有思路,请顺序认真阅读本文!(全网最全最详细题目解析

预备知识:

C/C++string头文件使用方法——PAT常用知识点(一)

  1. < string >头文件函数:substr(pos, len) 返回从pos号位开始,长度为len的子串。

题目翻译:

给定一个不超过9位数的整数,你需要用传统中文方式将它读取。如果是负数,首先输出 “负” 。例如,“-123456789” 读作 “一亿两千三百四十五万六千七百八十九”。注意:根据中文数字的读法,零(0)必须要被正确的处理。例如,“100800” 是读作 “一十万零八百”。

难点单词:

supposed to 应该
according to 据 ; 按 ; 依照 ; 按照 ; 根据

输入格式:

每个输入文件包含一个测试用例,它将给出一个不超过9位的整数。

输出格式:

对于每个测试用例,在一行中打印数字的中文阅读方式。字符之间用空格隔开,行尾不能有多余的空格。

输入样例(一):

-123456789

输出样例(一):

Fu yi Yi er Qian san Bai si Shi wu Wan liu Qian qi Bai ba Shi jiu

输入样例(二):

100800

输出样例(二):

yi Shi Wan ling ba Bai


题目解析:

字符串处理题,较难,有很多分支逻辑需要处理。

首先可以自己列举一些输出结果,找找所有数的共同点。可以发现:

  1. 除个位外,所有非零位在输出的时候都是先输出大写数字(如 “五” )再输出大写位(如 “千” )的形式;
    (非零位的数字和位同时输出)
  2. 若当前剩余数字为个数为4的倍数位,不论当前位是否为零,都要输出当前位单位(如 “万”、“亿” );
    (每隔4位必定输出一个位单位)
  3. 若万级上存在连续4个0,不能读万只能读零,如 “1,0000,2345” ,读作 “一亿零两千三百四十五”。(此种情况需要结合情况2进行特殊处理)
  4. 两个以上连续的0,最多只能读一次,如 “1002” ,读作 “一千零二”;
  5. 若某一个0位于万级,需要读出来,如 “10,0005” ,读作 “十万零五”;

逻辑梳理:

逻辑梳理非常重要!请务必先自己梳理一遍完整流程再看解析和代码!

若输入数据为0的话需要进行特判。当输入的数据不为0时:

  1. 若有符号,首先需要输出符号,然后将符号从数串中删除(方便后续处理);

  2. 从第一位数(最高位)开始检查。每一位数都会出现两种情况:①当前位非0 ②当前位为0(显然最高位不会为0);

    1. 若当前位非0
      a. 若当前位的前一位(或几位)为0,不论前面有几个0(显然这里需要一个变量来记录连续0的个数),都只用输出一个0,然后输出当前位的大写数字和大写位。

      b. 若当前位的前一位非0,直接输出当前位的大写数和大写位。

    2. 若当前位为0,累加连续0的个数,然后判断当前0的个数是否达到了上面分析的那个特殊条件「若万级上存在连续4个0,不能读万,只能读零」,若成立,则输出当前位的大写,然后将连续0个数重制为0。

看到这里,你可能有点懵。没关系,自己在纸上多分析一下处理流程。

建议先根据自己对上面的理解分析写出自己的代码再往下看~

参考代码:

#include <iostream>
#include <cstdio>
using namespace std;

int main() {
    string units[9] = {"", " Shi", " Bai", " Qian", " Wan", " Shi", " Bai", " Qian", " Yi"};
    string nums[10] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};
    string number;
    cin >> number;
    if ( number == "0" ) { // 输入为0特判
        cout << "ling" << endl;
    }
	else { // 输入不为0
        if ( number[0] == '-' ) { // 先输出符号
            cout << "Fu ";
            number = number.substr(1); // 输出后从字符串中删除
        }
        int len = number.length(); // 数字的个数
        int gap = 0; // 两个非0数字间0的个数
        for (int i = 1; i <= len; i++) {
            int n = number[i-1] - '0';
            if(n != 0) {
                if(gap) {
                    cout << " ling";
                    gap = 0;
                }
                if(i > 1) cout << " ";
                cout << nums[n] << units[len-i];
            } else {
                gap++;
                // 若未处理的数字个数为4的倍数且非连续4个零
                if((len-i)%4 == 0 && gap%4 != 0) {
                    cout << units[len-i];
                    gap = 0;
                }
            }
        }
    }
    return 0;
}

全部通过
在这里插入图片描述
我知道,本道题可能会有点难。
但别灰心!要知道我都分析了两个多小时才弄明白【哭笑
一起加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值