在這一節裡面,我們要介紹一個新的流程控制結構:do-while。 它的基本結構是
do BODY while (CONDITION);其中 BODY 是一些指令。如果超過一條指令,要用一對 { } 將它們括起來。 如果沒有指令,必須寫一個 ; 分號。 C 會先執行 BODY 一遍,然後檢查 CONDITION 是否為 True (只要 CONDITION 的值不是 0,就認為是 True)。 如果 True,則回頭重複執行 BODY,否則就做 while (CONDITION); 的下一條指令。
相信讀者在此時已經對流程控制結構,如 for, while, if-else,有了概念。 相對於 while 迴圈,do-while 迴圈的不同是, 在 while 裡面,先檢查 CONDITION,再決定 BODY 做還是不做。 在 do-while 裡面,先做一遍 BODY,在檢查 CONDITION,再決定繼續還是停止。 所以,在 while 裡面,BODY 可能一次都沒執行。 在 do-while 裡面,BODY 至少被執行了一遍。
以下舉一個函式 i2s() 來作為 do-while 結構的使用範例。 在 printf() 的輸出格式中,我們可以用十進制、八進制、十六進制數字, 來輸出一個整數。但是卻沒有輸出二進制數字的格式。 以下的 i2s(),就是要彌補這個缺憾。
/* 將一個正整數轉換成二進制數字的字串 */ void i2s(unsigned int n, char s[]) { int i=0, j, c; do s[i++] = (n & 1) + '0'; while ((n >>= 1) > 0); s[i] = '\0'; for (j=0, --i; j < i; c=s[j], s[j++]=s[i], s[i--]=c) ; }
讓我們看看 i2s() 的設計。 其中 (n & 1) 就是檢查 n 的位元組之 0 號位元是否為 1。 如果不是 1 (那就是 0),就在 s[] 裡面添一個 '0' 數目字。 如果是 1,就要添一個 '1' 數目字,而 '1' 數目字的 ASCII 號碼,就是 '0' 數目字的下一號。 所以我們寫
s[i++] = (n & 1) + '0';而這就是 do-while 的 BODY 部分。 此時,我們之所以選擇用 do-while 而不用 while, 原因非常明顯:如果輸入的 n 就是 0, 則 s[] 至少要放一個 '0' 進去。 所以,此 do-while 的 BODY 部分至少要被執行一遍。如果不慎寫成了
while ((n >>= 1) > 0) s[i++] = (n & 1) + '0';則遇到 n 本來就是 0 的 極端狀況,就會出錯 (s[] 成了空字串)。 i2s() 的最後一個指令,其實就是要將 s[] 的字元順序反過來。 我們可以呼叫 reverse() 來執行。 但是,為了這麼簡單的工作,還要宣告、呼叫另一個函式, 我覺得太麻煩了,所以就將 reverse() 的功能寫在 i2s() 裡面。
底下,我們寫一個簡單的程式來測試 i2s()。
#include <stdio.h> void i2s(unsigned int, char[]); /* Test for i2s() (test_i2s.c) */ main() { char s[8*sizeof(unsigned int)+1]; int x; x = 13, i2s(x, s); printf("%d\t%s\n", x, s); x = 0, i2s(x, s); printf("%d\t%s\n", x, s); x = (1 << 31), i2s(x, s); printf("%d\t%s\n", x, s); x = -1, i2s(x, s); printf("%d\t%s\n", x, s); }
假設 i2s() 寫在 i2s.c 裡面, 測試程式寫在 test_i2s.c 裡面,則執行步驟如下:
shell% gcc -c i2s.c shell% gcc test_i2s.c i2s.o shell% a.out 13 1101 0 0 -2147483648 10000000000000000000000000000000 -1 11111111111111111111111111111111我們看到,因為 C 自動處理 int 和 unsigned int 資料型態的特性, 所以即使在 main() 中將 x 定義成負數, 還是可以得到正確答案。
習題
void i2sm(unsigned int n, char s[], unsigned int m)它將 n 的數值轉換成二進制的數字,儲存在 s[] 裡面。 但是 s[] 至少要用掉 m 個格子。 如果 s[] 裡面的字元超過了 m 個, 就讓它超過。如果不足,必須在左邊補空格,使它總共有 m 個字元。 譬如,呼叫 i2sm(13, s, 8),則 s 字串就應該是 " 1101"
1 3 6 7則它們的位元組是
0001 0011 0110 0111按照位元的位置做加法,就相當於
0 0 0 1 0 0 1 1 0 1 1 0 + 0 1 1 1 ---------------- 0 2 3 3所以位元和就是
0 2 3 3一般而言,您要輸出 8*sizeof(unsigned int) 個數來表達位元和。
注意:此處所有文件均為原著,個別的版權宣告日後會一一公布, 整體版面設計亦尚未完成。但仍請勿抄襲文字與圖片,以免觸犯著作權法。
Created: May 18, 2000
Last Revised: May 18, 2000
© Copyright 2000 Wei-Chang Shann 單維彰