天天看點

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

點選檢視第一章 點選檢視第三章

第2章

控制語句

本章介紹利用控制語句的功能來解決問題的方法。C包含種類豐富的控制語句。C中的控制語句大緻可分為三類。

□選擇語句:選擇語句用于在幾個計算機控制流中選擇其一。選擇語句有兩種:if-else和switch。

□疊代語句:疊代語句用于有限次地重複執行一組語句。疊代語句有三種:while、do-while和for。

□跳轉語句:跳轉語句有四種,即break、continue、goto和return。通常,計算機控制從源代碼中前面的語句順序流到下一個語句。當你需要繞過此順序流,并讓計算機控制從一個語句跳轉到另一個語句(不一定是連續語句)時,可以使用跳轉語句。

goto語句用于跳轉到同一函數中的另一個語句。continue語句僅用于疊代語句中。break語句僅用于疊代或switch語句中。return語句用于函數中。

2.1 求1到N的整數的總和

問題

你希望開發一個以互動方式計算1到N的整數的總和的程式。

解決方案

編寫一個C程式,使用以下規格說明計算1到N的整數的總和:

□程式使用for循環執行1到N的整數的總和。for循環沒有什麼特殊的,你也可以使用while循環或do-while循環,但在這些類型的程式中,for循環是優選的。

□程式要求使用者輸入數字N(0□當計算的總和顯示在螢幕上時,程式會詢問使用者是否要計算另一個總和或退出。

代碼

以下是使用這些規格說明編寫的C程式的代碼。在文本編輯器中鍵入以下C程式并将其儲存在C:Code檔案夾下名為sum.c的檔案中:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

編譯并執行此程式。此程式的一次運作結果如下所示:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

工作原理

包含在LOC 16~18中的for循環執行1~N的整數的求和。在此程式中使用具有兩層嵌套的do-while循環。隻要使用者未能在指定範圍内輸入數字N,内部do-while循環就會将使用者保持在循環内。隻要使用者想要再次執行求和,外部do-while循環就會将使用者保持在循環内。内部do-while循環增加了此程式的穩健性。

除了for循環之外,還可以使用while或do-while循環來執行求和。要使用while循環執行求和,請使用以下代碼行替換LOC 16~18:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

要使用do-while循環執行求和,請将LOC 16~18替換為以下代碼行:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

編寫循環的終止條件時要小心。輕率地編寫循環的終止條件是bug的發源地。

■注意 bug圍繞邊界值“遊蕩”。

例如,檢視此處給出的for循環:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

乍一看,你可能認為這個for循環執行100次疊代,但實際上,它隻執行99次疊代。是以,在處理邊界值時要小心。

源代碼中的錯誤是bug。發現和糾正源代碼中的錯誤的過程稱為調試(debug)。

程式設計專家能夠建立具有最少數量的可能bug的程式,并且還知道如何調試程式。編寫一個完全沒有bug的小程式是可能的,但是由數千代碼行組成的專業程式永遠不會沒有bug。

2.2 計算數字的階乘

你想要開發一個程式來計算數字的階乘。

正整數n的階乘由n!表示,它的定義如下:

n! = 1×2×…×n

這裡給出了一些數字的階乘:

0! = 1(根據定義)

1! = 1

2! = 1×2 = 2

3! = 1×2×3 = 6

編寫具有以下規格說明的C程式:

□程式使用for循環計算N的階乘。

□程式要求使用者輸入數字N(0<N≤12)。如果使用者輸入該範圍之外的數字N,則程式要求使用者重新輸入數字。

□當計算的階乘顯示在螢幕上時,程式會詢問使用者是否想要計算另一個階乘或退出。

以下是使用這些規格說明編寫的C程式的代碼。在文本編輯器中鍵入以下C程式并将其儲存在檔案夾C:Code中,檔案名為fact.c:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

LOC 16~18中包含的for循環計算數N的階乘。在此程式中使用具有兩層嵌套的do-while循環。隻要使用者未能在指定範圍内輸入數字N,内部do-while循環就會将使用者保持在循環内。隻要使用者想要再次計算階乘,外部do-while循環就會将使用者保持在循環内。内部do-while循環增加了此程式的穩健性。除了for循環之外,還可以使用while或do-while循環來計算數字N的階乘。

2.3 生成斐波那契數列

你想開發一個程式來生成斐波那契數列。

Leonardo Fibonacci(1180—1250),也被稱為比薩的萊昂納多,是一位意大利數學家。他撰寫了許多關于數學的優秀論文,如“Liber Abaci”“Practica Geometriae”“Flos”和“Liber Quadratorum”。斐波那契數列以其發明人命名并在“Liber Abaci”中提及,從0和1開始,每個連續項都是前兩個項的和。根據定義,第一項為0,第二項為1。前幾項列于此處:

第一項 根據定義 0

第二項 根據定義 1

第三項 0 + 1 = 1

第四項 1 + 1 = 2

第五項 1 + 2 = 3

第六項 2 + 3 = 5

斐波那契數列中的項也稱為斐波那契數。這裡給出了一個可以生成斐波那契數的例程的僞代碼:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

□程式使用for循環計算斐波那契數。

□程式要求使用者輸入數字N(0<N≤45)。如果使用者在此範圍之外輸入數字N,則程式會要求使用者重新輸入此數字。然後程式生成N個斐波那契數。

□當計算出的斐波那契數顯示在螢幕上時,程式會詢問使用者是否想要計算另一個斐波那契數或退出。

以下是使用這些規格說明編寫的C程式的代碼。在C檔案中鍵入以下文本(程式)并将其儲存在檔案夾C:Code下名為fibona.c的檔案中:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

LOC 18~27中包含的for循環完成了大部分工作。LOC 23~26中包含的代碼計算斐波那契數。LOC 19和LOC 21中包含的代碼在螢幕上顯示計算出的斐波那契數。在此程式中使用具有兩層嵌套的do-while循環。隻要使用者未能在指定範圍内輸入數字N,内部do-while循環就會将使用者保持在循環内。隻要使用者想要再次計算斐波那契數,外部do-while循環就會将使用者保持在循環内。内部do-while循環增加了此程式的穩健性。除了for循環之外,還可以使用while或do-while循環來計算斐波那契數。斐波那契數列在植物學、電網理論、搜尋和排序中有應用。

2.4 确定給定數字是否為質數

你希望開發一個程式來确定給定的數字是否為質數。

質數是一個正整數,隻能被1和它本身整除。前幾個質數如下:2, 3, 5, 7, 11, 13, 17, 19。除了2之外,所有質數都是奇數。你将開發一個程式來确定給定的數字是否為質數。

程式執行開始時,系統會要求你輸入2~2 000 000 000範圍内的數字。鍵入此範圍内的任何整數,程式将告訴你此數字是否為質數。另外,輸入0以終止程式。顯然,要确定數字N是否為質數,必須将它除以2~(N-1)之間的所有數字并檢查餘數。如果每個除法的餘數都不為零,則數N是質數,否則,它不是質數。但是,實際上可以将N的數字除以2~√N(N的平方根)之間的所有數字并檢查餘數。如果N不能被2~√N之間的任何數字完全整除,那麼它肯定不能被2~(N-1)之間的任何數字整除。

此處給出了一個例程,用于确定給定數字lngN是否為質數。這裡,isPrime是一個int變量,lngN、lngM和i是long int變量,lngN的值為3或更大,并且isPrime設定為1(被解釋為真)。

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

在此例程的LOC 2中,通過隐式類型轉換将lngN的值轉換為double類型,然後将其傳入sqrt()以計算其平方根。sqrt()傳回的結果被傳到ceil()以将其轉換為較大的最接近的整數。在隐式類型轉換後,ceil()傳回的結果将指派給lngM。

接下來,lngN将除以2到lngM之間的所有數字。如果在所有這些除法中餘數都為非零,那麼lngN是質數,否則不是。這是在LOC 3~8的for循環中完成的。實際除法在LOC 4中執行,并檢查餘數的值(是否為零)。如果餘數為零,則執行LOC 5和6。在LOC 5中,int變量isPrime的值設定為零。在LOC 6中,執行break語句以終止for循環。注意isPrime的值,結果顯示在螢幕上。如果isPrime為1(真),則lngN為質數;如果isPrime為0(假),則lngN不是質數。

□程式使用for循環檢查數字的素性。

□程式要求使用者輸入數字N(2≤N≤2 000 000 000),以确定此數字是否為質數。如果使用者輸入該範圍之外的數字N,則程式要求使用者重新輸入此數字。然後程式檢查此數字的素性。如果使用者輸入0,則程式終止。

以下是使用這些規格說明編寫的C程式的代碼。在C檔案中鍵入以下文本(程式)并将其儲存在檔案夾C:Code中,檔案名為prime.c:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

LOC 25~30中包含的for循環完成了檢查數字的素性的大部分工作。LOC 31~34中的代碼顯示結果。在此程式中使用具有兩層嵌套的do-while循環。隻要使用者未能在指定範圍内輸入數字N,内部do-while循環就會将使用者保持在循環内。隻要使用者想要檢查新數字的素性,外部do-while循環就會将使用者保持在循環内。内部do-while循環增加了此程式的穩健性。請注意LOC 35,此處摘錄以供你快速參考:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

這似乎是一個無限循環,因為括号中沒有比較語句。但是,在LOC 18中提供了終止循環的規定,這裡也摘錄以供你快速參考:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

當lngN的值為零時,此循環的執行将成功終止。

庫函數ceil()和sqrt()在LOC 24中使用,這裡也摘錄以供你快速參考:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

庫函數ceil()和sqrt()是數學函數,這就是通過LOC 2将頭檔案math.h包含在這個程式中的原因。術語sqrt代表“平方根”,術語ceil代表“上取整”,這反過來意味着上限。以下是使用庫函數sqrt()的語句的通用文法:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

這裡,dblY是一個表達式,其計算結果為double類型的常量,而dblX是double類型的變量。函數sqrt()計算dblY的平方根并傳回結果,該結果指派給變量dblX。

函數ceil()将double值(作為參數傳遞)轉換為較大的最接近的整數值并傳回結果。以下是使用函數ceil()的語句的通用文法:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

這裡,dblY是一個表達式,其計算結果為double類型的常量,而dblX是一個double變量。

2.5 計算正弦函數

你想使用無窮級數展開計算角度x的正弦值。

這裡給出了無窮級數展開的公式:

sin x = x - x3 / 3! + x5 / 5! - x7 / 7! + …

這裡,x是以弧度表示的角度,它的取值範圍為-1≤x≤1。可以看到連續項的值持續迅速減小。是以,僅包括前十項就足夠了。如果x的值為1,則第十項的貢獻約為2E-20,而第40項的貢獻約為1.7E-121。

□程式使用for循環計算角度x的正弦值。

□程式要求使用者輸入角度x(-1≤x≤1)。如果使用者在此範圍之外輸入角度x,則程式會要求使用者重新輸入。

□當螢幕上顯示角度x的正弦值時,程式會詢問使用者是否要計算另一個角度的正弦值或退出。

以下是使用這些規格說明編寫的C程式的代碼。在C檔案中鍵入以下文本(程式)并将其儲存在檔案夾C:Code中,檔案名為sine.c:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

LOC 19~23中包含的for循環計算角度x的正弦值。LOC 24中的代碼顯示結果。在此程式中使用具有兩層嵌套的do-while循環。隻要使用者未能在指定範圍内輸入角度x,内部do-while循環就會将使用者保持在循環内。隻要使用者想要計算另一個角度的正弦值,外部do-while循環就會将使用者保持在循環内。内部do-while循環增加了此程式的穩健性。

2.6 計算餘弦函數

你想使用無窮級數展開計算角度x的餘弦值。

cos x = 1 - x2 / 2! + x4 / 4! - x6 / 6! + …

這裡,x是弧度,它的取值範圍為-1≤x≤1。可以看到連續項的值持續迅速減小。是以,僅包括前十項就足夠了,如前面所讨論的那樣。

□程式使用for循環計算角度x的餘弦值。

□當螢幕上顯示角度x的餘弦值時,程式會詢問使用者是否要計算另一個角度的餘弦值或退出。

以下是使用這些規格說明編寫的C程式的代碼。但是,這次使用的編碼算法與前面相比略有不同。在C檔案中鍵入以下文本(程式)并将其儲存在檔案夾C:Code中,檔案名為cosine.c:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

兩層嵌套的for循環用于計算角度x的餘弦值。LOC 30顯示結果。在此程式中使用具有兩層嵌套的do-while循環。隻要使用者未能在指定範圍内輸入角度x,内部do-while循環就會将使用者保持在循環内。隻要使用者想要計算另一個角度的餘弦,外部do-while循環就會将使用者保持在循環内。内部do-while循環增加了此程式的穩健性。

2.7 計算二次方程的根

你想要計算二次方程的根。

你想要計算二次方程ax2 + bx + c = 0的根。這些根由以下公式給出:

(-b + √b2 - 4ac)/2a  和  (- b - √b2 - 4ac)/2a

根據a、b和c的值,根可能是實數或虛數。

□程式要求使用者輸入a、b和c的值,可以是整數或浮點數。

□程式使用前面給出的公式計算根并在螢幕上顯示結果。

□當在螢幕上顯示二次方程的根時,程式會詢問使用者是否想要計算另一個二次方程的根或退出。

以下是使用這些規格說明編寫的C程式的代碼。在C檔案中鍵入以下文本(程式)并将其儲存在檔案夾C:Code中,檔案名為roots.c:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

執行簡單的數學運算以計算二次方程的根。取決于系數a、b和c的值,根可能是實數或虛數。是以,我們規定要測試根是實的還是虛的。隻要使用者想要計算另一個二次方程的根,do-while循環就會将使用者保持在循環内。

2.8 計算整數的反轉數

你想要計算整數的反轉數。

例如,如果給定的整數是12345,那麼它的反轉數是54321。

□程式要求使用者輸入整數N(0<N≤30 000)。如果使用者輸入該範圍之外的整數N,則程式要求使用者重新輸入整數。

□程式計算整數的反轉數并在螢幕上顯示結果。

□然後程式詢問使用者是否想要計算另一個整數的反轉數或退出。

以下是使用這些規格說明編寫的C程式的代碼。在C檔案中鍵入以下文本(程式)并将其儲存在檔案夾C:Code中,檔案名為reverse.c:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

執行簡單的數學運算以計算整數的反轉數。在此程式中使用具有兩層嵌套的do-while循環。隻要使用者輸入的不是在指定範圍内的整數N,内部do-while循環就會将使用者保持在循環内。隻要使用者還想要計算另一個整數的反轉數,外部do-while循環就會将使用者保持在循環内。内部do-while循環增加了此程式的穩健性。

2.9 使用嵌套循環列印幾何圖案

你希望使用嵌套循環(而不是使用5個printf()語句)在螢幕上生成和列印以下幾何圖案:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

這個圖案的秩是5,即它由5行組成。你希望生成從1到9的任何秩的圖案。

可以使用兩層嵌套的for循環以程式設計方式列印此圖案。編寫具有以下規格說明的C程式:

□程式要求使用者輸入圖案的秩(1≤N≤9)。如果使用者輸入該範圍之外的N,則程式要求使用者重新輸入N。

□程式使用兩層嵌套的for循環列印所需的圖案。但是,此程式中将有4個for循環。

□然後程式詢問使用者是否要列印其他圖案或退出。

以下是使用這些規格說明編寫的C程式的代碼。在C檔案中鍵入以下文本(程式)并将其儲存在檔案夾C:Code中,檔案名為pattern.c:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

for循環的正确組合生成所需的圖案。在此程式中使用具有兩層嵌套的do-while循環。隻要使用者輸入的不是在指定範圍内的整數N,内部do-while循環就會将使用者保持在循環内。隻要使用者還想要生成不同秩的另一個圖案,外部do-while循環就會将使用者保持在循環内。内部do-while循環增加了此程式的穩健性。

2.10 生成終值利息系數表

你希望生成一個終值利息系數表(FVIF)并将其列印在螢幕上。

可以使用兩層嵌套的for循環以程式設計方式生成和列印此表。編寫具有以下規格說明的C程式:

□此程式生成FVIF表,利率從1%到6%不等,期限從1年到10年不等。

□FVIF值應精确到小數點後三位。

以下是使用這些規格說明編寫的C程式的代碼。在C檔案中鍵入以下文本(程式)并将其儲存在檔案夾C:Code中,檔案名為interest.c:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句
帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

FVIF表可用于計算貨币的未來價值。n年後本金額(Po)的未來價值(FVn)(每年的利率為i%)由下列公式給出:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

這裡,

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

假設本金額為200美元,利率為每年6%,期限為8年,從上表中可以看出相應的FVIF是1.594(第8行最後一列)。該金額的未來價值如下:

帶你讀《C程式設計技巧:117個問題解決方案示例》之二:控制語句

在此程式中,LOC 1和2由include語句組成。LOC 3和4由define語句組成。LOC 5~29包含main()函數的定義。在LOC 7和8中,聲明了一些變量。LOC 9~11由三個printf()語句組成,這些語句列印有關FVIF表的資訊。LOC 12~17列印FVIF表的标題。LOC 18~25由嵌套的for循環組成,在這些嵌套循環中計算并列印FVIF表。LOC 26列印FVIF表的底線。

繼續閱讀