1. 程式人生 > >PAT乙級 1019. 數字黑洞 C語言

PAT乙級 1019. 數字黑洞 C語言

1019. 數字黑洞 (20)

題目
給定任一個各位數字不完全相同的4位正整數,如果我們先把4個數字按非遞增排序,再按非遞減排序,然後用第1個數字減第2個數字,將得到一個新的數字。一直重複這樣做,我們很快會停在有“數字黑洞”之稱的6174,這個神奇的數字也叫Kaprekar常數。
例如,我們從6767開始,將得到
7766 - 6677 = 1089
9810 - 0189 = 9621
9621 - 1269 = 8352
8532 - 2358 = 6174
7641 - 1467 = 6174
… …
現給定任意4位正整數,請編寫程式演示到達黑洞的過程。
輸入格式
輸入給出一個(0, 10000)區間內的正整數N。
輸出格式


如果N的4位數字全相等,則在一行內輸出“N - N = 0000”;否則將計算的每一步在一行內輸出,直到6174作為差出現,輸出格式見樣例。注意每個數字按4位數格式輸出。
輸入樣例1
6767
輸出樣例1
7766 - 6677 = 1089
9810 - 0189 = 9621
9621 - 1269 = 8352
8532 - 2358 = 6174
輸入樣例2
2222
輸出樣例2
2222 - 2222 = 0000

這道題的題意邏輯非常簡單,主要難點是要在“字串”和 “數值”之間轉換,因此要熟悉atoi(),sprintf()函式的使用(gcc預設不支援itoa(),所以用sprintf()代替)
注意


1. 使用者輸入的數字如果小於四位數,需要在左邊用‘0’補齊
2. 每一輪計算中如果出現小於四位數的數字,也要用‘0’補齊
3.如果使用者輸入的數字是“6174”,也應該進行計算,而不是直接結束!
4. 當數字正序 == 倒序,結果為“0000”

思路
字串形式獲取輸入,補齊‘0’
while(num[ ]是使用者的輸入 或 num[ ]!=‘6147’)
……..差=(num[ ]降序,轉換為數值)- (num[ ]升序,轉換為數值 )
…….. 將差轉換為字串,給num[ ]

程式碼如下:

#include<stdio.h>
#include<stdlib.h> #include<string.h> #define SIZE 5 #define END "6174" char * descent(char *);//降序排序 char * ascent(char *);//升序排序 int main(void) { char num[SIZE],aux[SIZE]; int t; scanf("%d",&t); sprintf(num,"%04d",t);//將使用者輸入補齊‘0’,寫入字串num[] int isInput =1;//即使使用者輸入的num==END,還是會進入迴圈 while(isInput ||strcmp(num,END)) { isInput = 0; strcpy(aux,num); int result = atoi(descent(num)) - atoi(ascent(aux)); if(!result) { printf("%s - %s = 0000\n",num,aux); break; } else printf("%s - %s = %04d\n",num,aux,result);//補齊‘0’ sprintf(num,"%04d",result);//補齊‘0’ } return 0; } char * descent(char * a) { for(int i =1;i<strlen(a);i++) { for(int j = i; j>0 && a[j]>a[j-1];j--) { char t = a[j]; a[j] = a[j -1]; a[j-1] = t; } } return a; } char * ascent(char * a) { for(int i =1;i<strlen(a);i++) { for(int j = i; j>0 && a[j]<a[j-1];j--) { char t = a[j]; a[j] = a[j -1]; a[j-1] = t; } } return a; }

小結
使用C的庫函式可以非常方便地在“字串”和“數值”之間進行轉換。
上述程式碼中使用的:
……..int atoi(char * pstr): 字串轉換為int數
……..int sprintf(char * pstr,“字串格式”,若干引數) : 這個真的太好用了!這樣就可以將引數3中指定的引數利用引數2的”字串格式“進行格式化之後,寫入到作為快取的引數1字串中…甚是強悍!
其中注意到函式的引數2,其實是const char *型別,也就是常數指標,我們平時習慣的”%d”等格式其實使用的是”支付字面量“,而這裡其實是可以放指標的········

其他類似的實用函式還有
1. atol :字串 轉 長整型
2. atoll : 字串 轉 long long
3. strtod(const char *nptr, char **endptr) :字串 轉 double,
還自帶正確性檢驗功能(將nptr字串轉換為double, 轉換結束的時候endptr指向最後一個成功轉換的字元的下一個字元…….這是一個很有用的特性,事先如果輸入是合法數值,那麼自然endptr指向’\0’,而如果輸入不合法,就會指向遇到的第一個不合法的字元)     
4.類似的還有:strtol() ,strtoul(), strtof() 等等。。。