1. 程式人生 > >PAT-ADVANCED1082——Read Number in Chinese

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++解題報告: