時至今日,C語言仍然是計算機領域的通用語言之一,但今天的C語言已經和最初的時候大不相同了。本書最主要的一個目的就是通過一種“現代方法”來介紹C語言,書中強調標準C,強調軟件工程,不再強調“手工優化”。這一版中緊密結合了C99標準,并與C89標準進行對照,補充了C99中的最新特性。本書分為C語言的基礎特性、C語言的高級特性、C語言標準庫和參考資料4個部分。每章末尾都有一個“問與答”小節給出一系列與該章內容相關的問題及答案,此外還包含適量的習題。
本書是為大學本科階段的C語言課程編寫的教材,同時也非常適合作為其他課程的輔助用書。
作者簡介:K.N.King 世界知名的計算機程序設計教育家,佐治亞州立大學數學與計算機科學系副教授。耶魯大學計算機科學碩士,加州大學伯克利分校計算機科學博士,曾任教于佐治亞理工學院。除本書外,他還撰寫了廣受歡迎的教材Java Programming:From the Beginning,并在Dr.Dobbs Journal等權威雜志上發表了許多論文。業余時間,King教授還在多部電影中扮演過角色。
《C語言程序設計:現代方法(第2版)》是C語言的經典之作,被譽為“近10年來最好的一部C語言著作”。書中討論了標準C和C標準庫的全部特性,包括信號、setjmp/longjmp和可變參數列表等其他書中很少涉及的內容。全書由易而難、循序漸進、螺旋式地講述C語言,很好地處理了指針和位運算等難點。第2版覆蓋了C99標準,并提供了對所有C99庫函數的參考,還擴展了GCC的內容,增加了對抽象數據類型的討論,并針對新CPU和操作系統做了更新!禖語言程序設計:現代方法(第2版)》尤為強調軟件工程和現代編程理念,在知識的闡述中突出工業界的最佳實踐、實際經驗和編程風格,使讀者能夠合理運用所學,編寫出可讀性好、可靠性高和容易維護的代碼。書中精心選擇了近500道習題,貼近實戰,與敘述文字相得益彰! ∧壳啊禖語言程序設計:現代方法(第2版)》已被全球200多所學校采用為教材,包括哈佛大學、麻省理工學院、斯坦福大學、加州大學伯克利分校、耶魯大學、加州理工學院等諸多名校。
在計算領域中,把顯而易見的轉變為有實用價值的,這一過程是“挫折”一詞的生動體現。
自本書第1版出版以來,基于C的語言大量興起(其中最杰出的代表是Java和C#),已有的C++和Perl等相關語言也取得了更大的成就。盡管如此,C語言仍然像當年一樣流行,仍然悄無聲息地掌控著世界上的許多軟件。跟1996年一樣,C語言仍然是計算機領域里的通用語言。
但即便是C語言也必須隨著時間而發展。C99標準的發布催生了對本書新版的需求,而且,第1版涉及的DOS和16位處理器也已經趨于過時。本版對內容進行了全面更新,并在其他許多方面進行了改進。
本版新增內容
下面列出了本版的新特色和所做的改進。
完整地覆蓋了C89標準和C99標準。本版和第1版最大的差別就在于覆蓋了C99標準。我的目標是覆蓋C89和C99之間的每一個重要差別,包括C99新增的所有語言特性和庫函數。C99中的每一處改變都會清楚地標出來,或者在小節標題中加上“C99”字樣,或者在討論比較簡短時在正文的左邊空白處用一個專門的圖標表示。我這樣做有兩個目的:一是提醒讀者注意C99中的改變,二是讓那些對C99不感興趣或沒有C99編譯器的讀者知道哪些內容可以跳過。C99新增的許多內容可能只有特定的讀者會感興趣,但有些新特性幾乎對所有的C程序員都有用。
提供了對所有C89和C99庫函數的快速參考。第1版中附錄D介紹了C89的所有標準庫函數,本版的附錄D給出了C89和C99的所有庫函數。
擴展了GCC的內容。自本書第1版出版以來,GCC(最初是GNU C Compiler的簡稱,現在指GNU Compiler Collection)得到了廣泛應用。GCC有很多優點,包括高性能、低成本(不用花錢)以及在眾多軟硬件平臺之間的可移植性等。由于認識到GCC日漸重要,我在本版中介紹了更多與GCC相關的信息,包括如何使用GCC以及常見的GCC錯誤消息和警告。
增加了對抽象數據類型的討論。在第1版中,第19章重點討論了C++。這部分內容現在看起來似乎作用不大,因為本書的讀者可能已經學過C++、Java或者C#了。在本版中,對C++的介紹替換為討論如何在C中建立抽象數據類型。
擴展了國際化特性的內容。本版第25章更加詳盡地討論了C語言的國際化特性。重點擴展了Unicode字符集及編碼。
針對CPU和操作系統做了更新。當我編寫本書第1版時,許多讀者用的還是16位機和DOS操作系統,但現在情況不同了。在本版中,我把討論的重點放在32位機和64位機上。盡管本版也介紹了Windows和Mac OS操作系統中影響C程序員的方面,但是針對Linux和其他UNIX版本的出現,我們的討論更側重于后一個系列的操作系統。
K. N. King 世界知名的計算機程序設計教育家,現為佐治亞州立大學數學與計算機科學系副教授。他擁有耶魯大學計算機科學碩士學位,加州大學伯克利分校計算機科學博士學位,曾任教于佐治亞理工學院。除本書外,他還撰寫了廣受歡迎的著作Modula-2: A Complete Guide 和Java Programming: From the Beginning,并在Dr.Dobbs Journal等權威雜志上發表了許多文章。
呂秀鋒,亞洲理工大學(AIT)計算機軟件碩士,現為北京理工大學軟件學院教師。多年來一直從事“計算機基礎(雙語)”、“C語言程序設計(雙語)”以及“程序設計開發與實踐”等本科生課程的教學工作,深受學生歡迎。她還譯有《數據結構與算法:C#語言描述》一書。
黃倩,中國科學院計算技術研究所工學博士,中國計算機學會會員。研究方向包括視頻處理、視頻監控等,已在知名的國際期刊和國際會議論文集上發表10篇論文。譯有《編程珠璣(第2版)》一書,受到讀者歡迎。
第1章 C語言概述1
1.1 C語言的歷史1
1.1.1 起源1
1.1.2 標準化1
1.1.3 基于C的語言2
1.2 C語言的優缺點3
1.2.1 C語言的優點3
1.2.2 C語言的缺點3
1.2.3 高效地使用C語言4
問與答5
第2章 C語言基本概念7
2.1 編寫一個簡單的C程序7
程序顯示雙關語7
2.1.1 編譯和鏈接8
2.1.2 集成開發環境8
2.2 簡單程序的一般形式9
2.2.1 指令9
2.2.2 函數9
2.2.3 語句10
2.2.4 顯示字符串10
2.3 注釋11
2.4 變量和賦值12
2.4.1 類型12
2.4.2 聲明13
2.4.3 賦值13
2.4.4 顯示變量的值14
程序計算箱子的空間重量14
2.4.5 初始化15
2.4.6 顯示表達式的值16
2.5 讀入輸入16
程序計算箱子的空間重量(改進版)16
2.6 定義常量的名字17
程序華氏溫度轉換為攝氏溫度17
2.7 標識符18
2.8 C程序的書寫規范19
問與答21
練習題23
編程題24
第3章 格式化輸入/輸出26
3.1 printf函數26
3.1.1 轉換說明27
程序用printf函數格式化數28
3.1.2 轉義序列28
3.2 scanf函數29
3.2.1 scanf函數的工作方法30
3.2.2 格式串中的普通字符31
3.2.3 易混淆的printf函數和scanf函數32
程序分數相加32
問與答33
練習題34
編程題35
第4章 表達式36
4.1 算術運算符36
程序計算通用產品代碼的校驗位38
4.2 賦值運算符39
4.2.1 簡單賦值40
4.2.2 左值41
4.2.3 復合賦值41
4.3 自增運算符和自減運算符42
4.4 表達式求值43
4.5 表達式語句45
問與答45
練習題47
編程題49
第5章 選擇語句50
5.1 邏輯表達式50
5.1.1 關系運算符50
5.1.2 判等運算符51
5.1.3 邏輯運算符51
5.2 if語句52
5.2.1 復合語句53
5.2.2 else子句53
5.2.3 級聯式if語句54
程序計算股票經紀人的傭金55
5.2.4 “懸空else”的問題56
5.2.5 條件表達式57
5.2.6 C89中的布爾值58
5.2.7 C99中的布爾值58
5.3 switch語句59
程序顯示法定格式的日期61
問與答62
練習題65
編程題67
第6章 循環69
6.1 while語句69
程序顯示平方表71
程序數列求和71
6.2 do語句72
程序計算整數的位數73
6.3 for語句73
6.3.1 for語句的慣用法74
6.3.2 在for語句中省略表達式75
6.3.3 C99中的for語句75
6.3.4 逗號運算符76
程序顯示平方表(改進版)77
6.4 退出循環78
6.4.1 break語句78
6.4.2 continue語句78
6.4.3 goto語句79
程序賬簿結算80
6.5 空語句81
問與答83
練習題84
編程題85
第7章 基本類型88
7.1 整數類型88
7.1.1 C99中的整數類型90
7.1.2 整數常量90
7.1.3 C99中的整數常量91
7.1.4 整數溢出91
7.1.5 讀/寫整數91
程序數列求和(改進版)92
7.2 浮點類型93
7.2.1 浮點常量94
7.2.2 讀/寫浮點數94
7.3 字符類型94
7.3.1 字符操作95
7.3.2 有符號字符和無符號字符95
7.3.3 算術類型96
7.3.4 轉義序列96
7.3.5 字符處理函數97
7.3.6 用scanf和printf讀/寫字符98
7.3.7 用getchar和putchar讀/寫字符98
程序確定消息的長度99
7.4 類型轉換100
7.4.1 常用算術轉換101
7.4.2 賦值過程中的轉換102
7.4.3 C99中的隱式轉換103
7.4.4 強制類型轉換103
7.5 類型定義105
7.5.1 類型定義的優點105
7.5.2 類型定義和可移植性105
7.6 sizeof運算符106
問與答107
練習題109
編程題110
第8章 數組113
8.1 一維數組113
8.1.1 數組下標113
程序數列反向115
8.1.2 數組初始化115
8.1.3 指定初始化式116
程序檢查數中重復出現的數字116
8.1.4 對數組使用sizeof運算符117
程序計算利息118
8.2 多維數組119
8.2.1 多維數組初始化120
8.2.2 常量數組121
程序發牌121
8.3 C99中的變長數組122
問與答123
練習題124
編程題125
第9章 函數129
9.1 函數的定義和調用129
程序計算平均值129
程序顯示倒計數130
程序顯示雙關語(改進版)131
9.1.1 函數定義132
9.1.2 函數調用133
程序判定素數134
9.2 函數聲明135
9.3 實際參數136
9.3.1 實際參數的轉換137
9.3.2 數組型實際參數138
9.3.3 變長數組形式參數140
9.3.4 在數組參數聲明中使用static141
9.3.5 復合字面量141
9.4 return語句142
9.5 程序終止143
9.6 遞歸144
程序快速排序146
問與答147
練習題150
編程題153
第10章 程序結構155
10.1 局部變量155
10.1.1 靜態局部變量156
10.1.2 形式參數156
10.2 外部變量156
10.2.1 示例:用外部變量實現棧156
10.2.2 外部變量的利與弊157
程序猜數158
10.3 程序塊161
10.4 作用域162
10.5 構建C程序163
程序給一手牌分類163
問與答169
練習題169
編程題170
第11章 指針172
11.1 指針變量172
11.2 取地址運算符和間接尋址運算符173
11.2.1 取地址運算符173
11.2.2 間接尋址運算符174
11.3 指針賦值174
11.4 指針作為參數176
程序找出數組中的最大元素和最小元素177
11.5 指針作為返回值179
問與答180
練習題181
編程題182
第12章 指針和數組184
12.1 指針的算術運算184
12.1.1 指針加上整數185
12.1.2 指針減去整數185
12.1.3 兩個指針相減186
12.1.4 指針比較186
12.1.5 指向復合常量的指針186
12.2 指針用于數組處理186
12.3 用數組名作為指針188程序數列反向(改進版)189
12.3.1 數組型實際參數(改進版)189
12.3.2 用指針作為數組名191
12.4 指針和多維數組191
12.4.1 處理多維數組的元素191
12.4.2 處理多維數組的行192
12.4.3 處理多維數組的列192
12.4.4 用多維數組名作為指針192
12.5 C99中的指針和變長數組193
問與答194
練習題195
編程題197
第13章 字符串198
13.1 字符串字面量198
13.1.1 字符串字面量中的轉義序列198
13.1.2 延續字符串字面量199
13.1.3 如何存儲字符串字面量199
13.1.4 字符串字面量的操作200
13.1.5 字符串字面量與字符常量200
13.2 字符串變量200
13.2.1 初始化字符串變量201
13.2.2 字符數組與字符指針202
13.3 字符串的讀和寫203
13.3.1 用printf函數和puts函數寫字符串203
13.3.2 用scanf函數和gets函數讀字符串203
13.3.3 逐個字符讀字符串204
13.4 訪問字符串中的字符205
13.5 使用C語言的字符串庫206
13.5.1 strcpy函數207
13.5.2 strlen函數208
13.5.3 strcat函數208
13.5.4 strcmp函數209程序顯示一個月的提醒列表209
13.6 字符串慣用法211
13.6.1 搜索字符串的結尾211
13.6.2 復制字符串213
13.7 字符串數組214
程序核對行星的名字217
問與答218
練習題220
編程題222
第14章 預處理器225
14.1 預處理器的工作原理225
14.2 預處理指令227
14.3 宏定義227
14.3.1 簡單的宏227
14.3.2 帶參數的宏229
14.3.3 #運算符231
14.3.4 ##運算符231
14.3.5 宏的通用屬性232
14.3.6 宏定義中的圓括號233
14.3.7 創建較長的宏233
14.3.8 預定義宏234
14.3.9 C99中新增的預定義宏235
14.3.10 空的宏參數236
14.3.11 參數個數可變的宏236
14.3.12 __func__標識符237
14.4 條件編譯237
14.4.1 #if指令和#endif指令238
14.4.2 defined運算符238
14.4.3 #ifdef指令和#ifndef指令239
14.4.4 #elif指令和#else指令239
14.4.5 使用條件編譯240
14.5 其他指令240
14.5.1 #error指令240
14.5.2 #line指令241
14.5.3 #pragma指令242
14.5.4 _Pragma運算符242
問與答243
練習題245
第15章 編寫大型程序248
15.1 源文件248
15.2 頭文件249
15.2.1 #include指令249
15.2.2 共享宏定義和類型定義250
15.2.3 共享函數原型251
15.2.4 共享變量聲明252
15.2.5 嵌套包含253
15.2.6 保護頭文件253
15.2.7 頭文件中的#error指令254
15.3 把程序劃分成多個文件254程序文本格式化255
15.4 構建多文件程序260
15.4.1 makefile260
15.4.2 鏈接期間的錯誤262
15.4.3 重新構建程序262
15.4.4 在程序外定義宏264
問與答264
練習題265
編程題266
第16章 結構、聯合和枚舉267
16.1 結構變量267
16.1.1 結構變量的聲明267
16.1.2 結構變量的初始化269
16.1.3 指定初始化269
16.1.4 對結構的操作270
16.2 結構類型270
16.2.1 結構標記的聲明271
16.2.2 結構類型的定義272
16.2.3 結構作為參數和返回值272
16.2.4 復合字面量273
16.3 嵌套的數組和結構274
16.3.1 嵌套的結構274
16.3.2 結構數組274
16.3.3 結構數組的初始化275程序維護零件數據庫275
16.4 聯合281
16.4.1 用聯合來節省空間282
16.4.2 用聯合來構造混合的數據結構284
16.4.3 為聯合添加“標記字段”284
16.5 枚舉285
16.5.1 枚舉標記和類型名286
16.5.2 枚舉作為整數286
16.5.3 用枚舉聲明“標記字段”286
問與答287
練習題289
編程題293
第17章 指針的高級應用294
17.1 動態存儲分配294
17.1.1 內存分配函數294
17.1.2 空指針295
17.2 動態分配字符串296
……
第18章 聲明 327
第19章 程序設計 345
第20章 底層程序設計 363
第21章 標準庫 377
第22章 輸入/輸出 384
第23章 庫對數值和字符數據的支持 419
第24章 錯誤處理 446
第25章 國際化特性 456
第26章 其他庫函數 482
第27章 C99對數學計算的新增支持 503
附錄A C語言運算符 524
附錄B C99與C89的比較 525
附錄C C89與經典C的比較 529
附錄D 標準庫函數 532
附錄E ASCII字符集 569
參考文獻 570
索引 573
C語言的輸入/輸出庫是標準庫中最大且最重要的部分。由于輸入/輸出是C語言的高級應用,因此這里將用一整章(本書中最長的一章)來討論頭——輸入/輸出函數存放的主要地方。
從第2章開始,我們已經在使用了,而且已經對printf函數、scanf函數、putchar函數、getchar函數、puts函數以及gets函數的使用有了一定的了解。本章會提供更多有關這6個函數的信息,并介紹一些新的用于文件處理的函數。值得高興的是,許多新函數和我們已經熟知的函數有著緊密的聯系。例如,printf函數就是printf函數的“文件版”。
本章的開始將會討論一些基本問題:流的概念、FILE類型、輸入和輸出重定向以及文本文件和二進制文件的差異(22.1節)。隨后將轉入討論特別為使用文件而設計的函數,包括打開和關閉文件的函數(22.2節)。在討論完printf函數、scanf函數以及與“格式化”輸入/輸出相關的函數(22.3節)以后,我們將著眼于讀/寫非格式化數據的函數。
·每次讀寫一個字符的getc函數、putc函數以及相關的函數(22.4節)。
·每次讀寫一行字符的gets函數、puts函數以及相關的函數(22.5節)。
·讀/寫數據塊的fread函數和fwri七e函數(22.6節)。隨后,22.7節會說明如何對文件上執行隨機的訪問操作。最后,22.8節會描述sprintf函數、snpr·intf函數和sscanf函數,它們是printf函數和scan£函數的變體,后兩者分別用于寫入和讀取一個字符串。
本章涵蓋了中的絕大部分函數,但忽略了其中8個函數。perror函數是這8個函1數中的一個,它與頭緊密相關,所以我把它推遲到24.2節討論頭時進行介紹。26.1節涵蓋了其余7個函數(vfprintf、vprintf、vsprintf、vsnprintf、vfscanf、vscanf和vsscanf)。這些函數依賴于valist類型,該類型在26.1節介紹。
在C89r扣,所有的標準輸入/輸出函數都屬于但C99有所不同,有些輸入/輸出函數在.頭(25.5節)中聲明。中的函數用于處理寬字符而不是普通字符,但大多數函數與中的函數緊密相關。中用于讀或寫數據的函數稱為宇節輸入/輸出函數,而中的類似函數則稱為寬字符輸入/輸出函數。