譚浩強教授所著的《C程序設計》一書受到國內專家和讀者的一致好評,被公認為學習C語言程序設計的優秀教材,被全國大多數高校選用,是學習C語言的主流用書。已累計發行了1250多萬冊,創同類書的全國發行最高紀錄。
針對我國應用型大學的實際情況,譚浩強教授于21世紀初在《C程序設計》一書的基礎上編寫出版了《C語言程序設計》,降低起點,精簡內容,通俗易懂,突出重點,緊扣基本要求,使讀者容易學習。該書出版后受到廣泛歡迎,十多年已出了兩版,重印50多次。本書是在《C語言程序設計(第2版)》的基礎上修訂再版的。
在這次修訂中,保持了原書概念清晰、通俗易懂的特點,同時根據C99新標準介紹程序設計,體現教材的先進性和規范性,并且更加容易學習與入門。本書定位準確,體系科學,內容適當、取舍合理、例題豐富,分析透徹。作者采用的“提出問題—解決問題—歸納分析”的三部曲,符合初學者的認知規律,取得很好的效果。
凡具有計算機初步知識的讀者都能讀懂本書。本書可作為應用型大學各專業學習C語言程序設計的教材,基礎較好的高職高專也可選用,本書也是不可多得的用于自學的好教材。
本書還配有輔助教材《C語言程序設計(第3版)學習輔導》。
程序設計是計算機工作者的一項基本功。C語言是在國內外廣泛學習和使用的一種計算機語言,受到廣大計算機愛好者的喜愛。我國幾乎所有的理工科大學都開設了C語言程序設計課程。
為了使C語言程序設計課程教學取得更好的效果,需要弄清楚幾個問題:
1. 為什么要學習程序設計
計算機的本質是“程序的機器”,程序和指令的思想是計算機系統中最基本的概念。只有懂得程序設計,懂得計算機是怎樣工作的,才能較深入地理解和應用計算機,才能較好地懂得怎樣使計算機按照人們的意圖進行工作。學習程序設計,能學到計算機處理問題的方法,培養計算思維,培養分析問題和解決問題的能力。
雖然非計算機專業的大學生,大多數將來并不一定會成為專業的軟件開發人員,不一定有許多機會用C語言編寫實用程序,但是在大學期間仍然需要學習程序設計。通過學習程序設計,使大學生具有程序設計的初步知識,具有編寫程序的初步能力,知道軟件開發的過程和特點,有利于各專業人士在今后工作中與程序開發人員溝通合作,進行應用軟件的開發工作。因此,大學生(尤其是理工類學生)學習程序設計是很有好處的。
具體地說,學習程序設計的目的有兩個方面: (1)學習用計算機解決問題的思路和方法;(2)學習怎樣用計算機工具去實現算法,即實現用計算機解題。
2. C語言是基礎而實用的語言
進行程序設計,必須用計算機語言作為工具,否則只是紙上談兵。可供選擇的語言很多,各有特點。C語言是基礎而實用的語言。并不是每一種語言都具有此特點的,有的語言實用,但不能作為基礎語言(如FORTRAN),有的語言可以作為基礎,但實際應用不多(如Pascal)。C語言功能豐富、表達能力強、使用靈活方便、應用面廣、目標程序效率高、可移植性好。既具有高級語言的優點,又具有低級語言的許多特點,既適合于編寫系統軟件,又能方便地用來編寫應用軟件。是多年來在國內外使用最廣泛的語言。國內外許多專家認為,C語言是最基本的通用語言,有了C語言的基礎,以后過渡到任何一種語言(如C++,C#,Java)都不會困難。C語言被認為是計算機專業人員的基本功。
3. 正確處理好算法和語法的關系
C程序設計課程既有基礎的性質(了解計算機處理問題的方式,學習算法),又有應用和工具的性質(掌握語言工具,具有編程的初步能力,能具體應用)。因此,既要注意講清概念,使學生建立正確的概念,又要培養學生實際處理問題的能力。
程序設計有4個要素: (1)算法是程序的靈魂;(2)數據結構是加工的對象;(3)語言是編程工具(算法要通過語言來實現);(4)要采用合適的程序設計方法。程序設計教學是否成功取決于能否將以上4個要素(尤其是算法與語言二者)緊密結合。
本書自始至終把這4個要素自然有機地結合起來,全面兼顧。算法和語法二者都很重要,都要重視。本書不是孤立地介紹語法,也不是全面系統地介紹算法,更不是根據語言規則的分類和順序作為教學和教材的章節和順序,而是從應用的角度出發, 以編程為目的和主線,由淺入深地介紹怎樣用C語言處理問題,把算法和語法緊密結合,同步展開,步步深入。作者精心安排順序,算法的選擇由易而難,細心選擇例子,使該讀者容易學習。在此基礎上,構造了新的教學和教材體系。
具體的做法是: 在每一章中,首先舉幾個簡單的例子,引入新的問題;接著介紹怎樣利用C語言去解決簡單的問題;然后再循序漸進地介紹較深入的算法和程序。使學生在富有創意、引人入勝的編程過程中,學會了算法,掌握了語法,領悟了程序設計的思想和方法。把枯燥無味的語法規則變成生動活潑的編程應用。多年的實踐表明,這種做法是成功的。
既然要學習編寫程序,就離不開計算機語言。如果不掌握語法規則的應用,連最簡單的程序也編寫不出來,或者錯誤百出。問題不是要不要掌握語言工具,而是通過什么方法學習和掌握語言工具的使用方法,是枯燥地死記語法規則,還是通過實例掌握語言的使用?初學時可以學習最基本的語法現象而淡化語法的細節,有些細節不必一一講授,可以讓學生自查自學。
建議教師在講授時,以程序為中心展開,著重講清解題思路以及怎樣用程序去實現它,不要孤立介紹語法規定,教材中敘述的語法規定,可以在介紹編寫程序的過程中加以說明,或在作簡單介紹后請學生自己閱讀,并通過上機實踐掌握它。
4. 在學習和應用計算機過程中培養計算思維
計算機基礎教育應該面向計算機應用,著眼于提高大學生的計算機應用能力,培養各個領域中的計算機應用人才,同時在教學過程中要注意培養學生的科學思維和信息素養。計算思維是科學思維的一部分。有專家認為: 計算思維是運用計算機科學的基礎概念進行問題求解、系統設計和理解人類行為的思維活動。計算思維的本質是抽象和自動化。程序設計中的算法思維就是典型的計算思維。學習程序設計的過程就是培養計算思維的過程。
作者認為: 計算思維是在學習和應用計算機的過程中自然而然地培養的,計算思維并不神秘,它是自然而然的結果,而不是生硬進行的過程;是本身存在的內在關聯,而不是外界強加的概念。我們要善于在教學過程中有意識地引導學生善于思考,掌握規律,舉一反三,養成科學思維(包括計算思維)。
培養計算思維不是最終目的。培養計算思維是為了更好地應用計算機,培養更多更好的計算機應用人才。
5. 要從實際出發,準確定位
在學習C語言程序設計的人群中,有不同的情況和要求。有的是計算機專業的,有的是非計算機專業的;有的是本科生,有的是高職生;有的來自研究型大學,有的來自應用技術型大學;有的以后成為計算機專業人員,有的是計算機應用人員;有的要求精通,有的要求粗通,有的則只求一般了解。必須準確定位,從具體實際出發,對不同對象提出不同的要求。不可能要求一個沒有計算機基礎的人,通過三四十學時的課程就能精通程序設計,掌握復雜的算法,編寫出復雜的程序。要求必須恰當,內容要有所取舍。在有限的學時內,只能學習基本的內容,為今后進一步的學習和使用打下必要的基礎。如果有少數人將來需要熟練地編程,甚至成為專業的軟件開發人員,則應當在學習本課程的基礎上繼續進行更深入的學習,例如至少應當完成一個綜合作業,開發一個具有一定規模的應用軟件的實踐項目。
本書的對象是應用型大學本科學生,程度較高的高職(大專)學生也可以用本書作為教材。
為了推動C程序設計教學,作者于1991年在全國率先編著了《C程序設計》一書,由清華大學出版社出版,向全國發行。各校師生普遍認為該書內容全面而系統、概念清晣而易懂,例題豐富,講解詳盡、包含了許多其他教材中沒有的內容,尤其是針對編程實踐中容易出現的問題作了分析,被認為是學習C語言程序設計的理想教材,至今已出版了四版,重印180次。21世紀初,作者根據不同學校(尤其是應用型大學)的需要,在《C程序設計》一書的基礎上,編寫出版了《C語言程序設計》一書,適當降低要求,精簡內容,降低起點,更加易于學習,很受廣大師生歡迎。被教育部定為“普通高等教育十一五國家級規劃教材”,向全國推薦,至今已出版了兩版,重印50余次。以上這兩本程度不同的教材至今已累計發行超過1250萬冊,成為大學C程序設計的主流用書,有力地推動了我國高校的C程序設計教學。
本書是在《C語言程序設計(第2版)》的基礎上進行修訂的。修訂中遵循以下原則:
(1) 保持原有特點和風格。由于作者所著的《C程序設計》和《C語言程序設計》內容全面,敘述清晰,通俗易懂,在教學實踐中取得了很好的效果,因此在修訂時盡量保持原有的優點,基本上保留原書的體系,注意概念準確,講解透徹,使讀者對C語言和程序設計有全面、完整的理解。
(2) 按照C99標準進行介紹,以適應C語言的發展,使編寫程序更加規范。目前國內許多介紹C語言的教材是按照C89標準介紹的,而國外的同類教材已改為以C99標準為藍本。本書按照C99標準的規定介紹程序設計,例如:
① 數據類型中,C99增加了雙長整型(long long int)、復數浮點型(float_complex,double_complex,long long _complex)、布爾型(bool)等。
② 根據C99的建議,main函數的類型一律指定為int型,并在函數的末尾加返回語句“return 0;”。
③ C99增加了注釋行的新形式——以雙斜線“//”開始的內容作為注釋行,這本來是C++的注釋行形式,現在C99把它擴充進來了,使編程更加方便。同時保留了原來的“/* …… */”形式,以使原來按C89標準編寫的程序可以不加修改仍可使用。本書采用C99的注釋新形式,讀者使用更方便,而且符合發展需要。因此,本書的程序基本上采用下面的形式: #include // 以"http://"作為注釋行的開始
int main() // 指定main函數為int類型
{
return 0; // 如函數正常執行,返回整數0
}
由于C99是在C89的基礎上增加或擴充一些功能而成的,因此C89和C99基本上是兼容的。過去用C89編寫的程序在C99環境下仍然可以運行。C99所增加的許多新的功能和規則,是在編制比較復雜的程序時為方便使用和提高效率而用的,在初學時可以不涉及,因此本書對目前暫時用不到的內容不作介紹,以免讀者分心,增加學習難度。在將來進行深入編程時再逐步了解和學習。
(3) 加強算法,強化解題思路。在介紹例題時,先進行問題分析,探討解題思路,構造算法,然后才是根據算法編寫程序,而不是先列出程序再解釋程序。在各章中由淺入深地結合例題介紹各種典型的算法。對窮舉、遞推、迭代、遞歸、排序(包括比較交換法、選擇法、起泡法)、矩陣運算、字符處理應用等算法作了詳細的介紹,對難度較大的鏈表操作的算法作了清晰的思路說明。引導讀者在拿到題目后,先考慮算法再編程,而不是坐下來就寫程序,以培養好的習慣,培養算法思維。
(4) 更加通俗易懂,容易學習。作者充分考慮到廣大初學者的情況,精心設計體系,適當降低門檻,便于讀者入門。盡量少用深奧難懂的專業術語,用通俗易懂的方法和語言闡述清楚復雜的概念,使復雜的問題簡單化。沒有學過計算機原理和高等數學的讀者完全可以掌握本書的內容。
本書采用作者提出的“提出問題—解決問題—歸納分析”的新的教學三部曲,先具體后抽象,先實際后理論,先個別后一般。而不是先抽象后具體,先理論后實際,先一般后個別。實踐證明這樣做符合讀者的認知規律,讀者很容易理解。
在介紹每個例題時,都采取以下的步驟: 給出問題→解題思路→編寫程序→運行結果→程序分析→程序改進。對有關內容用說明、注意、提醒、思考等標注,并用楷體字以引起注意。這種方法符合讀者認知規律,使讀者思路更加清晰,更容易接受和理解。通過運行程序,讀者看到結果,便于驗證算法的正確性,學習過程不覺得抽象,而會覺得算法具體有趣,看得見,摸得著。
在每一章的最后有“本章小結”,歸納本章的要點,提綱挈領,畫龍點睛,以加深印象,增強條理性。
本書便于自學。具有高中以上文化水平的人,即使沒有教師講解,也能基本掌握本書的內容。這樣,就有可能做到: 教師少講,提倡自學,上機實踐。
(5) 把教學內容分為基本要求和提高要求兩個部分。這是考慮到不同對象的要求的差別。在各章中把一部分較深入的內容作為“提高部分”,單獨列出,放在各章的最后,供學生選學和參考。如果學時不夠,可以只學基本部分。通過學習基本部分,能初步掌握C程序設計的基本內容,寫出相對簡單的程序,如果希望學習得更深入一些,掌握更多的編程思路和技巧,可以選學各章的“提高部分”。也可以教師講授基本部分,學生自學“提高部分”,以培養學生的自學能力。
應當怎樣學習C語言程序設計呢?作者給出以下建議:
(1) 在開始學習時不要死記語法細節。請記住: 重要的是學會編程序,而不是背語法。一開始就要學會看懂程序,編寫簡單的程序,然后逐步深入。有一些語法細節是需要通過較長期的實踐才能熟練地掌握的。初學時,切忌過早地濫用C語言的某些容易引起錯誤的細節(如不適當地使用++和--的副作用)。
(2) 不能設想今后一輩子只使用在學校里學過的某一種語言。但是無論用哪一種語言進行程序設計,其基本思路和方法都是一樣的。從這個意義上說,在大學里學哪一種語言,并不是很重要的原則問題。學會了一種計算機語言,可以很快地學會另一種語言。因此,在學習時一定要學活用活,舉一反三,掌握規律,在以后需要時能很快地掌握其他語言進行工作。
(3) 在學校學習階段,主要是學習程序設計的方法,進行程序設計的基本訓練,打下將來進一步學習的基礎。學習程序設計課程時,應該把精力放在最基本、最常用的內容上,學好基本功。如果對學生有較高的程序設計要求,應當在學習本課程后,安排一次集中的課程設計環節,完成有一定規模的程序設計。
(4) 程序設計是一門實踐性很強的課程,既要掌握概念,又要動手編程,還要上機調試運行,希望讀者一定要重視實踐環節,包括編程和上機。既會編寫程序,又會調試程序。衡量這門課學習的好壞,不是“知不知道”,而是“會不會干”。 考核的方法不應當采用標準題(是非題或選擇題),而應當把重點放在編制程序和調試程序上。
(5) 使用哪一種編譯系統并不是原則問題。程序編好以后,用哪一種編譯系統進行編譯都可以。讀者不應該只會用某一種編譯環境,應當了解、接觸和使用不同的編譯環境。不同的編譯系統,其功能和使用方法有些不同,編譯時給出的信息也不完全相同,要注意參閱使用說明書,特別要在使用中積累經驗,舉一反三。
為了幫助讀者學習本書,作者還編寫了本書的配套參考書《C語言程序設計(第3版)學習輔導》,提供本書中各章習題的參考答案以及上機實習指導。
薛淑斌高級工程師和金瑩副教授參加了本書的修訂。許多高校老師多年來使用本教材,提出了許多寶貴的意見和建議,使本書得以日臻完善。在此謹向一切幫助和支持過作者的人士表示由衷的感謝。
本書肯定會有不少缺點和不足,熱切期望得到專家和讀者的批評指正。
譚浩強2014年3月1日于清華園
第1章程序設計與C語言1
1.1計算機與程序、程序設計語言1
1.2C語言的出現和發展過程2
1.3簡單的C語言程序2
1.4運行C程序的步驟與方法7
1.4.1運行C程序的步驟7
1.4.2上機運行C程序的方法8
本章小結15
習題16
第2章數據的存儲與運算17
2.1數據在計算機中是怎樣存儲的17
2.1.1數據在計算機中是以二進制形式存儲的17
2.1.2位、字節和地址18
2.1.3不同類型數據的存儲方式19
2.2整型數據的運算與分析21
2.2.1整型數據運算程序舉例和分析21
2.2.2整型常量與整型變量23
2.3實型數據的運算與分析26
2.3.1實型數據的運算舉例26
2.3.2實型常量的表示形式28
2.3.3實型變量29
2.4字符型數據的運算31
2.4.1字符數據運算的簡單例子31
2.4.2字符常量和字符變量32
2.4.3字符串常量36
2.5符號常量37
2.5.1為什么要用符號常量 38
2.5.2符號常量的性質和使用方法40
2.6算術運算符和算術表達式41
2.6.1算術運算符41
2.6.2算術表達式43
2.7C運算符和C表達式45
2.7.1C運算符45
2.7.2C表達式46
2.8提高部分46
2.8.1求補碼的方法46
2.8.2整型常量的表示形式47
2.8.3整型變量的類型47
2.8.4整型常量的類型48
2.8.5C語言允許使用的數據類型49
2.8.6運算符的優先級與結合性50
本章小結50
習題51
第3章最簡單的C程序設計——順序程序設計53
3.1算法是程序的靈魂53
3.1.1什么是算法53
3.1.2怎樣表示算法55
3.2程序的三種基本結構58
3.3C語句綜述59
3.4賦值表達式和賦值語句62
3.4.1賦值表達式62
3.4.2賦值過程中的類型轉換64
3.4.3賦值語句65
3.4.4變量賦初值66
3.5數據輸入輸出的概念67
3.6字符數據的輸入輸出68
3.6.1用putchar函數輸出一個字符69
3.6.2用getchar函數輸入一個字符70
3.7簡單的格式輸入與輸出72
3.7.1用簡單的printf函數輸出數據72
3.7.2用簡單的scanf函數輸入數據76
3.8順序結構程序設計舉例79
3.9提高部分83
3.9.1關于無符號數據與有符號數據之間的賦值83
3.9.2較復雜的輸入輸出格式控制85
3.9.3簡單易用的C++的輸入輸出92
本章小結93
習題94
第4章選擇結構程序設計96
4.1條件判斷96
4.1.1條件判斷的含義96
4.1.2關系運算符和關系表達式97
4.1.3邏輯運算符和邏輯表達式98
4.2用if語句實現選擇結構102
4.2.1用if語句實現選擇結構舉例102
4.2.2if語句的一般形式104
4.2.3if語句使用的說明104
4.2.4使用嵌套的if語句實現多層條判斷106
4.3利用switch語句實現多分支選擇結構110
4.4程序綜合舉例112
4.5提高部分116
4.5.1用條件表達式實現簡單的選擇結構116
4.5.2在程序中使用條件表達式118
本章小結119
習題120
第5章循環結構程序設計123
5.1程序中需要用循環結構123
5.2用while語句和dowhile語句實現循環124
5.2.1用while語句實現循環124
5.2.2用dowhile語句實現循環126
5.3用for 語句實現循環128
5.3.1for語句的一般形式和執行過程128
5.3.2for循環程序舉例 129
5.4循環的嵌套133
5.5提前結束循環133
5.5.1用break語句提前退出循環 133
5.5.2用continue語句提前結束本次循環135
5.6幾種循環的比較137
5.7循環程序綜合舉例137
5.8提高部分142
5.8.1while和dowhile循環的比較142
5.8.2for語句的各種形式143
本章小結147
習題147
第6章利用數組處理批量數據149
6.1為什么要用數組149
6.2怎樣定義和引用一維數組149
6.2.1怎樣定義一維數組150
6.2.2怎樣引用一維數組的元素150
6.2.3一維數組的初始化152
6.2.4一維數組程序舉例153
6.3怎樣定義和引用二維數組156
6.3.1怎樣定義二維數組 156
6.3.2怎樣引用二維數組的元素157
6.3.3二維數組的初始化157
6.3.4二維數組程序舉例159
6.4字符數組162
6.4.1怎樣定義字符數組及對其初始化 162
6.4.2怎樣引用字符數組163
6.4.3字符串和字符串結束標志164
6.4.4怎樣進行字符數組的輸入輸出166
6.4.5字符串處理函數168
6.4.6字符數組應用舉例169
6.5提高部分173
6.5.1為什么在定義二維數組時采用兩對雙括號的
形式173
6.5.2對C的字符串函數的詳細說明174
本章小結178
習題179
第7章用函數實現模塊化程序設計181
7.1函數是什么181
7.2函數的定義和調用184
7.2.1為什么要定義函數184
7.2.2怎樣定義函數184
7.2.3怎樣調用函數185
7.2.4對被調用函數的聲明和函數原型188
7.3函數的嵌套調用和遞歸調用191
7.3.1函數的嵌套調用191
7.3.2函數的遞歸調用193
7.4數組作為函數參數199
7.4.1用數組元素作函數實參199
7.4.2用數組名作函數參數200
7.5變量的作用域和生存期207
7.5.1變量的作用域——局部變量和全局變量207
7.5.2變量的存儲方式和生存期210
7.5.3關于作用域和生存期的小結214
7.6內部函數和外部函數215
7.6.1什么是內部函數215
7.6.2什么是外部函數215
7.7提高部分218
7.7.1實參求值的順序218
7.7.2遞歸的典型例子——Hanoi(漢諾)塔問題218
本章小結221
習題223
第8章善于使用指針 225
8.1什么是指針225
8.2指針變量226
8.2.1使用指針變量訪問變量的例子226
8.2.2怎樣定義指針變量228
8.2.3怎樣引用指針變量229
8.2.4指針變量作為函數參數231
8.3通過指針引用數組236
8.3.1數組元素的指針236
8.3.2通過指針引用數組元素237
8.3.3用數組名作函數參數241
8.4通過指針引用字符串246
8.4.1字符串的表示形式246
8.4.2字符指針作函數參數250
8.4.3使用字符指針變量和字符數組的區別254
8.5提高部分257
8.5.1指針使用的技巧257
8.5.2多維數組的指針259
8.5.3指向函數的指針260
8.5.4返回指針值的函數260
8.5.5指針數組261
8.5.6多重指針——指向指針的指針262
本章小結263
習題265
第9章使用結構體類型處理組合數據——用戶自定義
數據類型2679.1定義和使用結構體變量267
9.1.1自己建立結構體類型267
9.1.2定義結構體類型變量269
9.1.3結構體變量的初始化和引用271
9.2結構體數組275
9.3結構體指針278
9.4用結構體變量和結構體變量的指針作函數參數282
9.5用指針處理鏈表285
9.5.1什么是線性鏈表285
9.5.2建立簡單的靜態鏈表286
9.5.3建立動態鏈表287
9.6提高部分289
9.6.1共用體類型289
9.6.2枚舉類型290
本章小結293
習題294
第10章利用文件保存數據295
10.1C文件的有關概念295
10.1.1什么是文件295
10.1.2文件名296
10.1.3文件的分類296
10.1.4文件緩沖區297
10.1.5文件指針297
10.2文件的打開與關閉298
10.2.1用fopen函數打開數據文件298
10.2.2用fclose函數關閉文件300
10.3文件的順序讀寫300
10.3.1向文件讀寫字符301
10.3.2向文件讀寫一個字符串304
10.3.3文件的格式化讀寫308
10.3.4用二進制方式讀寫文件308
10.4文件的隨機讀寫312
10.4.1文件位置標記及其定位313
10.4.2隨機讀寫文件315
10.5提高部分317
10.5.1系統定義的文件指針317
10.5.2回車換行符的轉換317
10.5.3fread和fwrite函數用于二進制文件的輸入
輸出318
10.5.4文件讀寫的出錯檢測318
本章小結319
習題320
附錄A常用字符與ASCII代碼對照表322
附錄BC語言中的關鍵字323
附錄C運算符和結合性324
附錄DC語言常用語法提要326
附錄EC庫函數331
參考文獻337