本書是一本以計算思維訓練為核心,以能力培養為目標的C語言程序設計教材,基于程序設計 = 算法思維 語言藝術 工程規范的知識和能力框架和前期以培養解題思路為主,語法知識夠用就行;后期補充必要的語法細節的教學策略編寫。全書共9單元可分為4個部分。
第1部分是針對C程序設計的初級訓練:第1單元介紹進行C語言程序設計首先應當掌握的一些基本概念和方法;第2、3單元在第1單元的基礎上介紹判斷結構和重復結構,第4單元介紹窮舉、迭代、遞歸和模擬,奠定算法基礎。
第2部分是在第1部分的基礎上進行數據類型的擴展:第5單元介紹數組,第6單元介紹3種可定制數據結構構造體、共用體和枚舉,第7單元介紹指針及其應用。
第3部分只有第8單元一單元,介紹分治、回溯、貪心策略和動態規劃,作為算法設計進階,可以使讀者的程序設計能力提升到較高水平。
第4部分用第9單元一單元介紹一些可能用得著的有關內容,包括外部變量、內聯函數、帶參宏定義、文件和位操作。
這樣的結構可以滿足多種不同層次的教和學的需求,并兼顧自學。
作者在編寫本書時力求概念準確、難點分散、例題經典、習題豐富、題型全面、注重效果,并以C99作為藍本,可以作為高等學校各專業的新一代程序設計課程教材,也可供從事程序設計相關領域的人員自學或參考。
以C99標準為藍本。? 零起點,實例引導,輕松入門,逐步深入。? 按照程序設計 = 計算思維 語言藝術 工程規范的指導思想編寫。? 貫穿算法分析和測試設計相互配合的現代程序設計教學方法。? 習題類型多、題量大,覆蓋面寬。? 結構獨特,適合不同層次、不同目的的學習需求。
第3版前言(一)這是一個信息時代。作為時代的寵兒,計算機在各行各業發揮著神奇的威力,而其靈魂來自程序設計。現在,程序設計不僅被視為計算機以及相關專業的看家本領,而且也成為這個時代文化的一部分,它所蘊含的邏輯思維給所有想開發腦力的人提供一種貼近時代的訓練。為此,程序設計不僅作為計算機及其相關專業的必修課程被開設,而且幾乎所有的理工科專業,甚至一些文科和藝術類專業也在開設。屈指計算,程序設計課程已經開設半個多世紀了,但是教學效果卻不盡如人意。因此,程序設計課程的改革成為課程改革的一個難點。筆者從20世紀80年代開始就將其作為自己努力的一個方向,不斷進行探索。最早進行的改革是將典型算法,如窮舉、迭代、遞歸和一些軟件工程的方法融入程序設計教學中。這些成果反映在筆者的第一本著作《BASIC程序設計》(山西科學教育出版社,1985)中。之后,在這方面繼續探索,在程序設計教學中進一步加入算法與數據結構的內容,以使學生得到更加系統的思維訓練。這些探索成果總結在由筆者主筆、譚浩強主編的《BASIC程序設計教程》(高等教育出版社,1988)中。但是,這本書引入的算法和數據結構內容過多,盡管到了21世紀最初幾年還有學校在使用它,但普遍反映其教學難度太大。20世紀90年代中期,受國家考試中心邀請,筆者在NIT(國家信息技術考試)主持C模塊的考試和教材編寫。受CIT(劍橋信息技術測試)教材的啟發,將程序測試加入到筆者編寫的《程序設計(C語言)》(清華大學出版社,1999年)一書中,并且在這本書中將傳統的語法體系改為問題體系。之后,在教學中不斷修正,同時把改革擴展到面向對象程序設計(C 、Java)中。在C語言方面,筆者先后出版了《新概念C語言程序設計》(中國鐵道出版社,2003)、《C語言程序設計案例教程》(清華大學出版社,2004)、《新概念C程序設計教程》(南京大學出版社,2007)、《新概念C語言教程》(中國電力出版社,2011)、《新概念C程序設計大學教程》(清華大學出版社,2012)、《新概念C程序設計(C99版)》。經過幾十年的摸索,一套全新的C程序設計教學改革的框架逐漸明朗:* 實現從語法體系向問題體系的轉變。* 建立程序設計 = 算法思維 語言藝術 工程規范的知識和能力框架。* 樹立以計算思維訓練為核心,以能力培養為目標的指導思想。* 采用前期以培養解題思路為主,語法知識夠用就行;后期補充必要的語法細節的教學策略。* 按照問題分析-設計代碼-語法說明線索進行局部安排。令筆者欣慰的是,目前類似的書已經陸續問世,品種不斷增加,這說明這支C語言程序設計教學改革的隊伍在不斷壯大。(二)C語言是一種高效、靈活、可移植、功能強大的程序設計語言。C語言從20世紀70年代初創立,迄今已半個多世紀還經久不衰,是程序設計語言歷史上壽命最長的語言。世界著名的TIOBE編程語言社區排行榜是編程語言流行趨勢的一個風向標,每月更新,其數據取樣于互聯網上有經驗的程序員、商業應用、著名搜索引擎(如谷歌、MSN、雅虎等)的關鍵字排名、Alexa上的排名等。圖0.1為其在2016年1月份發表的排行榜圖,可以看出其他程序設計語言跌宕起伏,而C語言一直名列前茅。非但如此,多種位于前列的程序設計語言(如C 、Java、C#、Objective C等)都是以C語言為母體發展起來的。所以,學習程序設計從C語言開始是一種明智的選擇。
圖0.1 2016年1月份發表的TIOBE編程語言社區排行榜當然,C語言也在不斷發展之中。1978年美國電話電報公司(AT&T)的貝爾實驗室正式發表了C語言。開發者B.W.Kernighan和D.M.Ritchie隨即編寫了著名的《The C Programming Language》一書,通常簡稱為《K&R C》,也有人稱之為K&R C標準。但是,K&R C第一版在很多語言細節上不夠精確。1983年美國國家標準化協會(American National Standards Institute)制定了一個C語言標準并于同年發表,通常稱之為ANSI C,并在此基礎上不斷修訂,于1989年末提出了一個報告[ANSI 89]。1990年,國際標準化組織ISO(International Organization for Standards)通過了此項標準,將其作為ISO/IEC 9899:1990國際標準,俗稱C89或C90。1995年,ISO修訂C90,形成1995基準增補1(ISO/IEC/9899/AMD1:1995),俗稱C89修正案1或C95。1999年通過ISO/IEC 9899:1999,ISO對C語言標準進行了更重要的改變,俗稱C99。2011年12月8號,ISO 發布了 C 語言的新標準ISO/IEC 9899:2011,俗稱C11。但是,國內C程序設計教材多數還基于C89甚至更早的標準,這種落后使得教學脫離應用,與世界潮流很不合拍。因此當務之急是過渡到C99,這是編寫本書的一個主要動機。在出版本書之前,筆者已經在清華大學出版社出版了《新概念C程序設計大學教程(C99版)》,本書在此基礎上進一步完善而成。目前支持C99并且簡單易用的開發平臺是DEV C ,它有兩款,即Orwell Dev-C 和wxDev-C 。截止到本書定稿,Orwell Dev-C 的最新版本是5.7.0,wxDev-C 的穩定版本是7.4.2,它們的下載地址分別如下。http://bloodshed-dev-c.en.softonic.com/http://sourceforge.net/projects/orwelldevcpp/?source=typ_redirecthttp://wxdsgn.sourceforge.net/(三)本書基于以計算思維訓練為核心,以能力培養為目標的教學模式和前期以培養解題思路為主,語法知識夠用就行;后期補充必要的語法細節的教學策略編寫。全書共9單元可分為4個部分。第1部分是針對C程序設計的初級訓練:第1單元介紹進行C語言程序設計首先應當掌握的一些基本概念和方法;第2、3單元在第1單元的基礎上介紹判斷結構和重復結構,第4單元介紹窮舉、迭代、遞歸和模擬,奠定算法基礎。然而這個基礎比較厚重,要想不沖淡突出程序設計思路的主體,又把這個厚重的基礎語法講清楚,在時間上,特別是在課時上是不允許的。為此,這3單元中都含有3個部分內容,即主體部分、知識鏈接和習題。在主體部分只從如何使用的角度介紹筆者所遇到的語法知識,把進一步的、較為系統的介紹放到知識鏈接中介紹。教師在講授時可以以主體部分為主,參考知識鏈接部分;或者把知識鏈接部分作為學生課后的閱讀材料使用。這樣就可以解決學習內容厚重與教學學時有限之間的矛盾,也可以激發學生自學的熱情,滿足不同學生的學習需求。在這一部分還介紹了非常重要但在之前被忽略的一些語法知識,例如表達式的副作用以及序列點等。第2部分是在第1部分的基礎上進行數據類型的擴展,第5單元介紹數組,第6單元介紹3種可定制數據結構構造體、共用體和枚舉,第7單元介紹指針及其應用。第3部分只有第8單元一個單元,介紹分治、回溯、貪心策略和動態規劃,作為算法設計進階,可以使讀者的程序設計能力提升到較高水平。第4部分用第9單元一個單元介紹一些可能用得著的有關內容,包括外部變量、內聯函數、帶參宏定義、文件和位操作。這樣的結構可以滿足多種不同層次的教和學的需求:以對程序設計作一般了解為目標者,可以重點學習第1部分,并對第2部分進行了解性學習;以掌握程序設計的基本方法為目標者,可以重點學習前兩部分內容,對第3部分和第4部分進行了解性學習;以較深入掌握程序設計的方法為目標者,可以在熟練前兩部分的基礎上,進一步深入學習第3部分和第4部分。(四)為了便于不同角度的復習與訓練,本書的習題中設置了5種欄目,即概念辨析、代碼分析、探索驗證、思維訓練和開發練習。概念辨析主要提供了一些選擇題和判斷題,旨在提高讀者對基礎語法知識的了解。代碼分析包括指出程序(或代碼段)執行結果、改錯和填空,旨在提高讀者的代碼閱讀能力,因為讀程序也是程序設計的一種基本訓練。探索驗證主要用于提示或者指導學習者如何通過自己的上機驗證來提高對語法知識的掌握,除了這個欄目中的習題以外,學習者最好能通過設計程序驗證自己對于概念辨析欄目中的習題的判斷是否正確。開發練習是一種綜合練習,應當要求學習者寫出開發文檔,內容主要包括問題(算法)分析、代碼設計、測試用例設計、測試及調試結果分析等幾個部分,重點應當放在問題分析、代碼設計和測試用例的設計上,要把這些都做好,再上機調試、測試,不要什么還沒有設計出來就去上機。思維訓練中給出了有一定難度的問題,只用于算法設計訓練,不要求給出程序。這個欄目僅在第4、5、8三個單元設置。為了有的放矢地進行一些重要專題的訓練,第4、7、8三個單元的習題以大節為單位給出。(五)在本書的編寫過程中,趙忠孝、張秋菊、張展為、張展赫、姚威、史林娟、戴璐、張友明、董兆軍等人參與了部分工作。此外,本書初稿完成之后,還承蒙《品悟C拋棄C程序設計中的謬誤與惡習》一書的作者薛非先生為本書提出了許多寶貴的意見。在本書即將出版之際,筆者由衷地感謝以上各位為本書所做的貢獻,也要感謝在本書編寫過程中參考過的有關資料的作者,包括一些網絡佚名作者。同時,殷切地期待廣大讀者和同仁的批評與建議,讓我們共同努力,把程序設計課程的改革做得更有實效。
張基溫 2017年1月羊城小海之畔
張基溫,知名學者,計算機教育家,研究和教學領域涉及計算機科學與技術、信息管理、信息經濟學、電子政務與電子商務、服務科學,發表論文百余篇,出版著作百余種;先后擔任名古屋大學訪問學者,山西財經大學、江南大學、華東政法大學、福建工程學院、晉城學院、廣西職業技術學院等多所大學的專職、客座或兼職教授,北京大學博雅方略城市發展與信息化研究中心研究員,南京大學出版社總編顧問,太原高新技術區IT研究院實驗室主任,山西省緊缺人才專家委員會副主任等職,中國信息經濟學會常務理事,全國高等院校計算機基礎教育研究會常務理事兼課程建設委員會副主任,中國計算機學會教育專業委員會委員,教育部NIT考試委員會委員,江蘇省計算機基礎教學指導委員會委員,山西省新世紀專家學者協會副會長;為清華大學出版社、電子工業出版社、中國水利水電出版社、南京大學出版社等出版社主編了信息管理與信息系統專業、計算機實驗與實踐、大學生信息素養等多個系列教材。在面向過程程序設計教學領域,從20世紀80年代初就開始進行有關研究和改革,嘗試將軟件工程方法和算法思想引入程序設計,倡導程序設計 = 計算思維 語言藝術 工程規范的程序設計教育理念,推行以思維訓練為核心,程序測試與程序設計并行、前期重在邏輯思維和方法訓練、語法夠用就行;后期進行語法細節補充的程序設計課程教學方法。他主筆并與他人聯合署名的《C語言程序設計教程》是*十一五規劃教材,并于2007年被評為*精品教材。
目錄
第1單元 C程序啟步 1
1.1 一個簡單的計算器程序設計 1
1.1.1
用偽代碼描述的簡單計算器程序算法 1
1.1.2
將偽代碼描述的算法逐步細化為C程序 2
1.1.3
C語言程序的編譯、鏈接與執行 4
1.2 數據類型、標識符與聲明 6
1.2.1
數據類型 6
1.2.2
C語言標識符規則 6
1.2.3
聲明 7
1.3 表達式 8
1.3.1
字面量 8
1.3.2
數據實體 8
1.3.3
含有操作符的表達式及其求值規則 10
1.3.4
C語言的實現定義行為和未定義行為 13
1.4 函數 13
1.4.1
用函數組織程序 13
1.4.2
函數定義、函數調用與函數返回 15
1.4.3
函數聲明 16
1.4.4
main()函數 17
1.4.5
庫函數與頭文件 17
1.4.6
printf()函數的基本用法 18
1.4.7
scanf()函數的基本用法 19
1.5 程序測試 22
1.5.1
程序中的語法錯誤和邏輯錯誤 22
1.5.2
程序運行中的異常與錯誤 22
1.5.3
程序測試及其觀點 22
1.5.4
程序的靜態測試與動態測試 23
1.5.5
設計用戶友好的程序 23
1.6 知識鏈接A:整數類型 24
1.6.1
有符號整數類型與無符號整數類型 24
1.6.2
標準整數類型與擴展整數類型 25
1.6.3
宏與整數類型的極值宏 26
1.6.4
整數常量使用的3種進制 27
1.6.5
整數常量的標識 27
1.7 知識鏈接B:浮點類型 28
1.7.1
浮點類型的值的特性:取值范圍與精度 28
1.7.2
浮點數據的舍入模式 29
1.7.3
浮點類型數據的操作限制 30
1.7.4
浮點類型常量的書寫格式 30
1.7.5
_Complex類型和_Imaginary類型 31
1.8 知識鏈接C:字符類型 31
1.8.1
字符編碼概述 31
1.8.2
char類型的基本特點 32
1.8.3
轉義字符 33
1.8.4
用scanf()和printf()輸入與輸出字符 33
1.8.5
用getchar()和putchar()輸入與輸出字符 34
習題1 35
第2單元 選擇程序設計 42
2.1 可選擇計算類型的計算器程序算法分析 42
2.1.1
粗略算法分析 42
2.1.2
計算函數calculate()的算法分析 43
2.1.3
判等操作符與關系操作符 44
2.2
if-else型選擇結構 44
2.2.1
用if-else實現的calculate()函數 44
2.2.2
if-else結構的特點 45
2.2.3
if-else if結構 46
2.2.4
瘸腿if-else嵌套結構 47
2.2.5
邏輯操作符與邏輯表達式 48
2.2.6
條件表達式 49
2.2.7
良好的程序書寫風格 50
2.3 選擇結構的測試 51
2.3.1
白箱測試法 51
2.3.2
使用double類型數據的calculate()代碼 52
2.3.3
等價分類法 53
2.4
switch型選擇結構 56
2.4.1
基于整數值匹配的選擇結構switch結構 56
2.4.2
一個字符分類程序 57
2.4.3
用switch結構實現的calculate()函數 59
2.4.4
switch結構與if-else結構的比較 60
2.5 知識鏈接D:變量的訪問屬性 61
2.5.1
變量的生存期與標識符的作用域 61
2.5.2
局部變量 63
2.6 知識鏈接E:#include指令與const限定符 66
2.6.1
#define指令 66
2.6.2
const限定符 67
2.7 知識鏈接F:左值表達式與右值表達式 68
2.7.1
左值表達式與右值表達式的概念 69
2.7.2
左值表達式的應用 70
習題2 71
第3單元 重復程序設計 82
3.1 可連續計算的計算器算法分析 82
3.1.1
初步算法 82
3.1.2
算法細化 82
3.1.3
重復結構的C語言實現 83
3.2
while結構 83
3.2.1
while結構的基本原理 83
3.2.2
采用while結構的可連續型計算器主函數 84
3.2.3
逗號操作符 85
3.3
do-while結構 86
3.3.1
do-while結構的基本原理 86
3.3.2
采用do-while結構的可連續型計算器主函數 86
3.4 for結構 87
3.4.1
for結構的基本原理 87
3.4.2
采用for結構的可連續型計算器主函數 87
3.4.3
計數型重復結構 89
3.4.4
復合賦值操作符與增值、自減操作符 93
3.5 重復結構的程序測試 94
3.5.1
基于路徑覆蓋的重復結構測試 94
3.5.2
邊值分析法與重復結構測試 94
3.5.3
基于因果分析的程序測試 96
3.6
break與continue 98
3.6.1
break與continue語法概要 98
3.6.2
實例:求素數 99
3.7 知識鏈接G:表達式的副作用與序列點 101
3.7.1
表達式的副作用 101
3.7.2
序列點及其對表達式求值順序的影響 102
3.7.3
副作用編程對策 104
3.8 知識鏈接H:算術數據類型轉換 105
3.8.1
算術表達式中的數據類型轉換 105
3.8.2
普通算術轉換中的提升拉齊規則 105
3.8.3
傳送轉換中的數據類型轉換 107
3.8.4
數據的顯式類型轉換 108
3.8.5
數據類型轉換風險 109
習題3 113
第4單元 算法基礎 121
4.1 窮舉 121
4.1.1
搬磚問題 122
4.1.2
推斷名次 124
習題4.1 128
4.2 迭代與遞推 132
4.2.1
用二分迭代法求方程在指定區間的根 133
4.2.2
猴子吃桃子問題 136
4.2.3
用輾轉相除法求兩個正整數的最大公因子 138
習題4.2 141
4.3 遞歸 144
4.3.1
階乘的遞歸計算 144
4.3.2
漢諾塔 147
4.3.3
臺階問題 150
習題4.3 151
4.4 模擬算法 152
4.4.1
產品隨機抽樣 153
4.4.2
用蒙特卡洛法求(的近似值 156
4.4.3
事件步長法中子擴散問題 157
4.4.4
時間步長法鹽水池問題 159
習題4.4 163
第5單元 數組 166
5.1 一維數組 166
5.1.1
數組類型的特征 166
5.1.2
數組的定義 167
5.1.3
數組的初始化 168
5.1.4
下標變量 169
5.1.5
變長數組與常量數組 170
5.2 排序與查找 171
5.2.1
直接選擇排序 171
5.2.2
冒泡排序 173
5.2.3
二分查找 176
5.3 二維數組 177
5.3.1
二維數組的概念 177
5.3.2
二維數組的初始化 178
5.3.3
訪問二維數組元素 180
5.4 字符串 181
5.4.1
字符串字面量 181
5.4.2
字符數組與C字符串變量 182
5.4.3
字符串的輸入與輸出 183
5.4.4
字符串操作的庫函數 186
習題5 189
第6單元 可定制數據類型 195
6.1 構造體類型 195
6.1.1
構造體類型的特征與定制 195
6.1.2
用typedef定義類型的別名 196
6.1.3
構造體變量 197
6.1.4
構造體變量的分量及其操作 200
6.1.5
構造體數組 201
6.1.6
復合字面量 204
6.2 共用體類型 205
6.2.1
共用體類型的定制及其變量的定義 205
6.2.2
共用體類型與構造體類型的比較 206
6.2.3
共用體變量的應用舉例 208
6.3 枚舉類型 210
6.3.1
枚舉類型及其定義 210
6.3.2
枚舉變量及其聲明 211
6.3.3
對枚舉變量和枚舉元素的操作 211
6.3.4
用枚舉為類提供整型符號常量名稱 212
習題6 212
第7單元 指針 220
7.1 指針類型與指針變量 220
7.1.1
指針及其聲明 220
7.1.2
同類型指針間的賦值與判等操作 221
7.1.3
指針的遞引用 223
7.1.4
void指針 224
7.1.5
用const限定指針 224
習題7.1 225
7.2 數組與指針 230
7.2.1
數組名具有退化的左值性 230
7.2.2
下標表達式的指針性質 231
7.2.3
指針與字符串 233
7.2.4
二維數組與指針 235
習題7.2 237
7.3 函數與指針 243
7.3.1
指針作為函數參數 243
7.3.2
帶參主函數 250
7.3.3
返回指針值的函數 251
7.3.4
函數類型與指向函數的指針 252
習題7.3 258
7.4 指向構造體的指針與鏈表 262
7.4.1
指向構造體類型變量的指針 262
7.4.2
鏈表及其特點 263
7.4.3
構建鏈表 264
習題7.4 266
7.5 動態存儲分配 270
7.5.1
申請需要的存儲空間 270
7.5.2
釋放一個指針指向的存儲空間 272
7.5.3
修改一個指針指向的存儲空間大小 273
7.5.4
構建動態鏈表 273
7.5.5
帶有彈性數組成員的構造體 277
習題7.5 278
第8單元 算法設計進階* 280
8.1 分治策略 280
8.1.1
快速排序 280
8.1.2
自行車帶人問題 283
習題8.1 286
8.2 回溯策略 288
8.2.1
迷宮問題 289
8.2.2
八皇后問題 292
習題8.2 294
8.3 貪心策略 296
8.3.1
旅行費用問題 296
8.3.2
刪數問題 299
習題8.3 301
8.4 動態規劃 303
8.4.1
動態規劃概述 303
8.4.2
點數值三角形的最優路徑 305
8.4.3
背包問題 307
習題8.4 311
第9單元 語海拾貝 314
9.1 外部變量 314
9.1.1
外部變量及其定義 314
9.1.2
外部變量的鏈接性 314
9.1.3
外部變量的風險 319
9.2 帶參宏 319
9.2.1
帶參宏的基本定義格式 319
9.2.2
使用帶參宏的注意事項 320
9.2.3
帶參宏與函數的比較 321
9.3 內聯函數 322
9.3.1
內聯函數的概念 322
9.3.2
內聯函數的定義 323
9.3.3
內聯函數的限制 323
9.4 數據文件 324
9.4.1
數據文件及其分類 324
9.4.2
FILE類型及其指針 325
9.4.3
數據文件操作的一般過程 326
9.4.4
程序示例 330
9.5 位操作與位段 331
9.5.1
按位邏輯運算 332
9.5.2
移位運算 333
9.5.3
位段 334
習題9 336
附錄A C語言運算符的優先級和結合方向 344
附錄B C語言的關鍵字 345
附錄C 格式化輸出函數printf()的格式 346
C.1
printf()格式參數的結構 346
C.2
printf()格式符 346
C.3 長度修飾符 347
C.4 域寬與精度說明 348
C.5 格式前綴修飾符 348
附錄D 格式化輸入函數scanf()的格式 349
D.1
scanf()指針參數 349
D.2
scanf()格式參數的結構 349
D.2.1
格式參數字符串的結構 349
D.2.2
基本格式符和長度修正 349
D.2.3
字段寬度 350
D.3
scanf()的停止與返回 351
D.4 數值數據的輸入控制 351
D.5 字符型數據的輸入控制 351
D.5.1
在格式字段前添加空格使格式字段可以跳過空白字符 351
D.5.2
用掃描集控制字符數組的讀入 351
附錄E 編譯預處理命令 352
E.1 宏定義 352
E.2 文件包含 352
E.3 條件編譯 352
附錄F C標準庫頭文件 353
附錄G C語言常用的標準庫函數 354
G.1 數學函數 354
G.2 字符函數和字符串函數 355
G.3 輸入與輸出函數 356
G.4 動態內存分配函數 357
G.5 退出程序函數 358
G.6 數值轉換函數 358
G.7 時間和日期函數 358
附錄H C99、C89與K&R C 主要內容的比較 360
參考文獻 361