華中科技大學c語言實驗報告_第1頁
華中科技大學c語言實驗報告_第2頁
華中科技大學c語言實驗報告_第3頁
華中科技大學c語言實驗報告_第4頁
華中科技大學c語言實驗報告_第5頁
已閱讀5頁,還剩202頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

譯中科技大孚課程實驗報告課程名稱: C語言程序設計專業班級:計算機科學與技術1234班學號: U123412345姓名: OOO指導教師: O。O報告日期: OOOO年。月O日計算機科學與技術學院目錄TOC\o"1-5"\h\z\o"CurrentDocument"實驗1表達式和標準輸入與輸出實驗 1\o"CurrentDocument"實驗目的 1\o"CurrentDocument"實驗內容及要求 1\o"CurrentDocument"自設題 12\o"CurrentDocument"實驗小結 14\o"CurrentDocument"實驗2流程控制實驗 15\o"CurrentDocument"實驗目的 15\o"CurrentDocument"實驗內容及要求 15\o"CurrentDocument"自設題 29\o"CurrentDocument"實驗小結 34\o"CurrentDocument"實驗3函數與程序結構實驗 35\o"CurrentDocument"實驗目的 35\o"CurrentDocument"實驗內容及要求 35\o"CurrentDocument"自設題 49\o"CurrentDocument"實驗小結 53\o"CurrentDocument"實驗4編譯預處理實驗 54\o"CurrentDocument"實驗目的 54\o"CurrentDocument"實驗內容及要求 54\o"CurrentDocument"自設題 67\o"CurrentDocument"實驗小結 69\o"CurrentDocument"實驗5數組實驗 70\o"CurrentDocument"實驗目的 70\o"CurrentDocument"實驗內容及要求 70\o"CurrentDocument"自設題 96\o"CurrentDocument"實驗小結 97\o"CurrentDocument"實驗6指針實驗 98\o"CurrentDocument"實驗目的 98\o"CurrentDocument"實驗內容及要求 98\o"CurrentDocument"自設題 123\o"CurrentDocument"實驗小結 127\o"CurrentDocument"實驗7結構與聯合實驗 128\o"CurrentDocument"實驗目的 128\o"CurrentDocument"實驗內容及要求 128\o"CurrentDocument"自設題 171\o"CurrentDocument"實驗小結 177\o"CurrentDocument"實驗8文件實驗 178\o"CurrentDocument"實驗目的 178\o"CurrentDocument"實驗內容及要求 178\o"CurrentDocument"自設題 188\o"CurrentDocument"實驗小結 190\o"CurrentDocument"參考文獻 191實驗1表達式和標準輸入與輸出實驗1.1實驗目的(1)熟練掌握各種運算符的運算功能,操作數的類型,運算結果的類型及運算過程中的類型轉換,重點是C語言特有的運算符,例如位運算符,問號運算符,逗號運算符等;熟記運算符的優先級和結合性。(2)掌握getchar,putchar,scanf和printf函數的用法。(3)掌握簡單C程序(順序結構程序)的編寫方法。(4)掌握書寫實驗報告的格式與基本要求。1.2實驗內容及要求源程序改錯下面給出了一個簡單C語言程序例程,用來完成以下工作:(1)輸入華氏溫度f,將它轉換成攝氏溫度C后輸出;(2)輸入圓的半徑值r,計算并輸出圓的面積s;(3)輸入短整數k、p,將k的高字節作為結果的低字節,p的高字節作為結果的高字節,拼成一個新的整數,然后輸出;在這個例子程序中存在若干語法和邏輯錯誤。要求在計算機上對這個例子程序進行調試修改,使之能夠正確完成指定任務。#include<stdio.h>#definePI3.14159;intmain(void)4{intf;shortp,k;doublec,r,s;/*fortask1*/printf(€€InputFahrenheit:'');scanfT%d'',f);c=5/9*(f-32);print"“\n%d(F)=%.2f(C)\n\n”,f,c);13/*fortask2*/printfpinputtheradiusr:n);scanf(n%ff,&r);s=PI*r*r;printf(M\nTheacreageis%.2f\n\nM,&s);/*fortask3*/printfpinputhexintk,p:");scanf(n%x%x”,&k,&p);21newint=(p&0xff00)|(k&0xfTO0)?8;printf(Mnewint=%x\n\n°,newint);return0;24}解答:(1)錯誤修改:1)第2行的符號常量定義后不能有分號,正確形式為:#definePI3.141592)第3行的intmain(void)返回值類型和函數名應分開,正確形式為:intmain(void)3)第10行的scanf("%d”,f);在輸入內容時指向地址應使用&,正確形式為:scanf("%d”,&f)4)第11行的c=5/9*(f-32);由于f是int型,在運算時右側表達式會被截去小數部分,正確形式為:c=5.0/9*(&32);5)第12行的printf(41\n%d(F)=%.2f(C)\n\n”,f,c);由于c被定義為雙精度浮點數應使用占位符%If,正確形式為:prints"\n%d(F)=%.21f(C)\n\n”,f,c);6)第15行的scanf("%f',&r);由于r被定義為雙精度浮點數應使用占位符%If,正確形式為:scanfi["%lf,,&r);7)第17行的prints"\nTheacreageis%.2f\n\n",&s);由于s被定義為雙精度浮點數應使用占位符%If,正確形式為:printfl^"\nTheacreageis%.21f\n\n",&s);8)第17行的printf("\nTheacreageis%.2f\n\n",&s);在printf中不涉及對s的修改,應不用&,正確形式為:prints"\nTheacreageis%.21f\n\n",s);9)第20行的scanf("%x%x",&k,&p);由于k,p被定義為短整數,占位符應使用%hx,正確形式為:scanff%hx%hx",&k,&p);10)第21行的newint=(p&0xfR)0)|(k&0xflro0)?8中使用了一個未聲明的變量newint,應在使用前聲明,正確形式為:(6)shortp,k,newint;(注意,改動針對第六行)11)第21行的newint=(p&0xfTO0)|(k&0xffD0)<<8忽略了運算順序,應恰當使用括號改變運算順序,正確形式為:newint=(p&0xflTO0)|((k&0xflTO0)<<8);12)第21行的newint=(p&0xfTO0)|(k&0xflTO0)<<8位運算邏輯有誤,應恰當改變運算方式,正確形式為:newint=(p&0x1TO0)|((k&0x1TO0)?8);13)第22行的printff'newint=%x\n\n",newint);由于newint被定義為短整數,占位符應使用%hx,正確形式為:printf("newint=%hx\n\n",newint);(2)錯誤修改后運行結果:見圖1-1(查閱資料知1華氏度確為-17.22攝氏度;半徑為2的圓面積在保留2位小數且n取3.14159時面積確為12.57;將a2cd的高字節作為結果的低字節,a3a3的高字節作為結果的高字節,拼成一個新的整數,這樣的確得到a3a2,其中采用16進制是為了表達與驗證方便)InputPahrenheit:11<F>--17.22<C>inputtheradiusi*:2Theacreayeis12.57inputhexintk.p:a2cda3a3newint-a3a2圖1-1源程序改錯的運行結果1.2.2源程序修改替換下面的程序利用常用的中間變量法實現兩數交換,請改用不用第三個變量的交換法實現。#include<stdio.h>intmain(){inta,b,t;print/'Inputtwointegers:^^);scanfT%d%d,,,&a,&b);t=a,a=b,b=t;prinfC'\na=%d,b=%d”,a,b);return0;}解答:由于只能使用兩個變量,我們需要利用一個變量來保存兩個數的一些共同特征,而這些特征要能通過一定的運算返回初始的數,而若把兩數之和存放于第一個數中,通過依次均減去第二個數,可在恢復原來的數的同時將它們交換順序。替換后的程序如下所示:#include<stdio.h>intmain()(inta,b;printffTnputtwointegers:");scanf^s(n%d%dn,&a,&b);a=a4-b;b=a-b;a=a-b;printf("\na=%d,b=%d",a,b);return0;運行結果見圖1-2(1,2交換位置后確為2,1)InputtMointegers:12a-2,!>-1圖1-2源程序修改替換題的運行結果1.2.3程序設計(1)編寫一個程序,輸入字符C,如果C是大寫字母,則將C轉換成對應的小寫,否則C的值不變,最后輸出C。解答:首先,無論輸入什么字符,這個字符均具有相應的ASCII碼,所以我們無需檢測輸入是否合理,而在接受這個輸入之后,我們需要根據它的ASCII碼來判斷它是否為大寫字母,如果它是大寫字母,那么就把它變為小寫字母(減去A與a的ASCH碼值之差即可實現這個要求),而若該字符不滿足該要求,直接原樣輸出即可,算法見流程圖1-1,其余細節見程序注釋,程序如下。流程圖1-1程序設計題1的算法#include<stdio.h>intmain()intc;printf("輸入字符,如果它是大寫字母,則將它轉換成對應的小寫,否則原樣輸出:");c=getchar();〃通過getchar()來獲得字符對應的ASCII碼if(c<='Z'&&c>='A') 〃判斷是否為大寫字母c=c-('A'-'a');〃大寫字母變小寫printf("處理結果是:%c",c);return0;)測試:由于本題不涉及無效輸入,所以我們只需分析程序的幾種運行情況,其中可分為對大寫字母進行轉化為相對應的小寫字符;而對于小寫字母而言,程序不應該將其進行任何轉化;此外,對于非字母輸入我們也不應該轉化,具體測試數據見表1-1,測試結果見圖1-3?1-5。表1-1編程題1的測試數據測試用例程序輸入理論結果運行結果用例1Eee用例2eee用例3111對應測試測試用例1的運行結果如圖1-3所示輸入字符,如果它是大寫字母,則將它轉換成對應的小寫,否則原樣輸出:E見或結果是:e圖1-3編程題1的測試用例一的運行結果對應測試測試用例2的運行結果如圖14所示。盤翥矗如既是大寫字母’則將垂挨成對應的小弓否則原樣輸出一圖1-4編程題1的測試用例二的運行結果對應測試測試用例3的運行結果如圖1-5所示。輸入字符,如果它是大寫字母,則將它轉換成對應的小寫,否則原樣輸出:1七里結果是:1圖1-5編程題1的測試用例三的運行結果說明上述的運行結果與理論分析吻合,驗證了程序的正確性。(2)編寫一個程序,輸入無符號短整數x,m,n(0<m<15,1<n<16-m),取出x從第m位開始向左的n位(m從右至左編號為0?15),并使其向左端(第15位)靠齊。解答:由于題目中明確要求輸入無符號短整數,且目前我們缺少檢查輸入是否為整數的手段,所以本題并不檢查輸入的x是否合理;不過以我們目前的知識,我們可以根據題目要求對輸入的m,n是否合理進行檢查(僅檢查它們是否在合理范圍內,默認其為整數)。而在確認輸入合理之后,我們著手開始對問題進行處理,由于這是一個涉及到計算機內部數據的二進制運算的問題,相應地,我們在解決這個問題時也要利用C語言提供的位運算來完成相應的操作,首先,由于我們只需要x從第m位開始向左的n位,所以我們需要去掉x的其余部分(第m位之前的內容),同時從第m位開始向左的n位之后的內容也不再被需要,所以我們也將其去除。至于這去除的實現,為防止數據的丟失,我們不應直接對x進行操作,而應對我們之后會用到的邏輯尺進行操作,而有關邏輯尺的操作,我們可先使用十六進制數對其賦值,使其全為KOxffff,這樣較將0取反更方便),再進行相應的左移與右移(注意在移動時要分開進行,否則會由于編譯器對運算的簡化使部分該被清0的位保留為1),而后,我們再用我們取得的邏輯尺與x進行按位與運算,即可取出x中相應的二進制位,之后,再根據題目的要求,把x移動到指定的位置,最后,由于題目中使用的數字均為十進制數,所以我們的輸入與輸出均采用十進制數進行。其余細節見程序注釋,算法見流程圖1-2,程序如下。#include<stdio.h>intmain()unsignedshortintx,m,n,i;printf("輸入x(10進制)、m(0-15)和n(1?16-m):”);scanf(n%hu%hu%huH,&x,&m,&n);if(m>=0&&m<=15&&n>=1&&n<=l6-m)〃判斷輸入是否合理{i=Oxffff; 〃準備位運算所需邏輯尺i?=m; //確定變換起始位置i?=16-n; 〃確定變換作用長度i?=16-m-n;〃進入變換位置/*注意在移動時要分開進行,否則會由于編譯器對運算的簡化使部分該被清。的位保留為1*/x&=i;x?=16-m-n;〃左移printf("經過變換得到:%hu",x);}elseprintf("輸入錯誤,請檢查您的輸入)〃提示輸入不合理return0;流程圖1-2程序設計題2的算法測試:由于本題中涉及了對錯誤輸入的排除,所以我們需要對程序能否正確排除這些錯誤的輸入進行測試,同時,我們也需要對程序的基本功能進行檢查,不過由于本題涉及到位運算,這使得對結果的驗證較為困難,我們需要合理的設計測試數據并將其轉化二進制數以供驗證,再將所得的二進制數轉為十進制數并程序輸出的十進制數進行比對,以驗證程序的正確性(即使采用十六進制輸入輸出也不夠結果也不是十分顯然,故不采用),測試數據見表1-2,測試結果見圖1?6?1-8。表1-2編程題2的測試數據或試厚孑物入3論逑累運行逑MSWXmNumi0000000000011001(25)3,H-MigMllOOOeOOOOOO0000K49152的1521101010110000011(54659)161勒入槽次:m(aeTs3?檢資臉入用的31101010110000011C54659)135輸入Cn(ft£^3)位交帔入對應測試測試用例1的運行結果如圖1-6所示輸入x(10進制)、m15)和n([?16-e):2532遂過變換得至49152圖1-6編程題2的測試用例一的運行結果對應測試測試用例2的運行結果如圖1-7所示。輸入X(10進制)、m(0?15)和n(1?16-m):54659161輸入錯誤,請密查您的輸入圖1-7編程題2的測試用例二的運行結果對應測試測試用例3的運行結果如圖1-8所示。輸入x(1。進制)、m(0?15)和n(1?16-m):54659135強入錯誤,請愈查您的輸入圖1-8編程題2的測試用例三的運行結果說明上述的運行結果與理論分析吻合,驗證了程序的正確性。(3)IP地址通常是4個用句點分隔的小整數(即點分十進制),如32.55.1.102o這些地址在機器中用無符號長整形表示。編寫一個程序,以機器存儲的形式讀入一個互聯網1P地址,對其譯碼,然后用常見的句點分隔的4部分的形式輸出。例如,整形676879571二進制表示就是:00101000010110000101110011010011,按照8位一組可表示為:408892211,由于CPU處理數據的差異,它的順序是顛倒的,所有最終格式為211.92.88.40。解答:首先,這依然是一個涉及到位運算的題目,所以我們依然會用到按位操作與邏輯尺,而邏輯尺的制備與使用均與我們在程序設計題2中所使用的方法大體相同,例如我們使用十六進制數制取邏輯尺,同時盡管從原理上說,我們只需要一個邏輯尺(在每次使用后對其進行移動即可),但這樣寫成的程序不夠明To而在取得了邏輯尺之后,我們再進行按位與運算,以達到取出各二進制位的效果。不過,本題與程序設計題2的不同之處在于,我們需把取出的數進行移動的位數是固定的,但需要注意的時,正如題目中所提到的由于CPU處理數據的差異,我們需要將我們取出的數據進行重新排序,而且,由于我們輸出的是IP地址,所以我們需要在輸出中添加相應的句點。此外,盡管本題中可能出現非數字輸入,但由于我們目前沒有有效的手段進行檢測,所以我們默認所有的輸入都是合理的。其余細節見程序注釋,算法見流程圖1-3,程序如下。輸入無符e長整形數中流程圖1-3程序設計題3的算法#include<stdio.h>intmain()iounsignedlongintip,m1,m2,m3,m4,p1,p2,p3,p4;printf("輸入長整數形式的ip地址:");scanf("%lu",&ip);ml=OxflTOOOOOO;〃各分段邏輯尺m2=OxOOffDOOO;//各分段邏輯尺m3=OxOOOOfTOO;//各分段邏輯尺m4=OxOOOOOOff;〃各分段邏輯尺pl=(ip&ml)?24;//取出各部分二進制數p2=(ip&m2)?16;〃取出各部分二進制數p3=(ip&m3)?8;//取出各部分二進制數p4=(ip&m4);〃取出各部分二進制數printf("這個ip地址常規形式為:%lu.%lu.%lu.%lu",p4,p3,p2,pl);//按要求格式輸出return0;)測試:由于本題默認所有的輸入都是合理的,所以我們不對輸入的數據是否位整數進行檢查(盡管這是必要的,我們會在以后的實驗提到如何實現)。同時,我們注意到本題的可能執行情況在正常情況下只有一種(但為了使驗證結果具有說服力,我們依然需要數組測試數據),且本題的測試數據相當龐大(特別是將其轉化為二進制后),所以我們需要借助計算機將其轉化為二進制數并進行相應的人工轉化并驗證。此外,本題的驗證還有一個關鍵之處,即IP地址的輸出順序是否符合要求,具體測試數據見表1-3,運行結果見圖1-9?1-11。表1-3編程題3的測試數據測試用例程序輸入理論結果運行結果長整形形式二進制(十進制)用例14564561300000010⑵10111000(184)01111111(127)00101101(45)45.127.184.245.127.184.2用例212345678900000111(7)01011011(91)11001101(205)00010101(21)21.205.91.721.205.91.7用例378965432100101111(47)00010001(17)00101011(43)00110001(49)49.43.17.4749.43.17.47對應測試測試用例1的運行結果如圖1-9所示輸入長整數形式的iP地址:45645613這個ip姬址常規形式為:45.127.184.2圖1-9編程題3的測試用例一的運行結果對應測試測試用例2的運行結果如圖1-10所示。黔球錯勰拶巴;梵寬7圖1-10編程題3的測試用例二的運行結果對應測試測試用例3的運行結果如圖1-11所示。麟球賽勰拜址■鱉舐7圖1-11編程題3的測試用例三的運行結果說明上述的運行結果與理論分析吻合,驗證了程序的正確性。1.3自設題問題:仿照程序設計題3,設計一段程序,當我們輸入一段IP地址(常規形式)時,輸出其長整數形式的IP地址。解答:本題中由于需要輸入IP地址,而IP地址是由句點分隔的,所以我們需要對格式化輸入函數進行相應設置,使之能正常輸入IP地址(否則會造成輸入域混亂,導致不可預知的錯誤),而當我們按格式輸入了IP地址之后,我們只需要將程序設計題3的程序中的處理順序逆轉即可(由于我們可以先進行按位與運算,再進行移動,所以我們可以只使用一個邏輯尺;此外,關于CPU處理數據順序的差異,可以在輸入時即交換順序,即用戶按實際順序輸入數據,而程序按CPU處理順序接受數據)。算法見流程圖1-4,其余細節見程序注釋,程序如下。#include<stdio.h>intmain(){unsignedlongip4,ip3,ip2,ipl,ip; 〃會發生移動,故其最大值并非128,不采用char型ip=0;〃使用前需按需初始化為0printf("請輸入常規形式的1P地址:");scanf^s("%lu.%lu.%lu.%lu",&ip4,&ip3,&ip2,&ipl);〃再輸入時即按CPU順序交換了存儲順序

unsignedlongm;m=OxOOOOOOfF;〃在移動之前,僅有前8位需取出〃由于已經發生移動,故此處無需交換順序ip+=(ipl&m)?24;〃由于已經發生移動,故此處無需交換順序ip+=(ip2&m)?16;ip+=(ip3&m)?8;ip+=(ip4&m);printf("該IP地址的長整數形式為:%lu\n",ip);return0;流程圖1-4流程圖1-4自設題的算法測試:本題的測試只需將程序設計題中的測試數據輸入輸出逆轉即可(理論分析由于與程序設計題3完全相同,故略去),測試數據見表1-4,程序運行結果見圖1-12,程序運行結果與理論相符,驗證了程序的正確性。表1-3編程題3的測試數據測試用例程序輸入理論結果運行結果用例145.127.184.24564561345.127.184.2用例221.205.91.712345678921.205.91.7用例349.43.17.4778965432149.43.17.47理論分析由于與程序設計題3完全相同,故略去I測試用例1請輸入常規形式的IP地址:45.127.184.2該IP地址的長整數形式為:45645613測試用例2請輸入常規形式的IP地址:21.205.91.7該IP地址的長整數形式為:123456789測試用例3請輸入常規形式的IP地址:49.43.17.47該IP地址的長整數形式為:789654321圖1-12自設題程序的運行結果1.4實驗小結這是我第一次撰寫的實驗報告,自然,會有很多的不完善之處,由于目前的知識有限,諸如流程控制,數組,編譯預處理等編程技術都無法使用,而這些技術的使用無疑會給本次實驗程序的編制帶來極大的方便。誠然,不使用這些手段進行編程的能力也是十分重要的,而本次實驗恰好鍛煉了我們的此種能力,使我們使用簡單而基本的運算與流程,去實現一些稍復雜的程序。而即使是這樣較為基本的編程實踐中,我也發現了很多自己平時并不注意的問題。比如在最開始我的部分返回值類型不為void的main函數卻沒有返回值,這使得我的程序在邏輯上并不完整(盡管運行結果看上去是對的)。而除了在編程上的體會之外,我對實驗報告的書寫也略有感觸。這是我第一次書寫實驗報告,在書寫實驗報告的過程中,我遇到了很多困難,比如流程圖的繪制和圖與表格的命名,但在指導老師與助教熱心幫助下,我逐一克服了這些困難,并在解決這些困難的同時使自己的能力也得到了相應的提高。實驗2流程控制實驗2.1實驗目的(1)掌握if-else,do-while,switch-case等流程控制語句之用法。(2)能正確理解各流程控制語句所包含的邏輯關系。(3)能正確理解各流程控制語句之間不同,并用這些不同優化自己的程序。(4)能用流程控制語句編寫簡單的C語言程序。2.2實驗內容及要求2.2.1源程序改錯下面是計算s=n!的源程序,在這個源程序中存在若干語法和邏輯錯誤。要求在計算機上對這個例子程序進行調試修改,使之能夠正確完成指定任務。例如,8!=40320#include<stdio.h>intmain(void)(inti,n,s=l;printf{nPleaseentern:n);scanfifM%dn,n);fdr(i=l,i<=n,i-H-)s=s*i;printff%d!=%dn,n,s);return0;II}解答:(1)錯誤修改:1),scanf在輸入時應指向單元地址而非單元名稱,正確形式為:scanf("%d",&n);2),fbr語句表達式1,2,3之間應用;分隔,正確形式為:(2)錯誤修改后運行結果:見圖2-1(8的階乘確為40320)Pleaseentern:8Bt-40320圖2-1修改后的運行結果2.2.2源程序修改替換(1)修改第1題,分別用while和do-while語句替換for語句。解答:在使用while語句時,其與for語句的主要差異在于沒有一個專門的語句為i賦予初值,所以需要在進入循環之前,為i賦予初值1。而在其他的地方,則與經ibr語句的處理基本一致,替換后的程序如下所示:#include<stdio.h>intmain(void)(inti=l,n,s=l;//相較于for語句的關鍵printf("Pleaseentern:");scanfi("%d",&n);while(i<=n)(s=s*i;iH;)printf("%d!=%d",n,s);return0;}運行結果見圖2-2(8的階乘確為40320)Pleaseentern:77!?5040圖2-2while結構下的運行結果在使用do-while語句時,其與while語句的差異特別體現在無論n的值為何值,其都會進行一次循環,但值得注意的是,這一次額外的循環(發生于輸入n=0時)在i的初值為1時,并不會改變s的值,從而并不需要進行額外的處理,調換循環體與條件的位置即可,替換后的程序如下所示:#include<stdio.h>intmain(void)inti=l,n,s=l;printf("Pleaseentern:");scanfi("%d",&n);do{s=s*i;i++;}while(i<=n);〃交換條件與循環體的位置printf("%d!=%d",n,s);return0;)運行結果見圖2-3(6的階乘確為720)Pleaseentern:66?=720圖2?3do-while結構的運行結果(2)修改第1題,要求輸入改為“整數s”,輸出改為“滿足n!^s的最小整數nwo例如,輸入整數為40310,輸出結果為n=8。解答:這個問題,從本質上來說,是要找到一個數,使它的階乘的值大于等于所輸入的n的值,且要求這個數的值最小。階乘的實現,可借助之前編寫的程序,并將它作為一個子函數進行調用,使主函數更加簡明,數的尋找可借助簡明的while循環來實現,程序如下所示,#include<stdio.h>intf(intp){intd=l;inti;fbr(i=l;i<=p;i-H-)d*=i;returnd;)intmain(void){inti,n=l,s=l,sl;print/'Pleaseenters:n);scanf(f,%dM,&sl);while(sl>s)〃比較n++;s=f(n);〃計算階乘}printf("n=%d\n",n);return0;運行結果見圖2-4(40320=8!>40312>7!=5040)Pleaseenters:40312m=8圖2-4第2題程序的運行結果2.2.3程序設計(1)假設工資稅金按以下方法計算:x<1000元,不收取稅金;1000Wx<2000,收取5%的稅金;20000x<3000,收取10%的稅金;30000x<4000,收取15%的稅金;4000<x<5000,收取20%的稅金;x>5000,收取25%的稅金。編寫一個程序,輸入工資金額,輸出應收取稅金額度,要求分別用if語句和switch語句來實現解答:首先對輸入的x進行判斷,判斷其是否是一個合理的工資數目,如果不合理(比如說是負數),就輸出提示輸入不合理的內容。而如果其輸入合理,則通過對x值的判斷,決定其對應的稅收方式,而后進行計算。需要注意的是,在if-else結構下,對x的區間劃分比較顯然,但由于switch語句只能選擇整數,結合x的分段區間寬度均為1000,于是將x除以1000后再強制轉換類型為int在進入各case進行運算,同樣重要的是,注意到switch語句的特點,我們可以巧妙的利用其特性,簡化程序語句。其余細節見程序注釋,算法見流程圖2-1與2-2,程序如下。#include<stdio.h>intmain(void)doublex,tax;printf("請輸入您的工資金額:,scanf_s("%lf,&x);if(x<0)printf("您輸入了錯誤的工資,請檢查您的輸入H");〃檢查輸入是否合理else(if(x<1000)tax=0;elseif(x<2000)tax=(x- 1000)*0.05;elseif(x<3000)tax=(x- 2000)*0.10+ 1000* 0.05;elseif(x<4000)tax=(x- 3000)*0.15+ 1000* (0.10 +0.05);elseif(x<5000)tax=(x- 4000)*0.20+ 1000* (0.05 +0.10+0.15);elsetax=(x-5000)*0.25+1000*(0.05+0.10+0.15+0.20);printf("(IFELSE方式)您須交稅:%.21f元\n",tax);tax=0;〃為利用switch語句的特點,會進行累加運算,此處需將tax清零switch(((int)x)/1000)//對switch僅能選擇整數的處理(default:tax+=(x-5000)*0.25;x=5000;〃注意到switch的特點case4:tax+=(x-4000)*0.20;x=4000;case3:tax+=(x-3000)*0.15;x=3000;case2:tax+=(x-2000)*0.10;x=2000;case1:tax+=(x-1000)*0.05;x=1000;〃此處的x=1000并不是必要的case0:;}printf("(SWITCH方式)您須交稅:%.21f元5",tax);)return0;流程圖2-1見下一頁。流程圖2-1程序設計題1的算法(if-else結構)流程圖2-2見下一頁。流程圖2-2程序設計題1的算法(switch結構)測試:測試數據:見表2-1,在選取測試數據時,我們注意到,首先應檢測程序能否正確判斷輸入的正確性,故我們輸入-1(負數)與.(非數字)。其次,我們在各數據段中選取具有代表性且易于人工驗算的數據,因此,我們在此處在各工資段中選取了500,1500,2500,3500,4500,5500.同時,選取邊界數據0,1000,2000,3000,4000,防止程序無法正常處理邊界值,圖2-5的運行結果說明結果與理論分析吻合,驗證了程序的正確性。

表2-1編程題1的測試數據測試用例1i療輸入您的1:保金額:1錯識的測試用例1i療輸入您的1:保金額:1錯識的I:俗.清依:令您的輸入道輸入您的I.貨金額:+您檢入rtrt設的?:資.謫檢化您的蛤入測試川例3晴瑜入您的I:洗金制I:O(IFELSE方式)您須交稅:0.00元(SWITCH方式)您須交幣兌:0.D。元測試川例4i卉蛤入您的工資金額:500(IFELSE方式)您須交:0.00元(SWITCH方式)您須交稅:0.00元測I試用例5入您的工資金額:1000(IFELSE方式)您須交稅:0.00元(SWITCH方式)您須交稅:0.00元測試用例6儲檢入您的I:資金額:1500(IFELSE方式)您須交稅:25.00元(SWITCH方式)您須交稅:25.00元測試川例7i.'i除入您的工資金額:2000(IFELSE方式)您須交稅:50.00元(SWITCH方式)您須交稅:50.00元測試用例8i行輸入您的工資金額:2500(IFELSE方式)您須交稅:100.00元(SWITCH方式)色;須「爻稅:10600元測試用例9療輸入您的1:資金額:3C00:IFELSE方式)您須交稅:150.00元(SWITCH方式)您須交稅:150.00元測試用例10療輸入您的1:資金額:3500:IFELSE方式)您須交稅:225.00元:SWITCH方式)您須交稅:225.00元測試用例11次輸入您的工費金額:4C00:IFELSE方式)您須交稅:300.00元:SWITCH方式)您須交稅:300.00元測試用例12青輸入您的工資金額:4500:IFELSE方式;)您須交稅:400.00元:SWITCH方式)您須交稅:400.00元測試用例13青輸入您的工資金額:5C00:IFELSE方式)您須交稅:500.00元:SWITCH方式)您須交稅:500.00元則試用例14音輸入您的工資金額:5500:IFELSE方式)您須交稅:625.00元:SWITCH方式)你須學稅:625.0071-測試用例.程序輸入.理論若果運行結果用例1.??.提示幻誤.提示錯誤.用例2.4-提示命誤.提示錯誤.用例3.0.00元.0.00元.照例4.5co0.00元.0.00元.用例5.10000.00元.0.007C用例6.150025.0(元25.00元.H例7.20005().(M比50.00元.用例8.2500100.0)元.100.00元.用例9.3000150.05元150.00元.用例103500.225.0)元.225.00元“him114000300.0)元.300.00元.用例12.4500400.0)元.400.00元.用例1350)0.500.0)元.500.00元.用例1455*)0.625.0)元.625.00元.圖2-5編程題1的測試用例一的運行結果(2)編寫一個程序,將輸入的一行字符復制到輸出,復制過程中將一個以上的空格字符用一個空格代替。解答:這與C語言處理注釋文字的方式相似,為此,我們定義兩個字符單元,分別用于收集當前收集的字符與上一個收集的字符,當這兩個單元都收集到空格字符時,停止輸出收集到的字符,否則,正常輸出收集到的字符,這樣,便可以將一個以上的空格字符用一個空格代替。其余細節見程序注釋,算法見流程圖2-3,程序如下。#include<stdio.h>intmain()charc,d=0;//搜集當前字符的c單元與前一字符的d單元,注意由于最開始“前一字符”不存在,需給d賦初值while((c=getchar())!=EOF)if(c!=")printf("%c",c);//非空格字符正常輸出if(c==")if(d!='')print<"%c",c);〃非連續空格字符正常輸出d=c;//記錄前一字符return0;流程圖2-3程序設計題2的算法測試:為了測試本程序應對各個位置的空格的能力,作者在各處放置了數量不等的空格,特別是首尾兩處,其次,為了測試程序是否會錯誤的少輸出字符,作者將所有的非空格字符均設為2個及以上。測試數據:字符串(前有2個空格)1122233llaabb111...3311AAAA444+++///666 (后有2個空格)理論輸出結果:(前有1個空格)1122233llaabbxlll...3311AAAA444+++///666(后有1個空格)對應測試測試用例的運行結果如圖2-6所示。特別提示,為使程序效果顯目,用字母x代表空格。下面的運行結果說明結果與理論分析吻合,驗證了程序的正確性。xxll22233xllaabbxxlll...33xxxllAAAA444+++〃/666xxxll22233xllaabbxlll...33x1lAAAA444+++///666x圖2-6編程題2的測試用例的運行結果(3)編寫一個程序,打印如下的楊輝三角形。1 /*第0行*/TOC\o"1-5"\h\z1 1 /*第 1行 */1 2 1 /*第 2行 */13 3 11 4 6 4 11 5 10 10 5 11 6 15 20 15 6 11 7 21 35 35 21 7 11 8 28 56 70 56 28 8 11 9 36 84 12612684 36 9 1每個數據值可以由組合C/計算(表示第i行第j列位置的值),而C/的計算如下:C,°=l (i=0,l,2,…)C/=C/-'*(i-j+l)/jG=0,l,2,3,...,i)說明:本程序中為了打印出金字塔效果,要注意空格的數目。一位數之間是3個空格,兩位數之間有2個空格,3位數之間只有一個空格,程序編制過程中要注意區分。解答:首先,定義一個函數用于生成組合數,題目中提供了一種很好的組合數生成方式,它能避免在計算到17的階乘時就會造成int溢出的結果使計算結果異常,從而提供了計算范圍更大的組合數的可能,當然,在本題中組合結果最大只能是999(否則會出現4位數而無法構成金字塔)。而到了生成金字塔的環節,我們可以將每一個數的單元視作一個長度為4的磚塊,這樣,我們可以得到一個顯然的結論:為了得到金字塔,從最下面一層開始,在其前方輸出2個空格,并且每向上一層,就再增加兩個空格。最后這個10層的金字塔,塔底有10個數,但值得注意注意的是這是(a+b)9的展開式各項系數而非(a+b嚴的,程序如下。#include<stdio.h>intzh(inta,intb)〃聲明一個新的函數,使程序更簡明(intj,i,r=l;if(a==0&&b==0)return1;〃處理c(0,0)的特殊情況for(i=1;i<=a;i++)r=(r*(b-i+l))/i;〃組合數算法returnr;)voidmain(){inti,j,n,k,p;n=9;〃十階金字塔對應的是(a+b)9的展開式fbr(i=0;i<=n;i++)(fbr(k=2*(n-i);k>0;k-)putchar('');〃生成空格fbr(j=0;j<=i;j++)printf("%4d",zh(j,i));//輸出數據,注意%4d的使用滿足了題目對空格數的要求putchar('\n');))測試:本題無需輸入,輸出如下圖。111TOC\o"1-5"\h\z12 113 3 11 4 6 4 11 5 10 10 5 11 6 15 20 15 6 11 7 21 35 35 21 7 11 8 28 56 70 56 28 8 19 36 84 126 126 84 36 9 1圖2-7編程題3的運行結果(4)編寫一個程序,將用戶輸入的任意正整數逆轉,例如,輸入1234,輸出432lo解答:由于本題明確指出所逆轉的對象是正整數,從而首先需要對獲得的輸入進行判定,以確定其是否是符合題目要求的輸入。再確定輸入合乎題目要求之后,利用同余除法的特性,求出輸入數據除以十的余數并將其輸出,而后將輸入的數字除以十,由于輸入是int型,從而除以十的結果等效于消除了最后一位數字,再求出新的數字除以10的余數,如此循環下去,便可輸出被逆轉的整數,考慮到循環的邏輯簡明,故采用while語句。其余細節見程序注釋,算法見流程圖2-4,程序如下。流程圖2-4程序設計題4的算法#include<stdio.h>intmain()intn,s;printf("請輸入一個正整數,本程序會將其逆轉:");scanf^s("%d",&n);if(n<=0)printf("本程序只接受正整數輸入,請檢查您的輸入)〃檢查輸入是否合理elsewhile(n)〃注意,此處只用于判斷循環是否結束,不用于判斷輸入是否合s=n%10;printf("%d",s);〃輸出最后一位數n=n/10;〃消除最后一位數)putchar('\n');printf("\t此即為逆轉結果");return0;}測試:首先,是對函數基本功能的測試,即測試其能否正確逆轉正整數,在此,我們選取一個正常的正整數O,接下來測試程序對異常輸入的反應一個異常輸入0(非正整數),一個異常輸入“。”(非數字),其預期結果與實際結果見表2-2,運行結果見圖2-8。表2-2編程題1的測試數據測試用例程序輸入理論結果運行結果用例1OOO用例2提示錯誤提示錯誤用例30提示錯誤提示錯誤測試用例:1請輸入一個正整數,本程序會將其逆轉:測試結果:測試用例:2請輸入一個正整數,本程序會將其逆轉:。本程序只接受正整數輸入,i療檢畬您的輸入測試用例:3請輸入一個正整數,本程序會將其逆轉:0本程不只接受正整數輸入,請檢代您的輸入圖2-8編程題4的運彳丁結果2.2.4選做題編寫一個程序,用牛頓迭代法求方程f(x)=3/_4/_5x+13=。滿足精度e=10-6的一個近似根,并在屏幕上輸出所求近似根。牛頓迭代法求方程近似根的迭代公式為:\x0=alx*+i=xk-f(xk)/f\xk)其中,/'(x)是函數f(x)的導函數。牛頓迭代法首先任意設定的一個實數。來作為近似根的迭代初值xo,然后用迭代公式計算下一個近似根XI。如此繼續迭代計算X2,X3,…,Xn,直到氏-%區精度e,此時值x。即為所求的近似根。解答:首先,為了計算Xk+I我們應先計算f(Xk)與F(Xk)而對這兩個多項式的計算,我們可以采用秦九韶算法,這樣可以減少對計算機而言較復雜的的乘法運算,雖然對單次計算而言,這樣的簡化效果并不明顯,但在多次的迭代計算中(本題中進行了三十三次),這樣的簡化可大幅提高計算效率。而在解決了f(Xk)與f'(Xk)的值后,為了使程序更加簡潔,我們將這兩個式子定義為新的函數,與此同時,將迭代過程也定義為一個新的函數。最后在判斷Xk+1與Xk的接進程度時,考慮到最初Xk+1并未賦值,我們在此處采用至少循環一次的do-while結構。其余細節見程序注釋,算法見流程圖2-5,程序如下。#include<stdio.h>#include<math.h>doublefifdoublex)(return(((3*x-4)*x-5)*x+13);〃秦九韶算法)doubledf(doublex){return((9*x-8)*x-5);〃秦九韶算法)doublen(doublex)return(x-f(x)/df(x));〃迭代}voidmain(){doublexk=l,xp=l;intk=0;doxk=xp;xp=n(xk);k++;〃統計計算次數while(fabs(xp-xk)>le-6);printf("方程的根:%lf\n計算次數:%d\n",xk,k);流程圖2-5選做題的算法測試:本題無需輸入,輸出見圖2-9。本方程的根為(sqrt(21799)/(2*3A(7/2))-249l/1458)A(l/3)+61/(81*(sqrt(21799)/(2*3A(7/2))-2491/1458)A(l/3))+4/9=-l.548909593下面的運行結果說明結果與理論分析吻合,驗證了程序的正確性。方程的根:T.548910計算次數:33圖2-9選做題的的運行結果2.3自設題問題:判斷一個數是否是質數。解答:為判斷一個數是否是質數,我們通常是把小于這個數的每一個數去除這個數直到除到它自身為止(稱為1方法),但是這樣的效率很低,且會進行大量的重復計算,于是有人提出只需要除到這個數的一半(稱為2方法),但事實上這樣也會造成重復計算,經過理論分析表明,只需要除到這個數的平方根即可(稱為3方法),當然,存在其他更優越的方法,如Solovay-Strassen算法和Miller-Rabin算法,但它們較復雜,也有針對特定環境的方法,例如把一定范圍內的質數先生成,在使用進行大小比較即可,但這針對多次查詢比較有效。在此,我們將比較1方法,2方法與3方法計算所需要的時間。特別地,對于3方法而言,開根號無論是對于人還是對于計算機都是一項復雜的工作,為提高計算效率,我們采用一個等價描述,即0<加46=加2與〃。這樣把需要多次迭代的開方運算變成了乘法運算,能顯著提高計算效率。至于計時方面,C語言的time.h中提供了相應的函數,我們可直接調用用來計時,注意到它的精度是毫秒級的,所以它的精度是足夠的,其余細節見程序注釋。算法(僅包含質數判斷)見流程圖2-6,程序如下.流程圖2-6自設題的算法#include<stdio.h>#include<time.h>〃用于計時#include<math.h>intf(intk,intx);〃索引函數intfl(intx);intf2(intx);intf3(intx);//計算函數voidmain(void){intx;intk=O;〃計數器a:x=100;k++;while(x<le5)〃防止計算過度,限制最大數值為十萬(printf("測試方法:%d\n",k);x*=10;printf("現在尋找小于%d的質數\n",x);clocktstart,end;//注意只記錄計算質數的時間start=clock();printf("找到%d個質數\n",f(k,x));end=clock();printff用時%.0僵秒\n————=\n",1000*((double)end-start)/(CLKTCK));〃顯示時間)if(k<3)gotoa;〃合理使用goto簡化程序}intf(intk,intx){if(k=1)returnfl(x);〃l方法if(k=2)returnf2(x);〃2方法if(k=3)returnf3(x);〃3方法)intfl(intx){inti,j,n=0,k=0;for(i=3;i<x;i++)〃注意2肯定是質數,1不是質數也不是合數for(j=2;j<i;j++)(if(i%j=0)n++;//n:合數判斷器一旦n不為0輸入的數即不為質數if(n){k++;n=0;break;//k:合數計數器return(x-k-2);〃總數減去合數數與1即是質數數}intf2(intx){inti,j,n=0,k=0;for(i=3;i<x;i++)//注意2肯定是質數,1不是質數也不是合數{for。=2;j<=i/2;j++)〃注意到等號是必要的,否則會漏掉形如2P(p為質數)的合數(if(i%j=0)n++;//n:合數判斷器一旦n不為0輸入的數即不為質數if(n){k++;n=0;break;//k:合數計數器return(x-k-2);〃總數減去合數數與1即是質數數}intf3(intx){inti,j,n=0,k=0;fbr(i=3;i<x;i++)〃注意2肯定是質數,1不是質數也不是合數{for(j=2;j*j<=i;j++)〃注意到等號是必要的,否則會漏掉形如p人2(p為質數)的合數

if(i%j=0)n++;//n:合數判斷器一旦n不為0輸入的數即不為質if(n)(k++;n=0;break;//k:合數計數器)))return(x-k-2);〃總數減去合數數與1即是質數數測試:本題無需輸入,查閱資料可知:1000以內的質數有168個;10000以內的質數有1229個;100000以內的質數有9592個;1000000以內的質數有78498個。結果見圖2-10,與理論數目相符,驗證了程序的正確性。測試方法:1現在尋找小于1000的質數找至U168個旗數測試方法:1現在尋找小于1000的質數找至U168個旗數小時0宅秒測試方法:1現右尋找小于1OOOO的質數找到1229個歷數用時25把秒測試方法:2現在尋找小于100000的質數找到9592個質數用時964毫秒測試方法:1現在J技小廠100000的旗數找到9592個項數用時1637,完秒測試方法:3現在尋找小于1000的質數找到168個質數用時1亳秒測試方法:2現在才找小于1000的歷數找到168個質數用時0亳秒測試方法:3現在尋找小于10000的質數找到1229個質數用時1亳秒測試方法:2現在尋找小于10000的質數找到1229個質數用時13亳秒測試方法:3現在尋找小于100000的質數找到9592個質數用時27亳秒圖2-10自設題程序運行結果由此可見,算法的優化對程序的運行效率是多么的重要,同樣的問題,使用不同的算法,其效率之差可能接近80倍。特別需要指出的是,方法1與方法2都無法正常的尋找小于一百萬的質數總數,而方法3處理這個問題僅需740毫秒(見圖2-11),充分體現其優越性。測試方法:3現在尋找小于1000000的質數找到78498個質數用時740毫秒圖2-11方法3尋找小于一百萬的質數總數2.4實驗小結在本次實驗中,我對各種流程控制語句的使用更加熟悉了,同時也對它們之間的差距與各自的優劣有了更加深刻的認識,比如while語句適合用于簡單的循環邏輯;而其衍生語句do-while語句適合用于一定會有循環發生的情形(即至少會執行一次循環體中的內容,如牛頓法求方程的根);而更加復雜的for語句則適合用于某些更加復雜的情況,但這些語句在本質上是一致的,即可使用某一語句實現這三種語句的所有功能(當然這會帶來不便)。而另一類型的流程控制語句(帶有選擇色彩的)if-else語句與switch語句則分別適用于較少選擇支與較多的選擇支,不過switch語句與if-else語句的最重要區別并不在此;它們的關鍵區別在于switch語句可用于某些需要滿足某一條件后順序執行之后所有語句的情形。此外,在本次實驗中,我也體會到了一個優良的算法對程序執行效率提高的重大作用,如在選做題中我們使用了秦九韶算法提高了多項式求值的效率;而在自設題的質數判斷中,一個合適的條件(算法)對程序效率的提升那更是不言而喻的。實驗3函數與程序結構實驗3.1實驗目的(1)熟悉和掌握函數的定義、聲明;函數調用與參數傳遞方法;以及函數返回值類型的定義和返回值使用。(2)熟悉和掌握不同存儲類型變量的使用。(3)熟悉多文件編譯技術。3.2實驗內容及要求3.2.1源程序改錯下面是計算s=l!+2!+3!+…+n!的源程序,在這個源程序中存在若干語法和邏輯錯誤。要求在計算機上對這個例子程序進行調試修改,使之能夠正確完成指定任務。#include<stdio.h>intmain(void){intk;fbr(k=l;k<6;k-H-)printf(nk=%d\tthesumis%ld\nn,k,sum_fac(k));return0;)longsum_fac(intn){longs=0;inti;longfac;fbr(i=l;i<=n;i-H-)fac*=i;s+=fac;returns;)解答:(1)錯誤修改:1)第5行處的循環使得程序只能計算一些固定數的階乘和,正確形式為:scanf_s("%d",&k);2)第6行處使用了一個新定義的函數sum_fac(),但沒有預先聲明,正確形式為:(在第1行與第2行之間插入)longsum_fac(intn);3)第15行處使用了一個未初始化的變量fac,正確形式為:longfac=1;4)第15行與16行的計算邏輯有誤,這樣只能得到n!的值,正確形式為:{fac*=i;s+=fac;}(2)錯誤修改后運行結果:見圖3-1(1!+2!+3!=1+2+6=9)pleasethenunbei*k

k=3thesunis'圖3-1修改后的運行結果3.2.2源程序修改替換(1)修改第1題中sumfac函數,使其計算量最小。解答:第1題中sum_fac函數計算量較大主要是由于無論是在求階乘時還是在求其和時均出現了大量的重復運算,為此,我們使用遞歸函數來減少計算量為此我們采用了靜態變量,注意這樣會使用“虛擬”(即計算但不輸出)的循環來達到記錄之前的階乘值得目的來簡化運算,其余細節見程序注釋,程序如下。#include<stdio.h>longsum_fac(intn);intmain(void)(intk,i;printf("pleasethenumberk:");scan匚s("%d",&k);if(k<=0)printf("legalinput!");〃排除非法輸入else{for(i=l;i<=k;i++)if(i=k)printf("k=%d\tthesumis%ld\n",i,sum_fac⑴);〃注意longint的占位符elsesumfac(i);〃“虛擬”輸出))return0;)〃以下得函數使用靜態變量簡化了運算staticlongfac=1,sum=0;longsum_fac(intn)(fac*=n;sum+=fac;returnsum;)運行結果見圖3-2 (l!+2!+3!+4!=l+2+6+24=33)pleasethenunherk:4

k=4thesunis33圖3-2修改后的正常運行結果pleasethenunbei*legalinput!圖3-3修改后的異常運行結果(2)修改第1題中sumfhc函數,計算s=1+,+'+...+2!3! 〃!解答:此處只需要每次計算階乘時改為計算其倒數即可,但特別需要注意的是,計算過程中會出現小數,因此需要改變大部分變量的數據類型,其余細節見程序注釋,程序如下。#include<stdio.h>doublesum_fiac(intn);longfac(intn);〃注意數據類型的改變intmain(void){intk;printf("pleasethenumberk:");if(k<=0)printf("legalinput!");〃排除非法輸入scanf("%d",&k);printf(,,k=%d\tthesumis%lf\nn,k,sumfac(k));return0;)doublesum_fac(intn){if(n>1)return1.0/fac(n)+sum_fec(n-1);〃注意1,0的使用強制轉換了類型elsereturn1;}longfac(intn){if(n>1)returnn*fac(n-1);elsereturn1;)運行結果見圖3-4與圖3-5-(1+1/2!=1+0,5=1.5)pleasetienumberk:2k?2thesunis1.500000圖3-4第2題程序的正常運行結果pleasethenumbei*k:-1legalinput!圖3?5第2題程序的異常運行結果3.2.3跟蹤調試題下面是計算fabonacci數列前n項和的程序,要求單步執行程序,觀察p,i,sum,n值。#include<stdio.h>intmain(void)(inti,k;longsum=0,*p=∑/*聲明p為長整型指針,指向sum*/scanf(n%dn,&k);for(i=l;i<=k;i++){sum+=fiabonacci(i);printf(Mi=%d\tthesumis%ld\nM,i,*p);/**p等價于sum*/return0;longfabonacci(intn)(if(n==l||n==2)return1;elsereturnfabonacci(n-1)+fabonacci(n-2);)(以下第1?3題的分析以輸入的n=2為分析基礎)(1)剛執行完scanf("%d",&k);語句,p,i值是多少?、答:通過理論分析,由于p被設定為指向sum的指針,故其值與此時sum之值相同,而sum在聲明時已經被賦予初值0,從而此時p的值也應為0。而i此時僅被聲明而尚未被初始化,從而其值為一個在int范圍內的隨機數。跟蹤的實際結果圖3-6所示,與理論分析相符。0*p0 lone*i-858993460 int圖3-6步驟(1)的跟蹤結果(2)從fabonacci函數返回后光條停留在哪個語句上?答:通過理論分析,由于是從第8行進入fabonacci函數且在進入前第8行的計算尚未完全結束,所以從fabonacci函數返回后應繼續未完成的計算,即光標應停在第8行。跟蹤的實際結果圖3-7所示,與理論分析相符。? 8 sum+=fabonacci(i);已用時間<=ims圖3-7步驟(2)的跟蹤結果(3)進入Fibonacci函數,watch窗口顯示的是什么?答:通過理論分析,在第一次進入fabonacci函數時,watch窗口中應顯示帶入的參數,又此時僅帶入了參數i,而參數i的值又為1,從而該窗□應顯示n=l。而在第二次進入時,i=2,同理該窗口應顯示n=2。跟蹤的實際結果圖3-8與圖3-9所示,與理論分析相符。

自礴口名稱直?nI▼9x類型int自助窗口▼9x類型int圖3-8步驟(3)的跟蹤結果(第一次進入)自動窗口 7x名稱 直 類型。n2 int自動窗口局部變量監視1圖3-9步驟(3)的跟蹤結果(第二次進入)(4)當i=3,從調用fabonacci函數到返回,n值如何變化?答:通過理論分析,在第一次進入fabonacci函數時,watch窗口中應顯示帶入的參數,又此時僅帶入了參數i,而參數i的值又為3,從而該窗□應顯示n=3,此時n不是1或2中的任意一個,故進入else后的語句,該語句中參數分別為2與1,從而該窗口應顯示n=2與n=l,之后,會直接進入if后的語句,該語句不會再為fabonacci函數提供參數,所以不再進入fabonacci函數,當然,在完成這些計算后,在return之前,n的值又一次變回3,從而該窗口應顯示n=3,此后,n便不復存在。跟蹤的實際結果圖3-10至圖3-14所示,與理論分析相符。自動窗口 7X名稱 值 類型?n2 int自動窗口局部變量監視1圖3-10步驟(4)的跟蹤結果(剛進入)

110%Elongfabonacci(intn)110%{已用時間<=1msif(n==111n?

return1;returnfabonacelsereturnfabonac自動直口局部變量監視1圖3-11步驟(4)的跟蹤結果(計算自bonacci(2))在動窗口 ▼qx名稱值 類型。n1 int自動窗口局部變量監視1圖3-12步驟(4)的跟蹤結果(計算fabonacci(l))自麗口 ▼Qx名梆值 類型名梆值 類型自初窗口曷部變量監視1圖3-13步驟(4)的跟蹤結果(return后)自動窗口TOC\o"1-5"\h\z名梆 值0*p 4?i 4.sum 4圖3?14步驟(4)的跟蹤結果(退出后)3.2.4程序設計題(1)編程讓用戶輸入兩個整數,計算兩個數的最大公約數并且輸出之(要求用遞歸函數實現求最大公約數)。同時以單步方式執行該程序,觀察遞歸過程。解答:首先,為了使計算盡量簡單,我們使用輾轉相減法來計算最大公約數,同時,輾轉相減法也是用于單步觀察執行過程的優良算法(因其計算結果簡單且計算次數較少)并且也可使用遞歸來提高運算效率,其余細節見程序注釋,算法見流程圖3-1,程序如下。流程圖3-1程序設計題(1)的算法#include<stdio.h>intR);voidmain()inta,b;prin氓"請輸入兩個正整數(以空格分隔):");scan7%d%d",&a,&b);if(a<=0||b<=0)printf("您輸入了非正整數內容,請檢查您的輸入\n");//檢查非法輸入elseprint口"它們的最大公約數是:%d\n",f(a,b));intf(inta,intb)//輾轉相減法

if(a=b)returna;if(a>b)returnf(a-b,b);if(a<b)returnf(a,b-a);測試:首先,我們應測試程序能否正常運行,為此我們選擇了具有多個公因數(非1)的90與60,而后選擇具有倍數關系的5與10與相等兩數12與12(注意到其擁有多個因數),接著又提供了一組帶有1的測試樣例7與1,以測試在非常情況下程序的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論