C語言程序設計第六次作業——循環結構(2)
之前的博客園圖片沒處理好,對大家說一聲抱歉。希望大家能夠多多指出我的錯誤,我來認真修改 ^ - ^ !。
(1)改錯題
序列求和:輸入一個正實數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;
}
錯誤信息 1:

錯誤原因 :while后面的括號沒有加“;”。

改正方法:在while后面加上分號“;”。

編譯正確,繼續執行

錯誤信息 2:

錯誤原因:答案不正確,輸入和輸出用了%f

改正方法:在輸入和輸出的時候把“%f”改成“%lf”和“%.6lf”。

結果發現答案還是不正確:

錯誤原因:回頭發現do while里面的語句運行不下去了就換一種格式來寫
改正方法:把第一個程序改成第二個,如下:
do{
item = 1/ n;
s = s + flag * item;
flag = -flag;
n = n + 3;
}while( item < eps);
do
{
item=flag*1.0/(3*n-2);
s+=item;
flag=-flag;
n++;
}
while(fabs(item)>eps);
**因為在源代碼中出現了數學函數fabs(),所以要用include<math.h>。

運行結果:運行正確!

附上正確的源代碼:
#include<stdio.h>
#include <math.h>
int main()
{
int flag,n;
double eps,item,s;
printf("Input eps: ");
scanf("%lf",&eps);
flag = 1;
s = 0;
n = 1;
do
{
item=flag*1.0/(3*n-2);
s+=item;
flag=-flag;
n++;
}
while(fabs(item)>eps);
printf( "s = %.6lf\n",s);
return 0;
}
(二)學習總結
1.語句while(1)和for( ; ; )是什么意思?,如何保證這種循環能正常執行?
while(1)相當於while(ture)里面的循環條件一直為真,一直循環下去。
保證這種循環正常執行在后面加一個判斷並且為假,就直接跳出循環;或者加一個break;也可以跳出循環,保證這個循環能夠正常運行。
for( ; ; )表示為死循環。
因為for后的圓括號中,第一個分號前的內容是執行第一次循環前執行的,第二個分號前的內容是每次執行前都要判斷的(如果該處表達式的值為真,那么執行循環體,如果為假,那么就跳出循環體),第二個分號后的內容是每執行完一次循環體后執行的。
在循環體中使用break跳出循環體。
2.一般情況下,設計循環結構時,使用for、while、do while三種語句都可以,並且三種語句可以相互轉換,但是,在某些特定情況下,我們應該優先選擇某種語句來快速實現循環設計。如果有如下情況:
(1)循環次數已知
(2)循環次數未知,但循環條件在進入循環時明確
(3)循環次數未知,且循環條件在進入循環時未知,需要在循環體中明確
針對上面三種情況,分別采用什么循環語句實現比較好?對每種情況,用我們完成的兩次循環結構作業中的題目加以說明。
①用for的循環結構來寫。例如:
循環結構(1)中 7-2 統計學生平均成績與及格人數, 7-3 奇偶分家 7-8 找出最小值,給出7-3的源程序:
#include <stdio.h>
int main(void)
{
int N,i,n,a = 0,b = 0;
scanf("%d",&n);
for(i = 0;i < n;i++)
{
scanf("%d",&N);
if(N % 2 == 0)
{
a++;
}
else
{
b++;
}
}
printf("%d %d",b,a);
return 0;
}
②可以用while和do while的循環結構來寫。例如:循環結構(2)中 7-5爬動的蠕蟲,循環結構(1)中 7-4 到底是不是太胖了 給出7-5的源程序:
#include <stdio.h>
int main(void)
{
int N,U,D,head=1,time=0;
scanf("%d %d %d",&N,&U,&D);
while(1)
{
head+=U;
time++;
if(head>N)break;
head-=D;
time++;
}
printf("%d",time);
return 0;
}
③可以用do while的循環結構來寫。例如:循環結構(2)中 7-1 求給定精度的簡單交錯序列部分和 7-3 求奇數和,給出7-3的源程序:
#include <stdio.h>
int main()
{
int n = 0, sum = 0;
do
{
scanf("%d", &n);
if (n % 2 == 1)
sum += n;
} while (n > 0);
printf("%d\n", sum);
return 0;
}
3.有如下問題:輸入一批學生成績,以-1作為結束,計算學生的平均成績。
要求分別用for語句、while語句、do while語句三種循環語句實現,並說明你認為哪種形式更合適?
循環次數未知,且循環條件在進入循環時未知,需要在循環體中明確,所以我覺得用do while寫來比較合適。
4.運行下面程序,輸入1到10,結果分別是什么?為什么?
(1)
#include<stdio.h>
int main()
{
int n,s,i;
s = 0;
for(i = 1; i <= 10; i++)
{
scanf("%d",&n);
if(n % 2 == 0)
break;
s = s + n;
}
printf("s = %d\n",s);
return 0;
}
輸出結果:

(2)
#include<stdio.h>
int main()
{
int n,s,i;
s = 0;
for(i = 1; i <= 10; i++)
{
scanf("%d",&n);
if(n % 2 == 0)
continue;
s = s + n;
}
printf("s = %d\n",s);
return 0;
}
輸出結果:

這倆個源程序看上去沒什么倆樣,但是不同的地方就是第一個用的是break,而第二個用的是continue。結果一個輸出1,一個輸出25,因為第一個就執行一次s=s+n,而s為0,n為1,當第一次輸入1的時候就直接跳出循環就進行s=s+n,所以最后輸出1;
而第二個流程圖用continue倆控制循環條件,他進行判斷后不會跳出而是直接進行下一個,並且把能整除2的數過濾掉,所以最后輸出的是25。
(三)實驗總結
(1) 題目
7-1 求給定精度的簡單交錯序列部分和
(2) 流程圖


(3) 源代碼
#include<stdio.h>
#include<math.h>
int main(void)
{
int dom,flog;
double eps,sum,t;
flog=1;
dom=1;
sum=0;
scanf("%lf",&eps);
do
{
t=flog*1.0/(3*dom-2);
sum+=t;
flog=-flog; /*讓這個值改變*/
dom++;
}
while(fabs(t)>eps);
printf("sum = %.6lf",sum);
return 0;
}
(4) 實驗分析:
問題1:
第一次寫的時候有while的形式是用一下格式:
while(fabs(x) > eps)
{
t=flog*1.0/(3*dom-2);
sum+=t;
flog=-flog; /*讓這個值改變*/
dom++;
}
但是輸出的結果答案錯誤,這個問題糾結了很長時間。該程序需要先執行一次然后再進行循環,如果用while的形式就不能保證進行一次,所以該格式不能保證。我們要用do while的格式來寫。
do
{
t=flog*1.0/(3*dom-2);
sum+=t;
flog=-flog; /*讓這個值改變*/
dom++;
}
while(fabs(t)>eps);
問題2:答案錯誤

原因:while括號里面的條件判斷錯誤

解決方法:把"<="改成">"。

答案正確:

(5)本題PTA提交列表

(1) 題目:
7-2 猜數字游戲
(2) 流程圖


(3) 源代碼
#include<stdio.h>
int main()
{
int key, n;
scanf("%d %d",&key,&n); /*輸入倆個數*/
int i;
int m;
int flag = 0; /*定義一個數*/
for (i = 1;i <= n;i ++)
{
scanf("%d",&m); /*再次輸入一個數*/
if (m < 0)
break;
if (m > key)
printf("Too big\n");
if (m < key)
printf("Too small\n");
if (m == key)
{
if (i == 1)
{
flag = 1; /*為假,跳出*/
printf("Bingo!\n");
break;
}
if (i == 2 || i == 3)
{
flag = 1; /*為假,跳出*/
printf("Lucky You!\n");
break;
}
if (i > 3)
{
flag = 1; /*為假,跳出*/
printf("Good Guess!\n");
break;
}
}
}
if (flag == 0) /*為真,輸出*/
printf("Game Over\n");
return 0;
}
(4) 實驗分析
錯誤信息:一開始輸入產生隨機數,用了數學函數rand(),但是結果輸出錯誤。
原因:理解題意錯誤,不用函數就可以,直接輸入倆個數再進行循環就可以。
需要注意的:循環結束可以用break來實現。在本題需要定義一個量flag=0,如果后面的跟前面所定義的相等就判斷為真,如果不相等就判斷為假,並且在break的條件下進行跳出進行下一步的運算。
(5)本題PTA提交列表

(1) 題目
7-3 求奇數和
(2) 流程圖


(3) 源代碼
#include <stdio.h>
int main()
{
int n = 0, sum = 0;
do
{
scanf("%d", &n);
if (n % 2 == 1)
sum += n;
} while (n > 0);
printf("%d\n", sum);
return 0;
}
(4) 實驗分析
問題 : 用 if--for的形式輸入結果總是部分正確,例如下面的錯誤源程序
#include <stdio.h>
int main()
{
int n,i,s,sum;
sum=0;
scanf("%d",&n);
i=0;
for(i=0;i<n;i++)
{
scanf("%d",&s);
if(s<0)
{
break;
}
else
{
if(s%2!=0)
{
sum=sum+s;
}
}
}
printf("%d",sum);
}
原因:該程序不能用if for的形式來寫,它需要先循環一次,然后再進行循環。給出正確的源程序:
#include <stdio.h>
int main()
{
int n = 0, sum = 0;
do
{
scanf("%d", &n);
if (n % 2 == 1)
sum += n;
} while (n > 0);
printf("%d\n", sum);
return 0;
}
(5)本題PTA提交列表

(四)博客互評
針對移動、淫領四妓夜物 的博客園:
(1).實驗總結寫的很認真,值得我們學習!老鐵,沒毛病!繼續加油
針對郭玉霖的博客園:
(1).在學習總結的第三個題文字與圖片應該空一格,這樣看起來比較舒服。
(2).在實驗分析的時候應該把問題用截圖截下來並且圈出來,這樣別人才能知道你哪兒多了條件或者哪兒漏了條件。
針對ShizukaRi的博客園
(1).在改錯題應該把錯誤的源程序給出來並且改正給出正確的。
(2).學習總結只能用很認真來形容,向你學習,可以看出你學的很好。
(3).實驗總結的第二個流程圖看着有點別扭,希望以后盡量截圖好一點,大家能夠更好的看清楚。
