C語言程序設計第五次作業
一:改錯題:
錯誤一:輸入所給代碼段,執行編譯命令,編譯錯誤,錯誤信息如下:
錯誤信息:
該錯誤信息指向第十三行:
錯誤原因:經過檢查,發現該行的for語句后多出一個“;”(分號),導致編譯器無法識別該語句的斷句,出現編譯錯誤。
改正方法:將多余的分號刪去。
錯誤二:繼續編譯,提示編譯錯誤,錯誤信息如下:
錯誤信息:
該錯誤指向第17行。
錯誤原因:13行的for語句后有多條語句,但是for后並未添加“{}”(大括號)。
改正方法:分別在第13,17行上添加“{}”(大括號)。
錯誤三:繼續編譯,提示錯誤信息如下:
錯誤信息:
錯誤原因:經過回頭檢查,發現在for語句的圓括號中,分別表示fahr初值,判斷范圍以及步長的語句之間的分隔符為“,”(逗號),而非“;”(分號)。
改正方法:將使用錯的 符號改為“;”(分號)。
編譯成功,如圖:
錯誤四:運行程序,輸入樣例數據“32 35”,發現對應的值輸出不符合預期,如圖:
錯誤原因:該錯誤為典型的輸出0錯誤,根據之前總結,可以初步判定為數型的聲明以及計算過程中的數型轉換錯誤,經過檢查,首先發現第16行的輸出語句中對應華氏度數的格式化輸出符號有問題,在聲明時以及輸出時均為int型,但是輸出時卻格式化為浮點型。如圖:
改正方法:將對應華氏度的輸出符號改為對應整形輸出的“%3d.
錯誤五:繼續運行,輸入樣例“32 35”,結果如下:
仍不符合預期,繼續按照數型的思路去查錯。
錯誤原因:經過查證,發現溫度轉換的計算式有誤,如圖:
原題設應為c = 5×(f-32)/9。
改正方法:將計算式改正,如圖:
錯誤六:樣例數據不變,輸出結果如下:
比預期多出數組數據。
錯誤原因:原題設為每次循環,華氏度的溫度增加2,而在源代碼的for語句中,每次循環華氏度只增加1.
改正方法:將循環后華氏度的增量改變為+2。如圖:
再次輸入樣例數據“32 35”,結果如圖:
該組數據符合題設,再次輸入另一組數據“40 30”,結果如圖:
符合預期。
為保證臨界值的准確性,輸入“32 32”,結果如圖:
符合預期。
輸入“34 34”,結果如圖:
符合預期。
符合預期,改正結束。
附上改正后的代碼:
#include <stdio.h>
int main(void)
{
int fahr , lower, upper; /* fahr表示華氏度 */
double celsius; /* celsius表示攝氏度 */
printf("Enter lower:");
scanf("%d",&lower);
printf("Enter upper:");
scanf("%d",&upper);
printf("fahr celsius\n"); /* 顯示表頭 */
/* 溫度轉換 */
for (fahr = lower ;fahr <= upper;fahr += 2)
{
celsius = 5 * (fahr - 32.0) / 9 ;
printf(" %3d %6.1f\n", fahr, celsius);
}
return 0;
}
二:學習總結:
1:根據所給源代碼總結:
1)首先運行程序,按序輸入1~10,運行結果如下:
2)實驗分析:
①首先定義三個整形變量,分別存儲用戶輸入數據,奇數的數目,偶數的數目。
②進入for循環,
i= 1,判斷條件為真。進入循環體。
③用戶輸入一個整型變量num。此時筆者輸入的值為1.
④進入選擇語句。判斷輸入的值能否被2整除。
⑤判斷結果為假,執行else語句。
即odd++,此時odd的值為1.
⑥回到for循環。i=2.條件為真。
⑦繼續輸入數據,筆者輸入2.此時num = 2.
⑧進入選擇語句,判斷為真,執行even++,此時even = 1.
.....................................
⑨輸入十次后,i = 11,不符合for循環的條件,執行for循環后面的語句。輸出even以及odd的值。就筆者輸入的數值而言,此時odd,even均=5.
程序終止。
3)該程序的主要功能是用戶輸入10個整型數據,由系統判斷該數值是奇數還是偶數,10個數輸入完畢后統計奇數與偶數的個數。
2:增量運算符:
(1)運行所給程序,結果如下:
單獨分析該程序,只是單純輸出i,j的值,其中的自增運算符不涉及其他運算,因此在本例中增量運算符不構成影響,但是增量運算符的前綴與后綴格式實際上是影響計算的。
(2)運行程序2:
①將所給源代碼輸入編譯器並執行,結果如圖:
②運行過程分析:
本案例說明增量運算符的前綴與后綴影響運算過程與結果。該程序首先聲明兩個整型變量i,j,並賦初值2.執行第一條輸出語句,由於i的增量運算符為后綴形式,因此先執行輸出語句,再對i執行增量操作層,所以b的值輸出為2,即為增量前的值。而j的輸出語句中,j為前綴形式,因此首先對j執行增量操作,再執行輸出命令,因此j輸出的值為3,而實際上在計算機內部,i與j此時的值都為3,下面稍微修改程序,用以驗證。
修改后的代碼如下:
#include <stdio.h>
int main()
{
int i,j;
i = 2;
j = 2;
printf("%d\n",i++);
printf("%d\n",++j);
printf("%d %d",i,j);
return 0;
}
筆者在最后又增加了一條輸出語句,且為執行其他操作,用以觀察i,j實際的值。運行修改后的程序,結果如下:
可以看到,i,j的值均為3,證明上述分析正確。
下面再給出一個與運算有關的更簡單的程序,如下:
#include <stdio.h>
int main()
{
int i = 2;
i = i++ * 2;
printf("i = %d\n",i);
return 0;
}
首先給i賦初值2.此時增量運算符為后綴形式,運行結果如下:
此時i的值為4,緊接着修改程序,將“i++”改為“++i”,即將后綴改為前綴。
再次運行,結果如下:
可以發現,在i的初值不變的情況下,i的運算結果出現了不同。因此較為簡明的解釋為,前綴形式的增量/減量運算符,在進行運算時,先對被賦予增量/減量的變量的值執行增/減量操作再執行后續運算,而后綴則相反,先執行其他運算,再將變量的值執行增/減量操作。因此在確定增/減量運算時一定要合理分析其前/后綴形式的使用。
3)關於循環語句的大括號:
①首先按序執行所給代碼,之后加以分析總結。
程序1:結果如圖:
輸出為一行5個星號。
程序二:結果如圖:
輸出同樣為一行5個星號。
程序3:結果如圖:
輸出為五行各1個星號。
程序4:結果如圖:
輸出為一行5個星號。
④下面給出分析:
首先分析程序1和2,1和2的主要區別在於縮格不同,但是再通過結果分析,結果上二者完全相同,效果完全相同,因此證明循環體的認定與縮格並沒有關系。
緊接着結合3與4,這二者的區別在於大括號括起的位置不同。但是輸出結果完全不同,可以從執行過程分析。以第1次循環為例。執行順序為先進入循環的判斷部分,i = 1滿足條件,進入循環,執行星號與換行的輸出語句,之后找到大括號,並判斷該次循環結束,因此每次循環實際上都輸出了一個星號與一個換行符。
之后是4的分析,仍然以第一次循環為例,i的值為1,進入循環判斷,判斷為真,進入循環體內,執行星號的輸出語句,檢測到大括號,認為本次循環結束,並重復執行五次,輸出五個星號,最后一次i > 5,條件判斷為假,跳出循環,執行for循環后的換行符的輸出語句,輸出一個換行符。
因此從數值上講,1輸出了五個星號與五個換行符,而4輸出了五個星號與1個換行符。因此可以證明,循環體的判定與縮格無關,而與大括號有關。系統在進入循環時,會以大括號為界來實現循環體的判定。
因此,單從循環體的判斷而不是輸出目的而言,1和2都是錯誤的,3和4都是正確的,只不過實現目的不同。因此,循環體的判定總結而言就是通過大括號的配對來判定。即尋找for后的左大括號與循環體后的右大括號。
4)其它總結:
首先關於本章的內容,實際上可以總結的大多數都在上面的案例中。但是有一些細節是總結不完的。
首先是復合運算符,實際上這種運算的本質是將賦值運算與算數運算復合的結果。參照博文:
http://blog.csdn.net/lyh__521/article/details/49622601
關於其優點最顯著的兩點在於其可以將同一變量重復使用,此外,當算數表達式較長且涉及較多變量時,太長太多的算數運算符顯然顯得繁瑣以及拖沓,因此合理使用復合運算符,能顯著提高代碼的可讀性以及簡潔性。
其次是關於逗號運算符。逗號運算符的基本性質有兩條,第一是其運算優先級為C語言中最低的,第二,其右結合性,逗號運算符的運算過程為將從左至右最后一個逗號后的值作為 整個表達式的值輸出,下面給出一段代碼:
#include <stdio.h>
int main(void)
{
int num1, num2 , num3;
num2 = 2;
num3 = 3;
num1 = 18+ (num2+2 * 2,num3+4);
printf("%d",num1);
return 0;
}
其中就用到了逗號運算符,且在括號中,還涉及了算數運算以及優先級較高的乘法運算。結果如下:
最終結果為25.
可以看到,括號中的“num2 + 2 * 2”就像是憑空消失了一般,實際上並不是,只是因為逗號運算符的結合性以及只取最右表達式的值的特性,使得整個括號的值為“num3 + 4”,即等於7,因此結果為18 + 7 =25.
正因為這種性質,使逗號運算符在順序求值上有很大的用途。也希望通過這個例子使同學更加理解這種運算符的運算規則。
最后是循環結構的使用方面。
第一,循環條件的使用實際上是十分廣泛的,特別是對於一些涉及重復操作的實際問題,例如輸入學生成績計算均值以及及格人數的問題。若是只有五個同學還好,不使用循環結構的情況下首先定義五個整形變量存放學生的成績,之后定義一個int型變量存放五位同學成績的總和,之后定義一個int型變量來存放及格人數,之后是定義一個double型變量存放均值.............................
五個還好,那么十個呢...100....1000000........
顯然定義那么多變量並不現實。這種情況下就能極大地體現出循環結構的優勢,即變量復用,重復操作的快捷性。
因此,回到開頭,for循環的適用范圍即為重復操作較多且不含更多變數的情況。
實際上for循環也有一些妙用,下面給出本次作業中的求學生成績的均值及及格人數的改版來說明:
#include<stdio.h>
int main(void)
{
int score = 0,sum = 0,pass = 0,i = 0;
for(;;) //此處判斷循環的條件為空
{
scanf("%d",&score); //輸入成績
if(score < 0) //判斷輸入成績是否小於0,此處以成績小於0為結束循環的信號
{
break;
}
else
{
sum += score;
if(score >= 60) //計算及格人數
{
pass++;
}
i++;
}
}
printf("average = %.1f\n",(double)sum / i);
printf("count = %d",pass);
return 0;
}
首先可以看到,在本案例中的for循環的判斷語句中,是不存在任何語句的,這就意味着在循環體內如果不添加結束循環的條件的話,這個循環是會無限進行的,但是筆者在循環體內增加了判斷分數是否小於0的選擇結構,即在此以小於0為結束循環的“暗號”,因此這個程序就實現了可以計算任意多個學生平均分以及及格人數的功能,所以適當利用這種手法,可以獲得強大的功能,只不過這種手法的使用需要注意的一點在於for后的括號內雖然可以沒有語句,但是表示分隔的兩個分號一定不能丟,一定不能丟,一定不能丟!!!!!!!!!
(3)實驗總結:
一:輸入學生數量以及成績求成績均值與及格人數:
1:流程圖:
2:源代碼:
#include<stdio.h>
int main(void)
{
int score = 0,count = 0,i = 1,sum = 0,pass = 0;
scanf("%d",&count);
if(count == 0 )
{
sum = 0,pass = 0;
}
else
{
for(i = 0;i < count;i++)
{
scanf("%d",&score);
sum += score;
if(score >= 60)
{
pass++;
}
}
}
printf("average = %.1f\n",(double)sum / i);
printf("count = %d",pass);
return 0;
}
3:實驗分析:
該題主要使用了簡單的for循環結構以及if else選擇結構,總體難度較低。筆者並未遇到太多困難,只不過要說明的地方在於幾個數型轉換的問題,在變量較多又不適合全部定義為double型的情況下,可以適當使用強制轉換來達到目的。另一點在於除0的問題,筆者有許多同學都出現過這樣的錯誤,因此在某個變量(本題中為i)的值可能為0且做分母時,一定要判斷其是否存在直接被使用的風險,在本題中保險起見筆者將其初始化為1,從而避免這種情況的發生。
雖然在代碼階段筆者未遇到錯誤,但是在流程圖的編輯階段卻出現了錯誤。
錯誤1:筆者將流程圖制作完成后,輸入樣例數據“5 77 54 92 73 60”,前期並未出現問題,但是當筆者輸入5個成績后,卻發現仍在提示輸入,進入死循環。
錯誤原因:在循環體內未添加i的自增函數,如圖:
改正方法:在循環體的最后添加“i = i + 1”,確保每一次循環i的值會增加1.
4:本題提交列表:
二:判斷到底是不是太胖了:
1:流程圖:
2:源代碼:
#include<stdio.h>
#include<math.h>
int main(void)
{
int count= 0,i = 0;
double high = 0.0,weight = 0.0,standard = 0.0;
scanf("%d",&count);
for(i = 1;i <= count;i++)
{
scanf("%lf%lf",&high,&weight);
weight /= 2;
standard = (high - 100) * 0.9;
if(fabs(standard - weight) < standard * 0.1)
{
printf("You are wan mei!\n");
}
else if(standard - weight < 0)
{
printf("You are tai pang le!\n");
}
else
{
printf("You are tai shou le!\n");
}
}
return 0;
}
3:實驗分析:
本題主要使用for循環以及if else選擇結構的使用。實際上與前幾題相近,只不過這道題上比較使人疑惑的地方在於if else的選擇條件上。
錯誤1:筆者輸入樣例數據“3 169 136 150 81 178 155”,結果如下:
可以看到,第三組數據得到的結果不符合題意,因此回頭檢查。
錯誤原因:經過檢查,發現在判斷胖和瘦的選擇語句中的條件有誤,如圖:
該處的判斷實際上已經不需要加上絕對值,只需判斷標准體重減去實際體重的值是否大於0即可,若大於零,則證明實際體重小於標准體重,且偏差值是大於10%的。
改正方法:將絕對值符號去掉。
4:本題提交列表:
三:統計學生成績:
1:流程圖:
由於Reptor中沒有switch結構,因此由if else結構代替。
2:源代碼:
#include<stdio.h>
int main(void)
{
int count = 0,A = 0,B = 0,C = 0,D = 0,E = 0,i = 0,score = 0;
scanf("%d",&count);
for(i = 1;i <= count;i++)
{
scanf("%d",&score);
switch(score / 10)
{
case 10:case 9:A++;break;
case 8:B++;break;
case 7:C++;break;
case 6:D++;break;
default:
E++;
}
}
printf("%d %d %d %d %d",A,B,C,D,E);
return 0;
}
3:實驗分析:本題實際上是前幾次練習的又一次改版,只不過加入了for循環的結構,並不存在太大問題。因此...好吧...真的沒出錯.........
4:本題提交列表:
四:找出最小值:
1:流程圖:
此處用int型最大值取代C語言中的“INT_MAX”。
2:源代碼:
#include<stdio.h>
#include<limits.h>
int main(void)
{
int num = 0,n = 0,min = INT_MAX,i = 0;
scanf("%d",&n);
for(i = 1;i <= n;i++)
{
scanf("%d",&num);
if(num <= min)
{
min = num;
}
}
printf("min = %d",min);
return 0;
}
3:實驗分析:
本題主要還是使用for循環與if else結構,雖然仍然是之前練習的改編,但是顯然簡潔了許多,也體現出了for循環處理多數據重復操作問題的優越性。雖然筆者並未遇到問題,但是有一點需要說明,關於“limits.h”。
使用該庫函數的目的是保證無論用戶輸入數值多大,都能保證輸入的值能被存儲到下一循環中去比較的變量中去,因此省去不必要的數值交換過程。關於錯誤分析...好吧...這個真的沒有...
4:本題提交列表:
四:博客互評:
劉暢:http://www.cnblogs.com/LLIU/p/7810044.html
第八題的實驗總結只寫了第一點,后面沒有了。
陳魔(真的不不知道同學的名字,希望下次注明一下):
http://www.cnblogs.com/liumiaomiao520/p/7795587.html
(1)第一題的錯誤都用紅筆標注出來啦,很清晰明了。
(2)第二題有的圖片格式不正確,導致沒有顯示出來。
(3)第二題總結的很完整,很完善,分析的有條例。
劉愷烜:http://www.cnblogs.com/liukaixuan/p/7812027.html
同學你的一個圖片沒有加載出來。
你在修改錯誤時將錯誤都用紅筆划了出來。而且你將比較大的流程圖切割開再在網頁上拼接上使得圖片更容易看清。這些都是我沒有做到應該向你學習的。
許天笑:http://www.cnblogs.com/snxtx/p/7812139.html
我覺得你寫的這個都比較清晰,而且解釋的比較詳細,每一點都很詳細,每道題的實驗分析說的很明確,向你學習。
郭玉霖:http://www.cnblogs.com/HBQ521/p/7803633.html
感覺每次你寫的很好,值得學習,。不出毛病。
范凱華:http://www.cnblogs.com/fkh1/p/7812032.html
內容詳細,知識點總結全面,排版清晰。
郭展旭:http://www.cnblogs.com/1234569ss/p/7801245.html
錯誤改正較為細致,對題目邊界值的測試較好,避免錯誤的發生。課下總結較好,在閱讀博文鏈接后學習到了很多,作業質量很高,值得學習。