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() 等等。。。