《21天學通C (第8版)》通過大量短小精悍的程序詳細而全面地闡述了C 基本概念和技術,以及C 11、C 14和C 17新增的功能,包括管理輸入 輸出、循環和數組、面向對象編程、模板、使用標準模板庫、列表初始化、lambda表達式、自動類型推斷等。這些內容被組織成結構合理、聯系緊密的章節,每章都可在1小時內閱讀完畢;每章都提供了示例程序清單,并輔以示例輸出和代碼分析,以闡述該章介紹的主題。為加深讀者對所學內容的理解,每章末尾都提供了常見問題及其答案以及練習和測驗。讀者可對照附錄E提供的測驗和練習答案,了解自己對所學內容的掌握程度。
《21天學通C (第8版)》是針對C 初學者編寫的,不要求讀者有C語言方面的背景知識,可作為高等院校教授C 課程的教材,也可供初學者自學C 時使用。
通過閱讀本書,讀者可快速掌握C 的基本知識并學習其中更高級的功能和概念。本書根據C 14標準進行了全面修訂,展望了C 17,并從實用的角度詮釋C 語言,幫助讀者學習如何使用它創建速度更快、更簡潔、更高效的C 應用程序。
掌握C 和面向對象編程的基本知識。
理解如何使用lambda表達式、移動構造函數和賦值運算符等C 功能編寫簡潔、高效的代碼。
學習C 編程的實踐并避開常見的陷阱。
學習標準模板庫,包括大多數真實C 應用程序都要用到的容器和算法。
使用每章末尾的練習來檢驗對知識的掌握程度。
本書特色:
無需任何編程經驗;
編寫速度更快、功能更強大的C 程序,編譯源代碼并創建可執行文件;
學習封裝、抽象、繼承和多態等面向對象編程概念;
使用標準模板庫中的算法和容器編寫功能豐富而穩定的C 應用程序;
學習自動類型推斷是如何幫助簡化C 代碼的;
使用lambda表達式、智能指針和移動構造函數完成復雜的編程工作;
通過向編程專家學習,掌握C 功能;
學習能夠用來編寫出簡潔且高性能應用程序的C 功能;
展望C 17有望引入的新功能。
讀者可通過www.epubit.com.cn book details 4780下載本書源代碼。
Siddhartha Rao是全球領先的企業軟件提供商SAP SE負責安全響應的副總裁。C 的發展讓他深信,您能編寫速度更快、更簡潔、更強大的C 應用程序。Siddhartha酷愛旅游,還是山地自行車運動的狂熱愛好者;他期待著您對本書的反饋。
第1章 緒論1
1.1 C 簡史1
1.1.1 與C語言的關系1
1.1.2 C 的優點1
1.1.3 C 標準的發展歷程2
1.1.4 哪些人使用C 程序2
1.2 編寫C 應用程序2
1.2.1 生成可執行文件的步驟2
1.2.2 分析并修復錯誤2
1.2.3 集成開發環境3
1.2.4 編寫第一個C 應用程序3
1.2.5 生成并執行第一個C 應用程序4
1.2.6 理解編譯錯誤5
1.3 C 新增的功能5
1.4 總結5
1.5 問與答6
1.6 作業6
1.6.1 測驗6
1.6.2 練習6
第2章 C 程序的組成部分8
2.1 Hello World程序的組成部分8
2.1.1 預處理器編譯指令#include9
2.1.2 程序的主體main( )9
2.1.3 返回值10
2.2 名稱空間的概念10
2.3 C 代碼中的注釋11
2.4 C 函數12
2.5 使用std::cin和std::cout執行基本輸入
輸出操作14
2.6 總結15
2.7 問與答15
2.8 作業15
2.8.1 測驗16
2.8.2 練習16
第3章 使用變量和常量17
3.1 什么是變量17
3.1.1 內存和尋址概述17
3.1.2 聲明變量以訪問和使用內存17
3.1.3 聲明并初始化多個類型相同的
變量19
3.1.4 理解變量的作用域19
3.1.5 全局變量20
3.1.6 命名約定22
3.2 編譯器支持的常見C 變量類型22
3.2.1 使用bool變量存儲布爾值23
3.2.2 使用char變量存儲字符23
3.2.3 有符號整數和無符號整數的
概念24
3.2.4 有符號整型short、int、long和
long long24
3.2.5 無符號整型unsigned short、unsigned int、unsigned long和unsigned long long25
3.2.6 選擇正確的數據類型以免發生
溢出錯誤25
3.2.7 浮點類型float和double26
3.3 使用sizeof確定變量的長度26
3.4 使用auto自動推斷類型28
3.5 使用typedef替換變量類型29
3.6 什么是常量30
3.6.1 字面常量30
3.6.2 使用const將變量聲明為常量30
3.6.3 使用constexpr定義常量表達式31
3.6.4 枚舉32
3.6.5 使用#define定義常量34
3.7 不能用作常量或變量名的關鍵字34
3.8 總結35
3.9 問與答36
3.10 作業37
3.10.1 測驗37
3.10.2 練習37
第4章 管理數組和字符串38
4.1 什么是數組38
4.1.1 為何需要數組38
4.1.2 聲明和初始化靜態數組39
4.1.3 數組中的數據是如何存儲的39
4.1.4 訪問存儲在數組中的數據40
4.1.5 修改存儲在數組中的數據41
4.2 多維數組43
4.2.1 聲明和初始化多維數組44
4.2.2 訪問多維數組中的元素44
4.3 動態數組45
4.4 C風格字符串46
4.5 C 字符串:使用std::string48
4.6 總結50
4.7 問與答50
4.8 作業50
4.8.1 測驗51
4.8.2 練習51
第5章 使用表達式、語句和運算符52
5.1 語句52
5.2 復合語句(語句塊)53
5.3 使用運算符53
5.3.1 賦值運算符(=)53
5.3.2 理解左值和右值53
5.3.3 加法運算符( )、減法運算符( )、乘法運算符(*)、除法運算符( )和求模運算符(%)53
5.3.4 遞增運算符( )和遞減運算符
( )54
5.3.5 前綴還是后綴55
5.3.6 相等運算符(==)和不等運算符
(!=)56
5.3.7 關系運算符56
5.3.8 邏輯運算NOT、AND、OR和
XOR58
5.3.9 使用C 邏輯運算NOT(!)、AND(&&)和OR(||)59
5.3.10 按位運算符NOT(~)、AND(&)、OR(|)和XOR(^)63
5.3.11 按位右移運算符(>>)和左移
運算符(<<)64
5.3.12 復合賦值運算符65
5.3.13 使用運算符sizeof確定變量占用
的內存量67
5.3.14 運算符優先級68
5.4 總結69
5.5 問與答69
5.6 作業70
5.6.1 測驗70
5.6.2 練習70
第6章 控制程序流程71
6.1 使用if…else有條件地執行71
6.1.1 使用if…else進行條件編程72
6.1.2 有條件地執行多條語句73
6.1.3 嵌套if語句74
6.1.4 使用switch-case進行條件處理77
6.1.5 使用運算符 :進行條件處理80
6.2 在循環中執行代碼81
6.2.1 不成熟的goto循環81
6.2.2 while循環83
6.2.3 do…while循環84
6.2.4 for循環86
6.2.5 基于范圍的for循環88
6.3 使用continue和break修改循環的
行為90
6.3.1 不結束的循環無限循環90
6.3.2 控制無限循環91
6.4 編寫嵌套循環93
6.4.1 使用嵌套循環遍歷多維數組94
6.4.2 使用嵌套循環計算斐波納契
數列95
6.5 總結96
6.6 問與答96
6.7 作業97
6.7.1 測驗97
6.7.2 練習97
第7章 使用函數組織代碼99
7.1 為何需要函數99
7.1.1 函數原型是什么100
7.1.2 函數定義是什么101
7.1.3 函數調用和實參是什么101
7.1.4 編寫接受多個參數的函數101
7.1.5 編寫沒有參數和返回值的函數103
7.1.6 帶默認值的函數參數103
7.1.7 遞歸函數調用自己的函數105
7.1.8 包含多條return語句的函數106
7.2 使用函數處理不同類型的數據107
7.2.1 函數重載107
7.2.2 將數組傳遞給函數109
7.2.3 按引用傳遞參數110
7.3 微處理器如何處理函數調用111
7.3.1 內聯函數112
7.3.2 自動推斷返回類型113
7.3.3 lambda函數114
7.4 總結115
7.5 問與答116
7.6 作業116
7.6.1 測驗116
7.6.2 練習116
第8章 闡述指針和引用118
8.1 什么是指針118
8.1.1 聲明指針119
8.1.2 使用引用運算符(&)獲取變量的
地址119
8.1.3 使用指針存儲地址120
8.1.4 使用解除引用運算符(*)訪問
指向的數據122
8.1.5 將sizeof( )用于指針的結果124
8.2 動態內存分配125
8.2.1 使用new和delete動態地分配和
釋放內存125
8.2.2 將遞增和遞減運算符( 和 )
用于指針的結果127
8.2.3 將關鍵字const用于指針129
8.2.4 將指針傳遞給函數130
8.2.5 數組和指針的類似之處131
8.3 使用指針時常犯的編程錯誤133
8.3.1 內存泄露133
8.3.2 指針指向無效的內存單元133
8.3.3 懸浮指針(也叫迷途或失控
指針)134
8.3.4 檢查使用new發出的分配請求是否得到滿足135
8.4 指針編程最佳實踐137
8.5 引用是什么137
8.5.1 是什么讓引用很有用138
8.5.2 將關鍵字const用于引用139
8.5.3 按引用向函數傳遞參數140
8.6 總結140
8.7 問與答141
8.8 作業142
8.8.1 測驗142
8.8.2 練習142
第9章 類和對象144
9.1 類和對象144
9.1.1 聲明類145
9.1.2 作為類實例的對象145
9.1.3 使用句點運算符訪問成員146
9.1.4 使用指針運算符(->)訪問成員146
9.2 關鍵字public和private147
9.3 構造函數150
9.3.1 聲明和實現構造函數150
9.3.2 何時及如何使用構造函數151
9.3.3 重載構造函數152
9.3.4 沒有默認構造函數的類154
9.3.5 帶默認值的構造函數參數155
9.3.6 包含初始化列表的構造函數156
9.4 析構函數157
9.4.1 聲明和實現析構函數157
9.4.2 何時及如何使用析構函數158
9.5 復制構造函數160
9.5.1 淺復制及其存在的問題160
9.5.2 使用復制構造函數確保深復制162
9.5.3 有助于改善性能的移動構造
函數166
9.6 構造函數和析構函數的其他用途166
9.6.1 不允許復制的類167
9.6.2 只能有一個實例的單例類167
9.6.3 禁止在棧中實例化的類169
9.6.4 使用構造函數進行類型轉換171
9.7 this指針172
9.8 將sizeof( )用于類173
9.9 結構不同于類的地方175
9.10 聲明友元176
9.11 共用體:一種特殊的數據存儲
機制178
9.11.1 聲明共用體178
9.11.2 在什么情況下使用共用體178
9.12 對類和結構使用聚合初始化180
9.13 總結183
9.14 問與答183
9.15 作業184
9.15.1 測驗184
9.15.2 練習184
第10章 實現繼承185
10.1 繼承基礎185
10.1.1 繼承和派生186
10.1.2 C 派生語法186
10.1.3 訪問限定符protected188
10.1.4 基類初始化向基類傳遞
參數190
10.1.5 在派生類中覆蓋基類的方法192
10.1.6 調用基類中被覆蓋的方法194
10.1.7 在派生類中調用基類的方法194
10.1.8 在派生類中隱藏基類的方法196
10.1.9 構造順序198
10.1.10 析構順序198
10.2 私有繼承200
10.3 保護繼承202
10.4 切除問題205
10.5 多繼承205
10.6 使用final禁止繼承207
10.7 總結208
10.8 問與答208
10.9 作業208
10.9.1 測驗208
10.9.2 練習209
第11章 多態210
11.1 多態基礎210
11.1.1 為何需要多態行為210
11.1.2 使用虛函數實現多態行為212
11.1.3 為何需要虛構造函數213
11.1.4 虛函數的工作原理理解
虛函數表217
11.1.5 抽象基類和純虛函數220
11.2 使用虛繼承解決菱形問題222
11.3 表明覆蓋意圖的限定符override225
11.4 使用final來禁止覆蓋函數226
11.5 可將復制構造函數聲明為虛函數嗎227
11.6 總結230
11.7 問與答230
11.8 作業231
11.8.1 測驗231
11.8.2 練習231
第12章 運算符類型與運算符重載232
12.1 C 運算符232
12.2 單目運算符233
12.2.1 單目運算符的類型233
12.2.2 單目遞增與單目遞減運算符234
12.2.3 轉換運算符236
12.2.4 解除引用運算符(*)和成員選擇
運算符(->)238
12.3 雙目運算符239
12.3.1 雙目運算符的類型240
12.3.2 雙目加法與雙目減法運算符240
12.3.3 實現運算符 =與 =242
12.3.4 重載等于運算符(==)和不等運算
符(!=)243
12.3.5 重載運算符<、>、<=和>=245
12.3.6 重載復制賦值運算符(=)248
12.3.7 下標運算符250
12.4 函數運算符operator()253
12.5 用于高性能編程的移動構造函數和
移動賦值運算符254
12.5.1 不必要的復制帶來的問題254
12.5.2 聲明移動構造函數和移動賦值
運算符254
12.6 用戶定義的字面量258
12.7 不能重載的運算符260
12.8 總結261
12.9 問與答261
12.10 作業261
12.10.1 測驗261
12.10.2 練習261
第13章 類型轉換運算符262
13.1 為何需要類型轉換262
13.2 為何有些C 程序員不喜歡C風格
類型轉換263
13.3 C 類型轉換運算符263
13.3.1 使用static_cast263
13.3.2 使用dynamic_cast和運行階段
類型識別264
13.3.3 使用reinterpret_cast267
13.3.4 使用const_cast267
13.4 C 類型轉換運算符存在的問題268
13.5 總結269
13.6 問與答269
13.7 作業270
13.7.1 測驗270
13.7.2 練習270
第14章 宏和模板簡介271
14.1 預處理器與編譯器271
14.2 使用#define定義常量271
14.3 使用#define編寫宏函數274
14.3.1 為什么要使用括號276
14.3.2 使用assert宏驗證表達式276
14.3.3 使用宏函數的優點和缺點277
14.4 模板簡介278
14.4.1 模板聲明語法278
14.4.2 各種類型的模板聲明279
14.4.3 模板函數279
14.4.4 模板與類型安全281
14.4.5 模板類281
14.4.6 聲明包含多個參數的模板282
14.4.7 聲明包含默認參數的模板283
14.4.8 一個模板示例283
14.4.9 模板的實例化和具體化284
14.4.10 模板類和靜態成員286
14.4.11 參數數量可變的模板287
14.4.12 使用static_assert執行編譯階段
檢查290
14.4.13 在實際C 編程中使用模板290
14.5 總結291
14.6 問與答291
14.7 作業291
14.7.1 測驗291
14.7.2 練習292
第15章 標準模板庫簡介293
15.1 STL容器293
15.1.1 順序容器293
15.1.2 關聯容器294
15.1.3 容器適配器294
15.2 STL迭代器295
15.3 STL算法295
15.4 使用迭代器在容器和算法之間交互295
15.5 選擇正確的容器297
15.6 STL字符串類298
15.7 總結298
15.8 問與答299
15.9 作業299
第16章 STL string類300
16.1 為何需要字符串操作類300
16.2 使用STL string類301
16.2.1 實例化和復制STL string301
16.2.2 訪問std::string的字符內容303
16.2.3 拼接字符串305
16.2.4 在string中查找字符或
子字符串306
16.2.5 截短STL string307
16.2.6 字符串反轉309
16.2.7 字符串的大小寫轉換310
16.3 基于模板的STL string實現311
16.4 總結312
16.5 問與答312
16.6 作業313
16.6.1 測驗313
16.6.2 練習313
第17章 STL動態數組類314
17.1 std::vector的特點314
17.2 典型的vector操作314
17.2.1 實例化vector314
17.2.2 使用push_back( )在末尾插入
元素316
17.2.3 列表初始化317
17.2.4 使用insert( )在指定位置插入
元素317
17.2.5 使用數組語法訪問vector中的
元素319
17.2.6 使用指針語法訪問vector中的
元素320
17.2.7 刪除vector中的元素321
17.3 理解大小和容量322
17.4 STL deque 類324
17.5 總結326
17.6 問與答326
17.7 作業327
17.7.1 測驗327
17.7.2 練習327
第18章 STL list和forward_list328
18.1 std::list的特點328
18.2 基本的list操作328
18.2.1 實例化std::list對象328
18.2.2 在list開頭或末尾插入元素330
18.2.3 在list中間插入元素331
18.2.4 刪除list中的元素333
18.3 對list中的元素進行反轉和排序334
18.3.1 使用list::reverse( )反轉元素的
排列順序334
18.3.2 對元素進行排序335
18.3.3 對包含對象的list進行排序以及
刪除其中的元素337
18.3.4 C 11引入的std::forward_list340
18.4 總結341
18.5 問與答342
18.6 作業342
18.6.1 測驗342
18.6.2 練習342
第19章 STL集合類343
19.1 簡介343
19.2 STL set和multiset的基本操作344
19.2.1 實例化std::set對象344
19.2.2 在set或multiset中插入元素345
19.2.3 在STL set或multiset中查找
元素347
19.2.4 刪除STL set或multiset中的
元素348
19.3 使用STL set和multiset的優缺點352
19.4 總結354
19.5 問與答355
19.6 作業355
19.6.1 測驗355
19.6.2 練習355
第20章 STL映射類356
20.1 STL映射類簡介356
20.2 STL map和multimap的基本操作357
20.2.1 實例化std::map和
std::multimap357
20.2.2 在STL map或multimap中插入
元素358
20.2.3 在STL map或multimap中查找
元素361
20.2.4 在STL multimap中查找元素363
20.2.5 刪除STL map或multimap中的
元素363
20.3 提供自定義的排序謂詞365
20.4 基于散列表的STL鍵-值對容器368
20.4.1 散列表的工作原理368
20.4.2 使用unordered_map和unordered_
multimap368
20.5 總結372
20.6 問與答372
20.7 作業372
20.7.1 測驗373
20.7.2 練習373
第21章 理解函數對象374
21.1 函數對象與謂詞的概念374
21.2 函數對象的典型用途374
21.2.1 一元函數374
21.2.2 一元謂詞378
21.2.3 二元函數380
21.2.4 二元謂詞381
21.3 總結383
21.4 問與答384
21.5 作業384
21.5.1 測驗384
21.5.2 練習384
第22章 lambda表達式385
22.1 lambda表達式是什么385
22.2 如何定義lambda表達式386
22.3 一元函數對應的lambda表達式386
22.4 一元謂詞對應的lambda表達式387
22.5 通過捕獲列表接受狀態變量的lambda
表達式388
22.6 lambda表達式的通用語法390
22.7 二元函數對應的lambda表達式391
22.8 二元謂詞對應的lambda表達式392
22.9 總結394
22.10 問與答394
22.11 作業395
22.11.1 測驗395
22.11.2 練習395
第23章 STL算法396
23.1 什么是STL算法396
23.2 STL算法的分類396
23.2.1 非變序算法396
23.2.2 變序算法397
23.3 使用STL算法398
23.3.1 根據值或條件查找元素398
23.3.2 計算包含給定值或滿足給定條件的
元素數400
23.3.3 在集合中搜索元素或序列401
23.3.4 將容器中的元素初始化為
指定值403
23.3.5 使用std::generate( )將元素設置為
運行階段生成的值405
23.3.6 使用for_each( )處理指定范圍內的
元素406
23.3.7 使用std::transform( )對范圍進行
變換407
23.3.8 復制和刪除操作409
23.3.9 替換值以及替換滿足給定條件的
元素412
23.3.10 排序、在有序集合中搜索以及刪除
重復元素413
23.3.11 將范圍分區415
23.3.12 在有序集合中插入元素417
23.4 總結419
23.5 問與答419
23.6 作業419
23.6.1 測驗420
23.6.2 練習420
第24章 自適應容器:棧和隊列421
24.1 棧和隊列的行為特征421
24.1.1 棧421
24.1.2 隊列422
24.2 使用STL stack類422
24.2.1 實例化stack422
24.2.2 stack的成員函數423
24.2.3 使用push( )和pop( )在棧頂插入和
刪除元素424
24.3 使用STL queue類425
24.3.1 實例化queue425
24.3.2 queue的成員函數426
24.3.3 使用push( )在隊尾插入以及使用
pop( )從隊首刪除427
24.4 使用STL優先級隊列428
24.4.1 實例化priority_queue類428
24.4.2 priority_queue的成員
函數429
24.4.3 使用push( )在priority_queue末尾
插入以及使用pop( )在priority_queue
開頭刪除430
24.5 總結432
24.6 問與答432
24.7 作業432
24.7.1 測驗432
24.7.2 練習432
第25章 使用STL位標志433
25.1 bitset類433
25.2 使用std::bitset及其成員434
25.2.1 std:bitset的運算符434
25.2.2 std::bitset的成員方法435
25.3 vector437
25.3.1 實例化vector437
25.3.2 vector的成員函數和
運算符438
25.4 總結439
25.5 問與答439
25.6 作業439
25.6.1 測驗439
25.6.2 練習440
第26章 理解智能指針441
26.1 什么是智能指針441
26.1.1 常規(原始)指針存在的
問題441
26.1.2 智能指針有何幫助442
26.2 智能指針是如何實現的442
26.3 智能指針類型443
26.3.1 深復制443
26.3.2 寫時復制機制445
26.3.3 引用計數智能指針445
26.3.4 引用鏈接智能指針445
26.3.5 破壞性復制445
26.3.6 使用std::unique_ptr447
26.4 深受歡迎的智能指針庫449
26.5 總結449
26.6 問與答449
26.7 作業450
26.7.1 測試450
26.7.2 練習450
第27章 使用流進行輸入和輸出451
27.1 流的概述451
27.2 重要的C 流類和流
對象452
27.3 使用std::cout將指定格式的數據
寫入控制臺453
27.3.1 使用std::cout修改數字的顯示
格式453
27.3.2 使用std::cout對齊文本和設置
字段寬度455
27.4 使用std::cin進行輸入455
27.4.1 使用std::cin將輸入讀取到基本
類型變量中455
27.4.2 使用std::cin:get將輸入讀取到char*
緩沖區中456
27.4.3 使用std::cin將輸入讀取到
std::string中457
27.5 使用std::fstream處理文件458
27.5.1 使用open( )和close( )打開和關閉
文件459
27.5.2 使用open( )創建文本文件并使用
運算符<<寫入文本460
27.5.3 使用open( )和運算符>>讀取文本
文件460
27.5.4 讀寫二進制文件461
27.6 使用std::stringstream對字符串進行
轉換463
27.7 總結464
27.8 問與答464
27.9 作業465
27.9.1 測驗465
27.9.2 練習465
第28章 異常處理466
28.1 什么是異常466
28.2 導致異常的原因466
28.3 使用try和catch捕獲異常467
28.3.1 使用catch(…)處理所有
異常467
28.3.2 捕獲特定類型的異常468
28.3.3 使用throw引發特定類型的
異常469
28.4 異常處理的工作原理470
28.4.1 std::exception類472
28.4.2 從std::exception派生出自定義
異常類473
28.5 總結474
28.6 問與答474
28.7 作業475
28.7.1 測驗475
28.7.2 練習475
第29章 繼續前行477
29.1 當今的處理器有何不同477
29.2 如何更好地利用多個內核478
29.2.1 線程是什么478
29.2.2 為何要編寫多線程應用
程序479
29.2.3 線程如何交換數據479
29.2.4 使用互斥量和信號量同步
線程480
29.2.5 多線程技術帶來的問題480
29.3 編寫杰出的C 代碼480
29.4 C 17有望引入的新特性481
29.4.1 支持在if和switch中進行
初始化481
29.4.2 保證復制得以避免482
29.4.3 避免內存分配開銷的
std::string_view482
29.4.4 類型安全的共用體替代品
std::variant483
29.4.5 使用if constexpr有條件地編譯
代碼483
29.4.6 改進的lambda表達式484
29.4.7 在構造函數中使用類型自動推斷
功能484
29.5 更深入地學習C 484
29.5.1 在線文檔485
29.5.2 提供指南和幫助的社區485
29.6 總結485
29.7 問與答485
29.8 作業485
附錄A 二進制和十六進制486
A.1 十進制486
A.2 二進制486
A.2.1 計算機為何使用二進制487
A.2.2 位和字節487
A.2.3 1KB相當于多少字節487
A.3 十六進制487
A.4 不同進制之間的轉換488
A.4.1 通用轉換步驟488
A.4.2 從十進制轉換為二進制488
A.4.3 從十進制轉換為十六進制489
附錄B C 關鍵字490
附錄C 運算符優先級491
附錄D ASCII碼492
附錄E 答案495