【PAT甲级 - C++题解】1082 Read Number in Chinese

✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:PAT题解集合
📝原题地址:题目详情 - 1082 Read Number in Chinese (pintia.cn)
🔑中文翻译:中文读数字
📣专栏定位:为想考甲级PAT的小伙伴整理常考算法题解,祝大家都能取得满分!
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

1082 Read Number in Chinese

给定一个不超过 99 位的整数,你应该用传统的中文方式阅读它.

如果是负数,则先输出 Fu

例如,-123456789 读作 Fu yi Yi er Qian san Bai si Shi wu Wan liu Qian qi Bai ba Shi jiu

注意:零(ling)必须按照中国传统正确处理。

例如,100800 读作 yi Shi Wan ling ba Bai

输入格式

共一行,包含一个不超过 99 位的整数.

输出格式

输出给定数字的中文读法,注意结尾不能有多余空格。

输入样例1:
-123456789
输出样例1:
Fu yi Yi er Qian san Bai si Shi wu Wan liu Qian qi Bai ba Shi jiu
输入样例2:
100800
输出样例2:
yi Shi Wan ling ba Bai
思路

这道题大致的思路是先处理最前面的正负号,然后再将剩余数字进行划分,除了最高位其它分成 4 位一组。例如, 123456789 可以划分成 123456789 三组,然后再分别进行处理。

这道题需要注意的是,正常的数字转换是小写的,而涉及到亿、万、千、百和十的开头都需要大写。另外,这里涉及到了一个 c++ 的函数 stoi ,作用是将字符串类型转换成整数类型。

  1. 先处理负号情况,如果有负号就加入 ans 当中。
  2. 处理数字存在第 9 位的情况。注意,需要先判断第 9 位是否为 0 ,如果为 0 直接跳过不去处理,后面的 5~8 位和 1~4 位同理,例如 100000000 就不需要处理后面 8 位。
  3. 处理数字存在第 5~8 以及 1~4 的情况,处理函数如下:
    1. 先处理前缀 0
    2. 再分别处理千位、百位、十位和个位,因为数字位数不定,所以我们需要额外进行判断。
  4. 判断 flag 是否为 0 ,如果为 0 说明并没有经过步骤 23 的处理,它本身就为 0 ,直接加入 ans 即可。
  5. 如果 ans 最后有空格的话需要去除,否则官网会报格式错误,然后输出结果 ans 即可。
代码
#include<bits/stdc++.h>
using namespace std;

//数字翻译
string nums1[] = { "ling","yi","er","san","si",
                "wu","liu","qi","ba","jiu" };
string nums2[] = { "Qian ","Bai ","Shi ","" };

//为了防止出现格式错误,我们用一个字符串容器来存储答案
string ans = "";	

//处理四位数字
void work(string x)
{
    //先将处理前缀0
    int k = 0;
    while (k < x.size() && x[k] == '0')    k++;
    if (k != 0)    ans += "ling ";
    x = x.substr(k);

    int cnt = 0;	//统计目前遍历到字符串x的第几位,因为可能不是4位数,直接用i访问会越界
    int flag = 0;	//处理数字中间出现0的情况,如1001、101等
    for (int i = 0; i < 4; i++)	//分别处理千位、百位、十位、个位
    {
        if (!stoi(x.substr(cnt))) break;	//如果x当前位置及以后都为0,则直接退出,如1000等
        if (4 - i > x.size())    continue;	//排除x不满足4位数的情况,如111没有千位
        
        //如果x当前位置为0,分情况讨论
        if (x[cnt] == '0') {
            if (!flag)   ans += "ling ";	//如果之前没有输出过0,则输出0
            flag = 1;	//置为1,防止重复输出,如1001中的0只能输出一次
            cnt++;
            continue;
        }
        
        ans += nums1[x[cnt++] - '0'] + " " + nums2[i];
    }
}

int main()
{
    string str;
    cin >> str;

    //先去掉负号的情况
    if (str[0] == '-') {
        ans += "Fu ";
        str = str.substr(1);
    }

    int n = str.size();
    int flag = 0;	//用于判断是否为0的情况
    
    //处理第9位
    if (n == 9 && stoi(str.substr(0, 1))) {
        flag = 1;
        int a = stoi(str.substr(0, 1));
        str = str.substr(1);
        ans += nums1[a] + " Yi ";
    }
    
    //处理第5~8位
    if (n >= 5 && stoi(str.substr(0, str.size() - 4)))
    {
        flag = 1;
        work(str.substr(0, str.size() - 4));
        str = str.substr(str.size() - 4);
        ans += "Wan ";
    }
    
    //处理1~4位
    if (n > 0 && stoi(str))   flag = 1, work(str);

    if (!flag) ans += "ling";	//如果flag没变,则说明str为0

    //要去除末尾空格,否则官网会报错
    if (ans[ans.size() - 1] == ' ')  ans = ans.substr(0, ans.size() - 1);
    cout << ans;

    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值