蓝桥杯,数的读法

问题描述  Tom教授正在给研究生讲授一门关于基因的课程,有一件事情让他颇为头疼:一条染色体上有成千上万个碱基对,它们从0开始编号,到几百万,几千万,甚至上亿。
  比如说,在对学生讲解第1234567009号位置上的碱基时,光看着数字是很难准确的念出来的。
  所以,他迫切地需要一个系统,然后当他输入12 3456 7009时,会给出相应的念法:
  十二亿三千四百五十六万七千零九
  用汉语拼音表示为
  shi er yi san qian si bai wu shi liu wan qi qian ling jiu
  这样他只需要照着念就可以了。
  你的任务是帮他设计这样一个系统:给定一个阿拉伯数字串,你帮他按照中文读写的规范转为汉语拼音字串,相邻的两个音节用一个空格符格开。
  注意必须严格按照规范,比如说“10010”读作“yi wan ling yi shi”而不是“yi wan ling shi”,“100000”读作“shi wan”而不是“yi shi wan”,“2000”读作“er qian”而不是“liang qian”。

一开始写的时候,想四个一组,逐一判断。然后发现,情况很复杂,试运行的时候,程序直接崩溃了。。。
(我也很崩溃)
分享一下愚蠢的我的错误代码(代码不全)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<fstream>
#include<cmath>
#include<stack>
#include<cstring>
#include<vector>
#include<map>
#include<string> 
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=10005;
vector<string>ans;
string k;
int cnt=0;
string f(int a){
 switch(a){
  //case 0: return k="ling";
  case 1: return k="yi";
  case 2: return k="er";
  case 3: return k="san";
  case 4: return k="si";
  case 5: return k="wu";
  case 6: return k="liu";
  case 7: return k="qi";
  case 8: return k="ba";
  case 9: return k="jiu";
  //case 10:return k="shi";
 }
}
void check(string str){
 int len=str.size(),i=0;
 int flag=2;
 if(len==4&&str[i]!='0'){
  flag=1;
  ans[cnt]=f(str[i]-'0');
  cnt++;
  ans[cnt]="qian";
  cnt++;
  len--;
  i++;
 }
 if(len==3&&str[i]!='0'){
  flag=1;
  ans[cnt]=f(str[i]-'0');
  cnt++;
  ans[cnt]="bai";
  cnt++;
  len--;
  i++;
 }
 else if(len==3&&str[i]=='0') {
  flag=0;
  len--;
  i++;
 }
 if(len==2&&str[i]!='0'){
  if(flag==0){
   ans[cnt]="ling";
   cnt++;
  }
  flag=1;
  if(str[i]=='1'&&ans.size()==0){
   ans[cnt]="shi";
   cnt++;
  }
  else{
   ans[cnt]=f(str[i]-'0');
   cnt++;
   ans[cnt]="shi";
   cnt++;
  }
  //cout<<"stop"<<endl;
  len--;
  i++;
 }
 else if(len==2&&str[i]=='0'){
  flag=0;
  len--;
  i++;
 }
 if(len==1&&str[i]!='0'){
  if(flag==0){
   ans[cnt]="ling";
   cnt++;
  }
  flag=1;
  ans[cnt]=f(str[i]-'0');
  cnt++;
     i++;
     len--;
 }
}
int main(){
 string str;
 cin>>str;
 int len=str.size();
 //cout<<len%4+len/4<<endl;
 if((len%4+len/4)>=3){
 // cout<<"stp";
  int i=0,j=0,ff=0;
  string st;
        for(i=0;i<len%4;i++){
         st[j]=str[i];
         j++;
  }
  check(st);
  ans[cnt]="yi";
  cnt++;
  st.clear();
  j=0;
  for(;i<len%4+4;i++){
   if(str[i]=='0'&&j==0)ff=1;
   else {
    st[j]=str[i];
             j++;
   }
  }
  if(j==0){
   ans[cnt]="ling";
      cnt++;
  }
  else{
   if(ff==1){
    ans[cnt]="ling";
          cnt++;
   } 
   check(st);
      ans[cnt]="wan";
      cnt++;
  }
  st.clear();
  j=0;
  ff=0;
  for(;i<len%4+8;i++){
   if(str[i]=='0'&&j==0);
   else {
    st[j]=str[i];
             j++;
   }
  }
  if(j==0);
  else{
   if(ff==1&&ans[cnt-1]!="ling"){
    ans[cnt]="ling";
          cnt++;
   } 
   check(st);
  } 
 } 
 cout<<cnt;
 for(int i=0;i<cnt;i++)cout<<ans[i]<<" ";
 return 0; 
} 

心烦之下,网上搜了别人的题解。(人家的代码怎么那么简洁漂亮TAT)

#include<iostream>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
int main(){
    char *num[]={"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
    char *wei[]={"shi","bai","qian","wan","yi"};
    char *str[20];  //存结果
    //i:指向n从后向前的数位,4位数为一组
    //j:数组str的下标
    //k:n的最后一位数
    //l[2]标明第几个四位数 
    int i=0,j=0,k,l[2]={0};
 ll n;//输入数字 
    cin>>n;
    while(n){
        k=n%10;
        n/=10;//从最后一位开始 
        if(k>0){
            if(i>0){
                if(i>=4 && !l[i/4-1]){  
    //如果是大于等于4位数的数,且已经加了一个wei,那么不要添加
                    l[i/4-1]=1;
                    str[j++]=wei[i/4+2];
                }
                if(i%4!=0){
                    str[j++]=wei[i%4-1];
                }
            }
            str[j++]=num[k];
        }
        else if(j>0 && str[j-1]!=num[0]) str[j++]=num[0];
        //判断连续另个是不是都是0,其实我觉得,放到最后再删也行 
        i++;
    }
    if(!(str[j-1]=="yi" && j>1 && str[j-2]=="shi"))  //去除yi shi的情况
        cout<<str[j-1]<<" ";        //输出第一位数
    for(i=j-2;i>=0;i--){        //输出剩余的各个字符串
        cout<<str[i]<<" ";
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值