问题描述 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;
}