PAT-ADVANCED1082——Read Number in Chinese
題目描述:
題目翻譯:
1082 用中文讀數字
給定一個不超過9位的整數,你需要用傳統中文的方式讀出它。如果它是一個負數,一開始輸出“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”。
輸入格式:
每個輸入檔案包含一個測試用例,每個測試用例包含一個不超過9位的整數。
輸出格式:
對每個測試用例,以中文方式列印數字。單詞由空格分隔,並且在行的末尾不能有額外的空格。
輸入樣例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
知識點:字串
思路:以字串形式讀取輸入
自己一開始寫的時候思路混亂,程式碼老長最後寫不下去了,看了《演算法筆記》中的解題步驟,步驟如下:
(1)整體思路是將數字按字串方式處理,並設定下標left和right來處理數字的每一個節(個節、萬節、億節)的輸出,即令left指向當前需要輸出的位,而right指向與left同節的個位。
(2)在需要輸出的某個節中,需要解決的問題是如何處理額外發音的零,設計的演算法如下:
設定bool型變數flag表示當前是否存在累積的零。當輸出left指向的位之前,先判斷該位是否為0:如果為0,則令flag為true,表示存在累積的零;如果非0,則根據flag的值來判斷是否需要輸出額外的零。在這之後,就可以輸出該位本身以及該位 對應的位號(十、百、千)。而當整一小節處理完畢後,再輸出萬或者億。
注意點:
(1)0的輸出應該為“ling”。
(2)讓left和right指向一個節的首尾可以採用如下方法:初始令left = 0,即用left指向首位;而令right = len - 1,即用right指向末位,其中len表示字串長度。之後不斷讓right減4,並控制left + 4不超過right,就可以得到第一個節。由於left會在輸出過程中自增至下一節的首尾,因此只需在當前節處理完畢後令right加4,即可讓right指向下一節的末位。
(3)如果萬節的所有位都為0,那麼就要注意不能輸出多餘的萬。例如,800000008的輸出應該是“ba Yi ling ba”,而不是“ba Yi Wan ling ba”。
時間複雜度和空間複雜度的分析對本題來說意義不大。
C++程式碼:
#include<iostream>
#include<cstring>
char num[10][5] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};
char wei[5][5] = {"Shi", "Bai", "Qian", "Wan", "Yi"};
int main(){
char str[15];
scanf("%[^\n]", str); //按字串方式輸入數字
int len = strlen(str); //字串長度
int left = 0, right = len - 1; //left與right分別指向字串首尾元素
if(str[0] == '-'){ //如果是負數,則輸出"Fu",並把left右移1位
printf("Fu");
left++;
}
while(left + 4 <= right){
right -= 4; //將right每次左移4位,直到left與right在同一節
}
while(left < len){ //迴圈每次處理數字的一節(4位或小於4位)
bool flag = false; //flag == false表示沒有累積的0
bool isPrint = false; //isPrint == false表示該節沒有輸出過其中的位
while(left <= right){ //從左至右處理數字中某節的每一位
if(left > 0 && str[left] == '0'){ //如果當前位為0且當前位不是首位,即對輸入是0的情況做了特殊處理
flag = true; //令標記flag為true
}else{ //如果當前位不為0
if(flag){ //如果存在累積的0
printf(" ling");
flag = false;
}
//只要不是首位(包括負號),後面的每一位前都要輸出空格
if(left > 0){
printf(" ");
}
printf("%s", num[str[left] - '0']); //輸出當前位數字
isPrint = true; //該節至少有一位被輸出
if(left != right){ //某節中除了各位外,都需要輸出十百千
printf(" %s", wei[right - left - 1]);
}
}
left++; //left右移1位
}
if(isPrint && right != len - 1){ //只要不是個位,就輸出萬或億
printf(" %s", wei[(len - 1 - right) / 4 + 2]);
}
right += 4; //right右移4位,輸出下一節
}
return 0;
}
C++解題報告: