李欣潼
摘要:C語言是一門十分重要但對初學程序設計的同學來說又是相對難學的一門計算機語言。從初學者的角度出發(fā),按照分析問題,算法設計,編碼實現(xiàn)及程序運行幾個步驟,說明了學習C語言的方法。論文以二元一次方程組的求解過程為案例,首先詳細地論述了問題分析的方法,然后從C語言學習時初學者難于掌握的運算符使用、循環(huán)控制、自定義函數(shù)、數(shù)組及指針幾個方面詳細地說明了分析和編碼實現(xiàn)方法,最后說明了上機實現(xiàn)的方法和重要性。
關鍵詞:初學者;C語言;二元一次方程組;問題分析;程序實現(xiàn)
中圖分類號:TP311 文獻標識碼:A 文章編號:1009-3044(2018)29-0113-04
Abstract: C is one of the very import program design language.Oriented beginner, this paper explains the method of learning C language according to the analysis of problems, algorithm design, coding implementation and program running steps. Taking the solving process of binary first-order equations as a case, this paper discuss the method of problem analysis at first, and then illustrates the method of coding at the aspects of operator use, loop control, custom functions, arrays and pointers which are difficult for beginners in C language learning. Finally, it explains the method of computer practice.
Key words: beginner; C Language ;binary first-order equations;problem analysis;computer practice
為響應“計算機要從娃娃抓起”的號召,我國各地中學均開設了計算機相關課程。程序設計在啟發(fā)中學生的想象力和創(chuàng)造力,提高數(shù)學分析和邏輯思維能力,增強理解和解決問題的能力等方面很有作用,因此已經(jīng)成為中學生必修的一門課程。C語言作為一門應用最為廣泛的計算機語言之一,是許多高中開設的計算機程序設計類課程,同時也成為信息學奧林匹克競賽的官方語言之一。C語言是一門面向過程的高級計算機語言,它語法靈活,編程簡潔、緊湊;特別適合于模塊化程序設計,層次結構清晰,且功能強大,即適合開發(fā)應用軟件,也可以開發(fā)系統(tǒng)軟件,因此應用領域特別廣泛。但由于它運算符豐富,語言限制不很嚴格,程序設計的自由度大[1][6],針對初學程序設計的中學生來說入門很困難,不容易掌握。本文根據(jù)自己學習C語言的感悟,將程序設計過程為主線,通過‘問題→想法→算法→程序的問題求解過程[2] ,詳述學習C語言程序設計的方法,以希望能對初學者有所借鑒。
1 學習第一步:從分析問題入手,由簡到難設計解決問題的步驟
學習程序設計的目的歸根結底是要利用計算機工具去解決人們?nèi)粘5纳?、工作、學習和娛樂等遇到的問題。問題的解決需要確定的步驟和方法。對于復雜的問題要分析問題的層次和功能模塊的劃分,而對于簡單的問題,只要確定已知什么要求什么怎么求即可,初學者學習程序設計之時,應該從學生比較熟悉的簡單問題入手,了解問題的具體內(nèi)容(分析問題),具備什么樣的條件(已知什么?),需要解決什么(要求解什么?),然后用自己具備的知識選擇適當?shù)慕鉀Q方法(選擇設計算法),最后按照計算思維過程根據(jù)算法來設計步驟,實現(xiàn)編程。中學生學習生活中,最為熟悉的是數(shù)學問題,因此可以選擇一些數(shù)學題目作為初始編程案例,題目難度從簡單過渡到復雜,在初學者易于介紹的狀態(tài)下逐步掌握程序設計的過程。本文以“求解二元一次方程組的解”作為全篇貫穿案例,介紹學習程序設計的過程。
①分析問題:
經(jīng)過分析,清楚待求解問題是對給定的二元一次方程組求它的解。針對初學者,可以先把問題設計得簡單些:只求有唯一解的二元一次方程組的解。這樣可以明確地是給定的方程它只有一個唯一解,問題和目的更為確定。結合學生的知識儲備,知道二元一次方程組是由兩個方程構成,每個方程由兩個待求的未知數(shù)及未知數(shù)的系數(shù)和常數(shù)項構成。求方程組的解需要利用消元法、代入法等求解。
②確定已知條件:
對于簡單的問題,大多是已知什么,求解什么,怎么求問題。經(jīng)過第一步的分析,明確了要解決的問題后,要先考察的是已知什么樣的條件,比如已知哪些數(shù)據(jù)和條件。當明確了已知條件并將其表示清楚,才可能進一步利用它們?nèi)デ蠼?。需要注意的是,對于已知?shù)據(jù),要通過分析數(shù)據(jù)的特點、表示的內(nèi)容來確定數(shù)據(jù)的類型,然后用合適的符號對已知數(shù)據(jù)進行表示。已知數(shù)據(jù)抽象成了符號,便可以方便地在算法中使用。本例中是給定一個簡單的有唯一解的二元一次方程組對其求解,它的已知條件應是兩個方程系數(shù)及常數(shù)項。可以按照數(shù)學課中使用的方式暫時用a1,b1,c1來表示第一個方程的已知條件;用a2,b2,c2表示第二個方程的已知條件。如果它們已知并且確定了就可以利用它們在算法中完成求解。
③確定要解決的具體問題
這種情況對于初學者,一般是要解決求什么的問題。求解的問題可能是完成某種操作,也可能是求得一些數(shù)據(jù)結果。求解的內(nèi)容不一樣,設計的算法也不同,因此明確求什么樣的結果將決定采用什么樣的算法。本文要求解二元一次方程組的兩個未知數(shù)的解,求的是數(shù)據(jù),設計的算法就應該與計算有關。如果要求解的是數(shù)據(jù),那么同已知一樣,應將結果用符號表示出來,以便于設計算法時應用。本例的求解問題是方程組的解,把它們表示為x和y。
④設計計算法方法即算法
分析問題之后,明確了已知和待求解問題,接下來就是怎么求解的問題,也就是用什么樣的方法來根據(jù)已知求未知。這個過程是要在編程者掌握了一定的數(shù)學、生活常識和計算機計算等知識和常用算法后,結合具體的問題選擇相應的算法來實現(xiàn)。這一步驟在整個編程過程中都是比較難的,只有有了一定的基礎和經(jīng)驗,才能更正確和合適地設計算法。但對于初學編程的同學,初始接觸的問題不難,是可以結合自己的基礎來確定算法的。需要特別注意的是程序設計設計的是程序,而程序是有著嚴格的順序和過程的,在設計問題的算法時,一定要注意計算的順序。算法中應用符號化的已知及待求數(shù)據(jù),會讓算法更為清晰明確。
⑤描述算法
通過算法可以看出清晰的問題計算過程和方法。
2 學習第二步:用C語言程序描述算法
確定好算法后,要用計算機程序來描述問題。計算機程序是選擇不同的計算機語言,按照相應的語法規(guī)則來程序化的算法。C語言是一種編程語法靈活,代碼簡潔、功能十分強大的計算機語言,但其運算符豐富,語法格式靈活,對初學者來說掌握起來并不容易。因此本文采用由簡至繁的方式讓學生循序漸進地掌握C語言的語法規(guī)則。
用計算機語言描述算法,首先要清楚所采用語言的程序結構。C語言是以函數(shù)為單位的,函數(shù)格式也比較簡單,很容易記憶,本文不再多述。
本文中從只有一個函數(shù)且函數(shù)內(nèi)部只是由順序結構構成的最簡單C語言程序開始,循序漸進結合第二部分內(nèi)容來說明C語言程序的編程方法。下面依然利用二元一次方程組的求解問題說明C語言程序設計的方法。
2.1數(shù)據(jù)及簡單程序
C語言數(shù)據(jù)類型豐富,運算符及表達式種類繁多,這說明C語言表達能力強,但因規(guī)則繁雜,對初學者來說掌握不易。初學之時,只要掌握C語言標識符的概念,整型、實型、字符類型基本數(shù)據(jù)及常用算數(shù)運算符和賦值運算符即可,不必過多記憶。
計算機工作原理是只有將程序和數(shù)據(jù)存入到內(nèi)存中,計算機才能執(zhí)行,所以內(nèi)存變量的概念是這部分的重點內(nèi)容。前文分析中已知數(shù)據(jù)、求解數(shù)據(jù)及算法設計時所借助的數(shù)據(jù)都必須存放在內(nèi)容變量中,所以要在分析問題時確定這些數(shù)據(jù)所代表的數(shù)據(jù)形式以及大體范圍,這樣就可以在設計程序時將它們首先聲明好。
本文案例中已知的六個數(shù)據(jù)表示的都是數(shù)值,可以是整型也可以是實數(shù),但是待求解的數(shù)據(jù)在算法中需要用到除法運算求解,因此為了少損失精度,應務必將其定義為實數(shù)。所以數(shù)據(jù)定義為:int a1,b1,c1,a2,b2,c2; float x,y;。數(shù)據(jù)聲明過后,就可以利用這些數(shù)據(jù)完成運算了。初學時運算符學習中特別注意除號(/)和求余符號(%)以及賦值號(=)的使用,其他均與數(shù)學課中的使用相似,不必過度探討。同時掌握基本數(shù)據(jù)的簡單輸入輸出函數(shù)的scanf和printf的使用也是必需的。這樣就可以實現(xiàn)簡單的數(shù)學計算類程序的編寫了。至此,本文中二元一次方程組的解相應的程序就可以完整地編寫出來(完成程序略)。只記住少量的規(guī)則就能夠描述簡單程序對初學者來說是一個學習動力,并能鼓舞和激勵他進一步學習。
2.2循環(huán)控制
順序結構和選擇結構在初學者學習時難度均不大,接受容易。選擇結構中只要牢記if語句的語法和常用的關系和邏輯運算符的使用,大多掌握起來并不困難。但循環(huán)結構是初學者學習C語言時繼運算符和表達式后的又一個難點。循環(huán)結構程序設計是C語言程序設計中最重要和最難掌握的基本結構[3]。C語言的循環(huán)結構可以由while、do while和for語句實現(xiàn)。三個語句各有其特點,但均可以完成任何的循環(huán)控制。初學者開始只要掌握while的語法規(guī)則,當清楚并掌握了while語句的使用,其余兩個自然就迎刃而解了。
除了循環(huán)控制的語句,學習者還應該明白循環(huán)語句的用處。在簡單問題中循環(huán)結構有兩個作用:①控制重復某些計算的次數(shù)(次數(shù)≥2);②符合一定條件后重復執(zhí)行某些計算,直到條件不滿足為止。通過對問題的分析,只要在算法中出現(xiàn)上面兩種情況,就一定要用到循環(huán)結構。對于循環(huán)結構的算法實現(xiàn),兩種情況都要從以下四個步驟考慮:循環(huán)結構執(zhí)行之前的初始化問題;循環(huán)條件的控制問題;需要重復執(zhí)行的內(nèi)容;循環(huán)控制條件的修改。熟記這四方面的使用,循環(huán)結構就可以萬無一失了。下面還以二元一次方程組求解來詳細說明。在分析問題基礎上按照循環(huán)的兩種情況增加題目難度:①求n個不同的二元一次方程組的唯一解(n代表個數(shù),比如n=5);②判斷已知條件,若輸入的兩個方程的未知數(shù)系數(shù)對應成比例,使得二元一次方程組無唯一解,即繼續(xù)輸入,直到輸入的數(shù)據(jù)能夠使方程組有唯一解為止。按照問題分析:第一種情況是重復執(zhí)行多次,計算需要一次次完成,只要在問題分析的算法中加入對次數(shù)的統(tǒng)計和判斷即可;第二種情況對輸入數(shù)據(jù)要按照數(shù)學上一樣的判斷方法,由于“對應成比例”的判斷易產(chǎn)生誤差,所以改為對應乘積的比較更合適。具體實現(xiàn)從四個步驟說明兩種情況。
1)循環(huán)結構執(zhí)行之前的初始化問題
第一種情況在原有算法中,加入一個次數(shù)統(tǒng)計變量n,它初始可以從任意一個數(shù)值開始,一般習慣上從0或1開始,本文計從1開始,即n=1;
第二種情況是根據(jù)輸入的二元未知數(shù)的系數(shù)來判斷,因此就是輸入的a1,b1,a2,b2的值,即input a1,b1,a2,b2。
2)循環(huán)條件的控制問題
第一種情況求五個二元一次方程組的解,就是重復執(zhí)行五次求解,那么循環(huán)控制條件就是在次數(shù)沒超過5次之時均要計算,則循環(huán)控制可以為n≤5;
第二種情況系數(shù)成比例就要重復輸入,因此控制條件是判斷a1b2-a2b1是否為0。
3)需要重復執(zhí)行的內(nèi)容
第一種情況重復的是方程組解的多次求解,因此算法2中的①②③④步都需要重復;
第二種情況是對輸入數(shù)據(jù)的判斷,因此重復的是輸入數(shù)據(jù)語句,即步驟①。
4)循環(huán)控制條件的修改
第一種情況循環(huán)控制條件是執(zhí)行一次循環(huán)就增加一次次數(shù),所以應為n=n+1;
第二種情況循環(huán)是因為輸入的數(shù)據(jù)使得方程組沒有唯一解,那就需要重復輸入,所以循環(huán)控制條件的修改是再次輸入數(shù)據(jù),即scanf(“%d%d%d%d%d%d”,&a1;,&b1;,&c1;,&a2;,&b2;,&c2;);常數(shù)項也一同輸入吧。
通過上面的問題和算法分析,兩個情況下程序在算法1基礎上,確定為圖2和圖3。
2.3 C語言函數(shù)
在C語言應用中,模塊化程序開發(fā)的方法是必須的。函數(shù)使用是實現(xiàn)模塊化程序必不可少的方法[5],函數(shù)的使用有諸多優(yōu)點:可以增加程序的可讀性、可以實現(xiàn)代碼重用、可以讓程序結構更清晰等,但自定義函數(shù)的使用對于初學者來說也是特別難掌握的。學習時最應該讓初學者掌握的是什么時候用函數(shù)和函數(shù)應該如何定義。什么時候用函數(shù)呢?簡單地理解就是程序中有特定功能的獨立部分、在程序中要被多次執(zhí)行的部分,這些地方都可以用作自定義的函數(shù)。那么如何聲明函數(shù)呢?首先要知道函數(shù)的功能,其次要清楚函數(shù)的形式參數(shù)。函數(shù)的功能決定了函數(shù)的任務:它由哪些代碼實現(xiàn),它的功能是求一個數(shù)還是完成某種操作;而函數(shù)的形式參數(shù)就是函數(shù)功能是被哪些數(shù)據(jù)決定,這些決定函數(shù)功能的數(shù)據(jù)就應該是函數(shù)的形式參數(shù)。了解了這些初步的簡單函數(shù)聲明就可以實現(xiàn)了。
比如二元一次方程組求解中,判斷方程組是否有唯一解部分就是獨立于其他部分的,可以用自定義函數(shù)實現(xiàn)。它的功能是判斷是否有唯一解,這個判斷需要由哪些數(shù)據(jù)確定呢?是兩個方程的未知數(shù)系數(shù),那么方程的未知數(shù)系統(tǒng)就是形式參數(shù)。函數(shù)的功能是判斷結果,那么可以約定如果有唯一解函數(shù)的結果即函數(shù)值是0,如果沒有唯一解,那么函數(shù)值就是1。根據(jù)這樣的分析,可以將函數(shù)定義為圖4。
此例中對二元一次方程組的求解,也可以編寫成自定義函數(shù)。函數(shù)的功能是求解二元一次方程組的解,實現(xiàn)功能的代碼是獨立的。函數(shù)的功能需要根據(jù)方詞組的未知數(shù)系數(shù)及常數(shù)項來決定,那它們就是這個函數(shù)的形式參數(shù)。因函數(shù)的功能不似圖4的函數(shù)是只求一個值的,那么功能的實現(xiàn)需要結合其他的C語言知識來實現(xiàn),比如解用兩個全局變量來實現(xiàn),函數(shù)無需返回值(函數(shù)的程序略);也可以將結果通過兩個特別增加的形式參數(shù)傳值帶回到主調函數(shù)中(將在2.5中詳述)。
2.4數(shù)組的使用
數(shù)組的作用是為了管理和使用內(nèi)存的批量存儲單元。它的使用拓展了C語言的應用范圍,比如批量數(shù)據(jù)的排序,以及有關利用矩陣的計算等應用,相應地也增加了分析問題的難度和對應算法的復雜性。初學者要了解何時適合使用數(shù)組、數(shù)組的簡單使用方法、特別是數(shù)組下標的表示即可,熟練掌握了之后,再考察難度較高的應用和算法。
從二元一次方程組的求解,了解已知數(shù)據(jù)有6個,待求數(shù)據(jù)有2個,都不很多,用數(shù)學課上的常用符號——英文字母(x,y)及英文字母加數(shù)字(a1,b1,c1等)表示就可以分得很清,哪個符號是哪個未知數(shù)的系數(shù),哪個是常數(shù)項不會搞亂。但是當未知數(shù)多(比如≥3)時,再用這樣的符號,對應起來可能會比較麻煩。比如n個未知數(shù)n個方程的方程組,即使是n個常數(shù)項都不知道用哪些字符表示能分清楚到底是第幾個方程的,更別說使用了。但是如果應用了C語言的數(shù)組,可以用數(shù)組的下標表示是第幾個方程的常數(shù)項,并且下標能夠靈活變化,一個符號可以統(tǒng)一代表所有方程的常數(shù)項。數(shù)據(jù)一旦用抽象符號表示,可以更易分析算法。這樣n個常數(shù)項可以用一個一維數(shù)組來表示。常數(shù)項若都是int類型,那么常數(shù)項就可以用int c[n]; 聲明(n為符號常量或是有確定值的整數(shù),代表有n個方程)。同樣的每個方程由n個未知數(shù),那么每個方程的未知數(shù)系數(shù)也可以用一個一維數(shù)組定義,比如int a1[n]; ,而有n個方程組了,那系數(shù)中的每一個都需要再加一維,這樣便構成了二維數(shù)組,可以定義為:int a[n][n];。這樣知道了數(shù)組何時使用,而且引進了下標,對批量數(shù)據(jù)的位置和表達容易了也通用了,問題分析和算法的確定也更容易,數(shù)組在C語言編程中使用就有了基礎。數(shù)組的使用不要急,要從簡單的一維數(shù)組實踐開始,特別注意數(shù)組下標的范圍、變化以及在批量數(shù)據(jù)中的位置,循序漸進才能真正掌握。
2.5 指針的使用
指針是C語言的重要數(shù)據(jù)類型也是C語言的精髓和特色[6]。指針的使用可以提高C語言程序運行的速度,可以提高內(nèi)存的使用效率,也可以間接地訪問內(nèi)存變量,從而擴充程序的功能。但是指針也是比較難掌握的內(nèi)容。
建立在應用基礎上的C語言學習,是要按照由簡至難,從陌生到了解,再到熟悉,最后到完全掌握的過程學習,所以依然可以從簡單的簡單變量的間接訪問開始,了解和體會了指針的基本功能,其他的作用就會慢慢地接受。
2.3節(jié)中可以把二元一次方程組求解過程聲明為自定義函數(shù),方程組的解可以“通過兩個特別增加的形式參數(shù)傳值帶回到主調函數(shù)中”,那么我們在主調函數(shù)中的求解x,y的值,可以利用被調函數(shù)多增加的這兩個特別的形式參數(shù)計算傳回。由于C語言的函數(shù)無論被調函數(shù)還是主調函數(shù)都是相互對立的,它們之間的聯(lián)系就是通過調用聯(lián)系。調用時主調函數(shù)首先要完成實參將值傳給被調函數(shù)的形式參數(shù),借用這個機會,如果實參傳給對應形參的是值,那么形參可以利用這個值完成計算;實參如果傳給對應形參的是地址,那么對應的形式參數(shù)獲得實參的地址,就可以在自己的函數(shù)內(nèi)部完成對對應實參的訪問,這就是間接訪問。具體地定義求二元一次方程組的解的函數(shù)見圖5:
實參的調用語句為:solve(a1,b1,c1,a2,b2,c2,&x;,&y;);。調用時實參a1-c2是傳值給對應的形參,對應的形參與之對應關系是單向賦值,形參只從實參那里得到了值。而實參x,y傳給對應形參指針變量px和py的是地址,當獲得了實參的地址,指針變量就可以通過內(nèi)存地址間接的訪問對應的實參,圖5程序中*px的值就是x的值,*py就是變量y。這樣被調函數(shù)通過被傳地址的指針變量間接地為主調函數(shù)范圍內(nèi)有效的變量x,y賦過了值,這就是間接訪問。這個明白了再了解了指針移動等運算,指針部分的掌握也就不成問題了。
這部分學習建立在應用基礎上,以任務作為驅動,讓C語言學習過程中的幾個難點部分從簡開始,易于讓初學者接受和掌握,這樣學起來會更有信心。
3 學習第三步:上機實現(xiàn)
C語言程序設計的學習,理論分析、編碼與上機實踐同等重要[7],程序完成了但不在機上運行是毫無意義的。所以程序在計算機上運行正確無誤才是任務的最終完成。初學者一定要重視這個環(huán)節(jié)。如果運行錯誤要仔細分析錯誤原因,若要弄清楚需后退回到第一步和第二步再做修改,直到運行無誤為止。無論是問題的分析還是算法的設計,抑或是編碼時的C語言語法,上機運行可以實現(xiàn)對前面的學習檢驗同時更有效地豐富經(jīng)驗。上機實驗時,熟悉所用工具的開發(fā)環(huán)境也是很重要的。當前C語言的編程大多采用合適的集成開發(fā)環(huán)境,比如dev cpp及codeblocks等,無論哪一種熟練掌握它的操作,特別是出現(xiàn)錯誤時的錯誤提示、調試和分析程序運行的手段,對于初學者都是很重要的??傊嬎銠C語言的學習理論和實踐同等重要。
4 結論
學校講課及學生學習編程時,都是從學習語法開始講授或是學習,學習之初學生就開始背誦語法。語法是語言的基礎和規(guī)則,當然很重要,可以說沒有掌握語法,就無法編寫出正確的程序。但是對初學者來說,機械地背誦語言,很容易忘掉且不容易牢記。本文從初學程序設計的學生出發(fā),論述了從分析問題開始,以任務驅動為主要方式,讓學生掌握編程的步驟:分析問題、設計算法、確定步驟,并形成習慣。論文再以C語言學習時的難點為內(nèi)容,采取案例的方式說明克服它們的方法,目的是希望初學者從簡單問題開始,循序漸進使學生在潛移默化中學會程序設計。
參考文獻:
[1] 倪瑞曉.C語言編程技術的分析研究[J].計算機技術與發(fā)展,2009,19(12):251-254.
[2] 胡明,王紅梅.程序設計基礎:從問題到程序[M].北京:清華大學出版社,2011.
[3] 裘宗燕.今天的C程序設計課教什么,怎么教——兼議《從問題到程序》的修訂[J].計算機教育,2012,13(7):24-32.
[4] 李娟,張燕.C語言循環(huán)結構教學的設計與實踐[J].計算機教育,2018(3):89-91.
[5] 蘇冬娜,高俊濤.基于C語言的計算機編程技術分析[J].信息與電腦, 2016(18):54-55.
[6] 張蕾.基于項目化教學的"C語言程序設計"課程改革[J].計算機教育,2013(2):17-20.
[7] 夏秋菊.在C語言教學中如何培養(yǎng)學生的動手編程能力[J].新課程學習:下,2013(2).
【通聯(lián)編輯:王力】