【C&C++】迴圈結構:黑洞陷阱
要求:
程式輸入的一個小於1000且三個數字不全相等的整數,請你輸出進入黑洞的重排求差過程。本問題又稱“Kaprekar問題”。
495 是一個很神奇的數,被稱為黑洞數或者陷阱數。
給定任何一個小於1000的正整數,經前位補0後可以得到一個三位數(兩位數前面補1個0,一位數前面補2個0)。如果這個三位數的三個數字不全相等,那麼經有限次“重排求差”操作(組成該數的數字重排後的最大數減去重排後的最小數),總會得到495。
例如,對整數80,前位補0後得到080,重排後可以得到800,008。此時可以得到的最大數為800,最小數為008(即8)。那麼只需要4次重排求差即可得到495,過程如下:
1:800-8=792 //第一次
2:972 -279=693 //第二次,將第一次的結果進行重排求差
3:963-369=594 //第三次,將第二次的結果進行重排求差
4:954-459=495 //第四次以此類推
相關知識
要實現上述功能,需要反覆做一些相同或相似的工作,也就是反覆執行一些程式碼。這需要用到迴圈語句。
C 和 C++ 有3種基本的迴圈控制結構:while
語句、do-while
語句和 for
語句。
while 迴圈
while 迴圈語句表現為:
while (<條件表示式>)
<語句>
其中 while 是 C 和 C++ 的關鍵字, <條件表示式>
是迴圈控制條件,<條件表示式>
while 語句執行過程
首先計算<條件表示式>
的值,如果<條件表示式>
的值為0(即 false ),則跳過迴圈體<語句>
,執行整個 while 語句的後繼語句;
如果<條件表示式>
的值為非0(即 true ),則執行指定的<語句>
,執行完該語句後,再計算<條件表示式>
的值,如果<條件表示式>
的值仍然為非0,則繼續執行指定的<語句>
,再進行測試 ……,直到<條件表示式>
的值為0,再跳過迴圈體<語句>
,結束整個 while 語句的執行,接著執行整個 while 語句的後繼語句。
例如下面的程式可以計算飛機上下落的鐵球落地的時間(精確到秒)。假設飛機高度為2500米,下落的高度d(米)和時間t(秒)之間的關係是
d=(1/2)gt ^ 2
, 其中g = 9.82 m/s ^ 2
。
// 初始狀態時間為秒,下落高度為米
int sec = 0;
float dis = 0;
// 如果下落高度小於米,則繼續迴圈
while (dis < 2500)
{
// 每次迴圈計算每秒後的下落高度
sec += 1;
dis = 0.5 * 9.82 * sec * sec;
}
// 輸出落地需要的秒數
cout << sec << "秒" << endl;
do-while 語句
第二種迴圈語句是 do-while
語句,一般格式為:
do <語句>
while (<條件表示式>);
其中,do 和 while 都是 C 和 C++ 的關鍵字,do 和 while 之間的語句是迴圈體,<條件表示式>
是迴圈控制條件,整個 do-while 語句的最後是作為語句結束標誌的分號。
do-while 語句構成的迴圈與 while 語句構成的迴圈有所不同:
它先執行迴圈中的<語句>
,然後計算<條件表示式>
的值,判斷條件的真假,如果為 true,則繼續迴圈;如果為 false,則終止迴圈,繼續執行整個 do-while 語句的後繼語句。
因此,do-while 語句是一種出口控制的迴圈結構,其迴圈體至少要被執行一次,而 while 語句是入口控制的迴圈結構,其迴圈體未必會被執行。
do-while 語句的執行流程圖如下:
同樣的,當迴圈體包含多條語句時,可以用花括號把它們括起來,形成一個複合語句。
for 語句
第三種迴圈語句為 for 語句,一般形式為:
for (<初始化語句> ;[<條件表示式>]; [<增量表達式>] )
<語句>
for 是 C 和 C++ 的關鍵字,表示 for 迴圈語句的開始。<語句>
是 for 語句的迴圈體。
<初始化語句>
可以是任何合法的語句,<條件表示式>
和<增量表達式>
則可以由任何合法的表示式充當,具體說明如下:
1.初始化語句:
<初始化語句>通常是一個賦值語句,用來給迴圈控制變數賦初值。
<初始化語句>可以是表示式語句或宣告語句,以“ ; ”結束。
2.條件表示式:
<條件表示式>是一個能夠轉換成邏輯值的表示式,它決定什麼時候退出迴圈,該表示式可以為空(為空時邏輯值恆為 true )。
<條件表示式>和<增量表達式>之間用 “ ; ” 分開。
3.增量表達式:
<增量表達式>定義了迴圈控制變數每迴圈一次後按什麼方式變化,該表示式也可以為空,這時不產生任何計算效果。
for 語句的執行過程
首先計算<初始化語句>
,然後計算<條件表示式>
的值。
如果該值為 false,則結束迴圈,跳過迴圈體的<語句>
,轉到整個for語句的後繼語句繼續執行;
如果該值為 true,則執行迴圈體的<語句>
,執行完迴圈體後,緊接著執行<增量表達式>
,再計算<條件表示式>
的值,如果該值為 true,則執行迴圈體的<語句>
,再執行<增量表達式>
,再計算<條件表示式>進行測試,…… ,直到<條件表示式>
的值為 false,則結束迴圈,跳過迴圈體的<語句>
,繼續執行整個 for 語句的後繼語句。
for 語句的執行流程圖如下:
例如下面的程式可以計算1到100之間所有整數的和並輸出:
int sum = 0; // 宣告求和變數並初始化
// 求和
for (int i = 1; i <= 100; i++)
sum += i;
cout << "The sum of 1 to 100 is: " << sum << endl;
程式設計要求
獲取輸入的一個小於1000且三個數字不全相等的整數,並輸出進入黑洞的重排求差過程。
程式實現:
測試輸入:123
預期輸出:
1:321-123=198
2:981-189=792
3:972-279=693
4:963-369=594
5:954-459=495
測試輸入:18
預期輸出:
1:810-18=792
2:972-279=693
3:963-369=594
4:954-459=495
int main()
{
int n;
int h, l;
int max, mid, min;
int i = 0;
cin >> n;
while(n != 495)
{
int a = n / 100;
int b = n / 10 % 10;
int c = n % 10;
if (a <= b)
{
if (c >= b)
{
mid = b;
max = c;
min = a;
}
else if (c >= a)
{
mid = c;
max = b;
min = a;
}
else
{
mid = a;
max = b;
min = c;
}
}
else
{
if (c < b)
{
mid = b;
max = a;
min = b;
}
else if(c < a)
{
mid = c;
max = a;
min = b;
}
else if (c > a)
{
mid = a;
max = c;
min = b;
}
}
h = max * 100 + mid * 10 + min;
l = min * 100 + mid * 10 + max;
i ++;
n = h - l;
std::cout << i << ":" << h << "-" << l << "=" << n << std::endl;
}
return 0;
}
測試編譯為: