標籤:轉化 while迴圈 pre 9.png i++ 結構 數值 奇數 來源程式
(一)改錯題
序列求和:輸入一個正實數eps,計算序列部分和 1 - 1/4 + 1/7 - 1/10 + ... ,精確到最後一項的絕對值小於eps(保留6位小數)。
輸入輸出範例:
Input eps:1E-4
s = 0.835699
來源程式(有錯誤的程式)
#include<stdio.h>int main(){ int flag,n; double eps,item,s; printf("Input eps: "); scanf("%f",&eps); flag = 1; s = 0; n = 1; do{ item = 1/ n; s = s + flag * item; flag = -flag; n = n + 3; }while( item < eps) printf( "s = %f\n",s); return 0;}
錯誤一:
錯誤原因:while語句後面沒有分號
改正方法:在while( item < eps)的後面加上一個“;”
改正錯誤後,編譯沒有錯誤
輸入資料驗證
程式錯誤
錯誤二:
錯誤原因:第八行輸入語句有問題,不應該用%f
改正方法:將%f改為%lf
錯誤三
錯誤原因:第13行中的運算為整型運算,並不能出現實數
改正方法:將“item = 1/ n”中的“1”改成“1.0”
改正後,輸入資料,程式仍然錯誤
錯誤四
錯誤原因:輸出語句有問題,%f錯誤
改正方法:將%f改為%lf
錯誤五
錯誤原因:迴圈語句有錯誤,while語句括弧裡面的語句錯誤
改正方法:將“while( item > eps)”裡的“<”改成“>”
將改正後的程式輸入資料進行驗證
附上改正後的程式:
#include<stdio.h>int main(){ int flag,n; double eps,item,s; printf("Input eps: "); scanf("%lf",&eps); flag = 1; s = 0; n = 1; do{ item = 1.0/ n; s = s + flag * item; flag = -flag; n = n + 3; }while( item >= eps); printf( "s = %lf\n",s); return 0;}
(二)學習總結
1.語句while(1)和for(;;)是什麼意思?,如何保證這種迴圈能正常執行?
答:兩個語句都是迴圈語句,並且都是無限迴圈,也就是我們說的死迴圈,這種迴圈適用於不清楚迴圈應該啟動並執行次數的迴圈。while()的括弧內的判斷方是括弧內的條件是否為真,只要括弧內為任意非零數值,均判斷為真,所以不一定為1,其他的非零數值均可,如:1,-5等均可。 而for迴圈,其判斷依據是根據for(;;)的括弧內的三個運算式來判斷真假,第二個運算式為迴圈的條件,若第二個運算式為空白,則迴圈停下來的條件就會缺失,迴圈語句則會無限迴圈。
若要保證這種迴圈正常執行,就必須保證其判斷條件為“1”,也就是真,即語句本身不能出現錯誤,並且不會出現迴圈控制語句,即不出現break語句等。
2.一般情況下,設計迴圈結構時,使用for、while、do while三種語句都可以,並且三種語句可以相互轉換,但是,在某些特定情況下,我們應該優先選擇某種語句來快速實現迴圈設計。如果有如下情況:
(1)迴圈次數已知
(2)迴圈次數未知,但迴圈條件在進入迴圈時明確
(3)迴圈次數未知,且迴圈條件在進入迴圈時未知,需要在迴圈體中明確
針對上面三種情況,分別採用什麼迴圈語句實現比較好?對每種情況,用我們完成的兩次迴圈結構作業中的題目加以說明。
答:(1)迴圈語句已知的情況下用for語句比較好,因為for語句中含有明確的將迴圈停止的語句。如pta迴圈第一次作業中,求奇數分之一序列前N項和這一題,此題便用for語句比較方便,明確迴圈的次數,選定一個初值,明確結束條件,便可以得出答案。
(2)迴圈次數未知,但迴圈條件在進入迴圈時明確,這種情況使用while語句比較好,由於迴圈次數未知,但是已知某些條件,便可以利用迴圈。如怕他迴圈第二次作業中,韓信點兵問題就是利用while語句,利用先迴圈在判斷的形式,該問題的迴圈次數為多少我們在不經過計算的情況下並不知道,但是題目所給出的條件可以讓我們寫出迴圈停止的語句,所以利用while語句比較好。
(3)迴圈次數未知,且迴圈條件在進入迴圈時未知,需要在迴圈體中明確,這樣的情況我們一般利用do while語句。如pta迴圈第二次作業中的掉入陷阱的數位問題,我們對迴圈執行的次數以及迴圈停止的條件並不清楚,do while迴圈的執行方式為先進入迴圈體執行一次迴圈體,之後再判斷迴圈條件是否成立,這樣利用迴圈體我們就可以使迴圈執行下去,來滿足題目要求。
3.有如下問題:輸入一批學產生績,以-1作為結束,計算學生的平均成績。
要求分別用for語句、while語句、do while語句三種迴圈語句實現,並說明你認為哪種形式更合適?
(1)若使用for語句,程式如下:
#include<stdio.h>int main(void){int grade=0,sum=0,i=0;double average=0.0;for(;;) {scanf("%d",&grade);if(grade!=-1){sum = sum +grade;i++;}else if(grade==-1){break;}}average = sum / i;printf("%f",average);return 0;}
(2)若使用while語句,程式如下:
#include <stdio.h>int main(){double sum = 0.0, n = 0.0, average = 0.0;int num = 0;sum = 0.0;num = 0;while (1){ scanf("%lf", &n); if (n == -1) { break; } sum += n; num++;}average = sum / num;printf("%f", average);return 0;}
(3)若使用do while語句,程式如下:
#include<stdio.h>int main(void){int grade=0,sum=0,i=0;double average=0.0;i=0;do{scanf("%d",&grade);sum = sum + grade;i++; }while(grade!=-1) ;average = (sum+1) / (double)(i-1);printf("%f",average);return 0;}
(4)無限迴圈。程式如下:
#include<stdio.h>int main(void){int n = 0,sum = 0,count = 0; for(;;) { scanf("%d",&n); if(n < 0) { break; } else { sum += n; count++; } }if(count == 0) { count++;}printf("average = %.1f\n",(double)sum / count);return 0;}
從程式碼上來看,while迴圈以及do while迴圈比較簡潔,但是for迴圈和無限迴圈我認為更加易懂,綜合來說我認為while語句更加合適,因為輸入時學生數量是未知的,所以for迴圈不太好,而當我們輸入完事,迴圈條件在進入迴圈時已經明確,所以比do while迴圈好,相比無限迴圈的繁瑣,while迴圈比較簡潔,所以while迴圈比較好。
4.運行下面程式,輸入1到10,結果分別是什嗎?為什嗎?
運行程式(1)結果如:
運行程式(2)結果如:
原因:兩個程式結果輸出顯然不同,差別就在於一個為break語句跳出迴圈,另一個為continue。if語句後面的內容是break語句,表示跳出迴圈,假如為迴圈嵌套形式的時候,當迴圈執行完for語句的時候,到達break語句,break語句會直接跳出距離他最近的迴圈,而不執行下一個迴圈;但continue語句則不同,當迴圈執行完for語句的時候,到達continue語句,continue語句會略過continue後面的內容,執行距離他最近的迴圈的判斷。所以這道問題,用break語句顯然不能滿足要求,應該使用continue語句。
(三)實驗總結
1.求給定精度的簡單交錯序列部分和問題
(1)題目
本題要求編寫程式,計算序列部分和 1 - 1/4 + 1/7 - 1/10 + ... 直到最後一項的絕對值不大於給定精度eps。
(2)流程圖
(3)原始碼
#include<stdio.h>#include<math.h>int main(){int n = 1;double eps,a = 1.0,S = 1.0,sum = 0.0;scanf("%lf",&eps);do{ a = 1.0 / (S* pow(-1,n+1)); S = S + 3 ; sum = sum + a; n++;}while(fabs(a) > eps);printf("sum = %lf",sum);return 0; }
(4)實驗分析
問題:輸出0.0000000
解決辦法:將計算結果強制轉化為double型
(5)pta提交列表
2.猜數字遊戲
(1)題目
猜數字遊戲是令遊戲機隨機產生一個100以內的正整數,使用者輸入一個數對其進行猜測,需要你編寫程式自動對其與隨機產生的被猜數進行比較,並提示大了(“Too big”),還是小了(“Too small”),相等表示猜到了。如果猜到,則結束程式。程式還要求統計猜的次數,如果1次猜出該數,提示“Bingo!”;如果3次以內猜到該數,則提示“Lucky You!”;如果超過3次但是在N(>3)次以內(包括第N次)猜到該數,則提示“Good Guess!”;如果超過N次都沒有猜到,則提示“Game Over”,並結束程式。如果在到達N次之前,使用者輸入了一個負數,也輸出“Game Over”,並結束程式。
(2)流程圖
(3)原始碼
#include<stdio.h>int main(){int M,N,n = 0,math;scanf("%d%d",&M,&N);do{ n++; scanf("%d",&math); if(math<0) { printf("Game Over"); break; } else if(n>N) { printf("Game Over"); break; } else if(math==M) { if(n==1) { printf("Bingo!"); break; } else if(n==2||n==3) { printf("Lucky You!"); break; } else { printf("Good Guess!"); break; } } else if(math<M) { printf("Too small\n"); } else if(math>M) { printf("Too big\n"); } }while(1);return 0;}
(4)實驗分析
問題:輸入正確答案後,仍然輸出gameover
解決辦法:在Bilgo加上exit(0)
(5)pta提交列表
3.求奇數和問題
(1)題目
本題要求計算給定的一系列正整數中奇數的和。
(2)流程圖
(3)原始碼
#include <stdio.h>int main(){int N,sum=0; while(1) { scanf("%d",&N); if(N%2!=0&&N>0) { sum+=N; } if(N<=0) { break; } }printf("%d",sum);return 0;}
(4)實驗分析
問題:輸入-1後,-1也假如計算
解決辦法:沒有及時退出迴圈,將迴圈變數減一次,
(5)pta提交列表
(四)部落格互評
李曉曉http://www.cnblogs.com/Reloaded/p/7825734.html
劉夢醒
滕文清
C語言程式設計第六次作業——迴圈結構(2)