Posted on 2008-04-19 23:31
silentneil 閱讀(2349)
評論(0) 編輯 收藏 引用
C語言程序設計教案
教材類型:新世紀計算機基礎教育從書
主教材:C程序設計(第二版)
編者:譚浩強 著
出版:清華大學出版社
輔教材:C 程序設計解題與上機指導(第二版)
編者:譚浩強 主編
出版:清華大學出版社
總學時:102 周數:17 周學時:4+2
目 錄
1 C語言概述
1.1 C語言出現的歷史背景
1.2 C語言的特點
1.3 簡單的C程序介紹
1.4 C程序的上機步驟
1.5 Turbo C常用命令簡介
2 程序的靈魂-算法
2.1 算法的概念
2.2 簡單算法舉例
2.3 算法的特性
2.4 怎樣表示一個算法
2.5 結構化程序設計方法
3 數據類型、運算符與表達式
3.1 C的數據類型
3.2 常量和變量
3.3 整型數據
3.4 實型數據
3.5 字符型數據
3.6 變量賦初值
3.7 各類數值型數據間的混合運算
3.8 算術運算符和逗號表達式
3.9 賦值運算符和賦值表達式
3.10 逗號運算符和逗號表達式
4 順序結構程序設計
4.1 C語句概念
4.2 賦值語句
4.3 數據輸入輸出的概念及在C語言中的實現
4.4 字符數據的輸入與輸出
4.5 格式輸入與輸出
4.6 順序結構程序設計舉例
5 選擇結構程序設計
5.1 關系運算符和關系表達式
5.2 邏輯運算符和邏輯表達式
5.3 If語句
5.4 Switch語句
5.5 程序舉例
6 循環結構程序設計
6.1 概述
6.2 goto語句以及用goto語句構成循環
6.3 while語句
6.4 do-while語句
6.5 for語句
6.6 循環的嵌套
6.7 幾種循環的比較
6.8 break語句和continue語句
6.9 程序舉例
7 數組
7.1 一維數組的定義和引用
7.2 二維數組的定義和引用
7.3 字符數組和字符串
8 函數
8.1 概述
8.2 函數定義的一般形式
8.3 函數參數和函數的值
8.4 函數的調用
8.5 函數的嵌套調用
8.6 函數的遞歸調用
8.7 數組作為函數參數
8.8 局部變量和全局變量
8.9 變量的存儲類別
8.10 內部函數和外部函數
8.11 如何運行一個多文件的程序
9 預處理命令
9.1 宏定義
9.2 文件包含處理
9.3 條件編譯
11 指針
10.1 地址和指10.2 針的概述
10.3 變量的指10.4 針和指10.5 向變量的指10.6 針變量
10.7 數組與指10.8 針
10.9 字符串與指10.10 針
10.11 指10.12 向函數的指10.13 針
10.14 返回指10.15 針值的函數
10.16 指10.17 針數組和指10.18 向指10.19 針的指10.20 針
10.21 有關指10.22 針的數據類型和指10.23 針運算小結
12 結構體與共用體
11.1 結構體概述
11.2 定義結構體類型變量的方法
11.3 結構體變量的引用
11.4 結構體變量的初始化
11.5 結構體數組
11.6 指11.7 向結構體類型數據的指11.8 針
11.9 用指11.10 針處理鏈表
11.11 共用體
11.12 枚舉類型
11.10 用typedef定義類型
13 位運算
12.1 位運算符和位運算
12.2 位運算應用舉例
12.3 位段
14 文件
13.1 C文件概述
13.2 文件類型指13.3 針
13.4 文件的打開與關閉
13.5 文件的順序讀寫
13.6 文件的定位
13.7 出錯的檢測
13.8 文件輸入輸出小結
第1章 C語言概述
1.1 C語言出現的歷史背景
C語言是國際上廣泛流行的計算機高級語言,即可用來寫系統軟件,也可用來寫應用軟件。
C語言是在B語言的基礎上發展起來的。
早期的C語言運行在UNIX操作系統上,后來運行在DOS操作系統上,現在的C語言可運行在Windos操作系統上。
C語言有許多版本,我們使用的是Turbo C 2.0。
P1,說明。
1.2 C語言的特點
C語言有許多優于其它語言的特點:
(1)語言簡潔、緊湊,使用方便、靈活。
C語言一共只有32個關鍵字,9個控制語句,書寫形式自由。
P2,表1.1。
(2)運算符豐富。
C共有34種運算符,如+、-等。
P2,說明。
(3)數據結構豐富。
C有整型、實型等多種數據結構。
P3,說明。
(4)具有結構化的控制語句。
C有if…else、while等多種結構化的控制語句。
P3,說明。
(5)語法限制不太嚴格,程序設計自由度大。
如對數組下標越界不作檢查等。
P3,說明。
(6)C語言可進行位運算。
這是C區別于其它高級語言的主要特點。
P3,說明。
(7)生成目標代碼質量高。
這也是C的優于其它高級語言之處。
P3,說明。
(8)C程序可移植性好。
即C程序可基本不做修改移到不同的計算機上運行。
P3,說明。
1.3 簡單的C程序介紹
P4,例1.1,見ex1-1.c。
程序功能:打印一個字符串,并輸出一個換行符。
P4,例1.2,見ex1-2.c。
程序功能:求兩個數之和。
P5,例1.3,見ex1-3.c。
程序功能:求兩個數的較大者。
分析這三個例子的執行過程。
說明:
4 C程序是由函數組成的。在上面的例子中的函數有:main、printf、scanf和max。其中main是主函數,printf、scanf是庫函數,max是自定義函數。一個C程序一定要有一個主函數。庫函數是放在*.h的庫函數文件中,只要直接調用就可。自定義函數要由用戶先定義后調用。
5 認識一下C函數
C函數定義的一般格式為:
函數類型 函數名(形參類型 形式參數,…)
{
數據聲明部分;
函數執行部分;
}
C函數調用的一般格式為:
函數名(實際參數,…)
(3)一個C程序總是從main主函數開始執行的,而不論main函數在程序中的位置如何。主函數可以調用子函數,子函數還可以調用子子函數。因此C程序是層次結構的。
(4)C程序一行可以寫多個語句,每個語句以“;”結束。C程序是區分大小寫字母的。C程序本身沒有輸入輸出語句,其輸入輸出是由庫函數printf和scanf來完成的。/*…*/是C的注釋語句。
1.4 C程序的上機步驟
C程序編寫好后,要經過編輯、編譯、連接與運行四個步驟,這四個步驟的作用分別是:
編輯:把C語言源程序輸入計算機并進行修改存盤,生成*.c的源程序文件。
編譯:用C編譯程序對*.c的源程序文件進行編譯,生成*.obj的二進制文件。
連接:把*.obj的二進制文件與系統標準模塊進行連接,生成*.exe的可執行文件。
運行:執行*.exe的可執行文件,輸出執行結果。
以上步驟均可在Turbo C的工作平臺上進行,啟動Turbo C,就可以進行編輯,打命令Ctrl+F9,就可以進行編譯、連接和運行,打命令Alt+F5,就可看到執行結果。
舉例說明,見ex1-1.c。
1.5 Turbo C常用命令簡介
1. 啟動和退出
啟動:在DOS下打TC,或在Windows下創建快捷命令執行。
退出:Alt+X
2. 程序的編輯
簡單編輯:Ins:插入/改寫 Backspace:刪除前一字符
Del:刪除當前字符 Ctrl+Y:刪除一行
塊操作:Ctrl+KB、Ctrl+KK:定義塊首、尾
Ctrl+KC、Ctrl+KV、Ctrl+KY:塊復制、塊移動、塊刪除
Ctrl+KH:取消塊定義
3. 程序載入與存盤
F3:載入程序 F6:切換窗口
F2:存盤 Alt+FN:新建程序
4. 編譯和運行
Ctrl+F9:編譯連接執行程序 Alt+F5:查看執行結果
Ctrl+F7:添加監視表達式 F7:進入子函數單步執行
F8:越過子函數單步執行 Ctrl+F2:取消單步執行
舉例說明,見ex1-1.c。
第2章 程序的靈魂-算法
一個程序應包括兩個方面的內容:
3 對數據的描述:即程序中的數據要指定它的類型和組織形式,也稱數據結構。
4 對操作的描述:即程序中對要做的事要指明它的操作步驟,也稱算法。
算法是程序的靈魂,也就是說,要計算機解決實際中的問題,“怎么解”是程序設計的關鍵。
2.1 算法的概念
(1)算法的定義
計算機算法:就是要計算機解決問題的操作步驟。
P13,例。
(2)算法的分類
計算機算法可分為兩類:數值算法和非數值算法。
P14,例。
2.2 簡單算法舉例
P14,例2.1。
注意:解決同一問題可有不同的算法,算法有優劣之分。
P15,例2.2。
注意:循環是算法中常用的手段。
2.3 算法的特性
算法具有如下特性:
(1)有窮性
即經過有限步就能夠完成。
P14,例2.1。P15,例2.2。
(2)確定性
即每一步都是確定的。
P14,例2.1。P15,例2.2。
(3)有零個或多個輸入
即一個算法必須輸入的數據可以是零個或多個。
P14,例2.1。P15,例2.2。
(4)有一個或多個輸出
即一個算法可以輸出一個或多個數據。
P14,例2.1。P15,例2.2。
(5)有效性
即算法中每一步驟都能有效地執行,并得到確定的結果。
P14,例2.1。P15,例2.2。
2.4 怎樣表示一個算法
算法的表示法有多種,敘述如下:
(1)用自然語言表示
即把算法用人們日常使用的語言表示出來。
P14,例2.1。P15,例2.2。
特點:常常具有不確定性,不宜采用。
(2)用流程圖表示
即把算法用一些特定的符號和圖形表示出來。
P20,例2.6,例2.7。
特點:這是一種較好的表示法,經常采用。
(3)用N-S圖表示
即把算法用一些特定的符號和圖形表示出來。
P26,例2.11,例2.12。
特點:這也是一種較好的表示法,經常采用。
(4)用偽代碼表示
即把算法用一些稱為偽代碼的文字和符號表示出來。
P29,例2.16,例2.17。
特點:這也是一種較好的表示法,經常采用。
(5)用計算機語言表示
即把算法用某種計算機語言符號表示出來。
P31,例2.20,例2.21。
特點:這當然是一種很好的表示法,可以輸入計算機執行。
2.5 結構化程序設計方法
算法有三種基本結構,它們是:
(1)順序結構:即算法的執行是按順序一步接著一步的執行。
(2)選擇結構:即算法的執行是對某些步驟可有選擇的執行。
(3)循環結構:即算法的執行是對某些步驟可有限次的重復執行。
這三種基本結構的流程圖見P23,圖2.14,圖2.15,圖2.16,圖2.17。用這三種基本結構設計程序稱為結構化程序設計。
結構化程序設計的方法指的是:
1 自頂向下
2 逐步細化
3 模塊化設計
4 結構化編碼
P32,例。
第3章 數據類型、運算符與表達式
3.1 C的數據類型
數據是程序的必要組成部分,也是程序處理的對象。C規定,在程序中使用的每一個數據必須屬于某一數據類型。
C語言中所有的數據類型見P38。
3.2 常量與變量
在程序運行過程中,值保持不變的量稱為常量,值可能發生變化的量稱為變量。
3.2.1 常量與符號常量
1. 常量
常量是日常所說的常數、字符、字符串等。
P38,例。
2. 符號常量
用#define定義的用標識符來表示的常量。
格式:#define 常量名 常量
功能:定義一個符號常量
P38,例3.1。
說明:常量名必須是一個標識符。
3.2.2 變量
1. 標識符
標識符是用來表示符號常量、變量、數組、函數、過程、類型及文件的名字的。
標識符的命名規則:
(1)以字母或下劃線開頭,由字母、數字和下劃線組成;
(2)不能與關鍵字同名,最好不要與庫函數名同名;
(3)長度無限定,但不同版本的C編譯時有自己的規定;
(4)區分大小寫。
P40,例。
2. 變量的聲明
格式:類型名 變量名,… ;
功能:聲明變量。
說明:(1)變量名必須是一個標識符,變量必須先聲明后使用;
(2)變量一旦聲明,系統就為它開辟一個相應類型的存儲空間;
(3)變量所占用的存儲空間的首地址稱為該變量的地址。
P40,例。
3. 變量的賦值
格式:變量名=表達式;
功能:把=號右邊表達式的值賦給=號左邊的變量。
P40,例。
3.3 整型數據
3.3.1 整型常量的表示方法
整型常量常用三種形式表示:
(1)十進制:直接寫;
(2)八進制:前加0;
(3)十六進制:前加0X或0x。
P41,例。
3.3.2 整型變量
1. 整型數據在內存中的存放形式
整型數據在內存中采用定點表示。
定點表示有原碼、反碼、補碼之分,一般在機內使用補碼。
原碼:最高位為符號位,小數點定在最低位之后,數值用二進制表示。
反碼:正數的反碼與原碼一樣,負數的反碼除符號位外各位取反。
補碼:正數的補碼與原碼一樣,負數的補碼是反碼加1。
例1:整數10的16位定點表示
因:(10)10=(1010)2
故:整數10的16位定點表示為
原碼:
0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0
反碼:
0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0
補碼:
0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0
例2:整數-10的16位定點表示
因:(-10)10=(-1010)2
故:整數-10的16位定點表示為
原碼:
1 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0
反碼:
1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1
補碼:
1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 0
現代計算機一般用補碼表示。
2. 整型變量的分類
(1)有三種整型變量
整型: int
短整型:short [int]
長整型:long [int]
(2)整型變量的分類
每種整型變量都可以是無符號的,無符號前加unsigned,有符號前加signed或省缺,于是可有6類整型變量。
P42,例。
(3)整型變量占用的存儲空間及取值范圍
P43,表3.1。
3. 整型變量的聲明
格式:[unsigned] int|short|long 變量名,…;
功能:聲明整型變量。
P44,例,例3.2。
4. 整型數據的溢出
int型的取值范圍為-32768~32767(-215~215-1),超出這個范圍稱為溢出,此時可能輸出難以理解的結果。
P44,例,例3.3。
3.3.3 整型常量的類型
整型常量一般按整型數據的取值范圍自動劃定,但也可強制規定它是什么類型,規則是:
無符號整型后加u或U;
長整型后加l或L。
P45,(1)~(5)
3.4 實型數據
3.4.1 實型常量的表示方法
實型常量常用二種形式表示:
(1)十進制小數形式:直接寫,要有小數點,前或后至少要有一個數;
(2)指數形式:用e或E的前后加數據表示,前面是一個小數,后面是一個整數。
P45,例。
3.4.2 實型變量
1. 實型數據在內存中的存放形式
實型數據在內存中采用浮點表示
方法:設總位數為16,高12位為尾數,低4位為階碼。尾數與階碼最高位為符號位,尾數小數點定在最高位之后,階碼小數點定在最低位之后。
例1:實數10.0的16位浮點表示
因:(10.0)10=(0.1)10×10(2)10=(0.1)2×10(10)2
故:實數10.0的16位浮點表示為
0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0
例2:實數-10.0的16位浮點表示
因:(-10.0)10=(-0.1)10×10(2)10=(-0.1)2×10(10)2
故:實數-10.0的16位浮點表示為
1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0
注意:(1)位數一般實數是32位,表示法類似;
(2)階碼與尾數的位數不同的計算機有不同的規定。
(3)數據進行轉化表示時,尾數表示為±0.a…的形式,且a不為0,故表示是唯一的。
(4)以上階碼與尾數是原碼表示,實際上應轉成補碼。
2. 實型變量的分類
(1)有三種實型變量
單精度: float
雙精度: double
長雙精度:long double
(2)占用的存儲空間及取值范圍
P46,表3.2。
(3)實型變量的聲明
格式:float | double |long double 變量名,…;
功能:聲明實型變量。
P46,例。
3. 實型數據的舍入誤差
由于單精度實型只保留7位有效數據,故實型數據超出7位時會造成舍入誤差。
P47,例3.4。
3.4.3 實型常量的類型
實型常量一般按雙精度double來處理,但也可強制規定它是什么類型,規則是:
單精度后加f或F;
雙精度后加l或L。
P47,例。
3.5 字符型數據
3.5.1 字符常量
(1)一般字符常量
是用單撇號括起來的一個字符。
P48,例。
(2)特殊字符常量
是以反斜捍“\”開頭后跟一些字母或數字組成的字符。
P48,表3.3。
P49,例3.5。
3.5.2 字符變量
只有一種類型:char
聲明格式:char變量名,…;
字符變量可以用來存放一個字符。
P49,例。
3.5.3 字符數據在內存中的存放形式
字符型數據在計算機內以ASCII碼的形式存放,每個字符占用一個字節。
方法:查ASCII碼表,最高位填0。
例:字符’a’的存儲形式
因:(a)字符=(97)10進ASCII碼=(1100001)2進ASCII碼
故:字符’a’的存儲形式為
0 1 1 0 0 0 0 1
P50,例3.6,例3.7。
注意:一般字符的ASCII碼值范圍為0~127,無符號字符的ASCII碼值范圍為0~255。
3.5.4 字符串常量
(1)字符串常量
是用雙撇號括起來的若干個字符。
P52,例。
(2)字符串常量的存儲
字符串常量的存儲是每個字符占用一個字節,尾部再加一個\0作為結束符。于是長度為n的字符串占用n+1個字節的存儲空間。
P52,例。
3.6 變量賦初值
格式:類型名 變量名=常量表達式,… ;
功能:聲明變量并賦初值。
P53,例。
3.7 各類數值型數據間的混合運算
各類數值型數據間的混合運算時會自動進行轉換。
規則:(1)char,short型轉為int型;
(2)float型轉為double型;
(3)不同類型由低向高轉換,即int →unsigned →long →double
P54,圖3.10。
P54,例。
3.8 算術運算符與算術表達式
3.8.1 C的運算符簡介
C語言的運算符有13類,P55。
學習運算符注意如下幾點:
(1)運算符的功能:如+號運算的意義。
(2)與運算量的關系:如單目、雙目,運算量的類型等。
(3)運算的優先級:如先* /后+-。
(4)結合方向:如算術運算從左到右,賦值從右到左。
(5)結果的類型:如兩個整型數相加還是整型數。
3.8.2 算術運算符和算術表達式
1. 基本的算術運算符
基本的算術運算符有:+、-、*、/、%
P55,例。
注意:(1)+、-可作單目運算符,也可作雙目運算符。
(2)/ 運算對整形是封閉的,如5/3的值是1。
2. 算術運算符的優先級和結合方向
(1)優先級:①單目+、-②*、/、%③雙目+、-
(2)結合方向:從左到右
P55,例。
3. 強制類型轉換運算符
格式:(類型標識符)表達式
功能:把表達式強制為類型標識符指定的類型。
優先級:與單目+-相同。
注意:(1)強制轉換是一種單目運算;
(2)被強制轉換變量本身并未轉換。
P56,例,例3.8。
4. 自增、自減運算符
(1)運算符:+ +、--
(2)優先級:與單目+、-相同。
(3)結合方向:從右到左
P57,例。
注意:(1)自增與自減運算符只能用于變量;
(2)前+ +、--:先增值后引用;
后+ +、--:先引用后增值。
5. 有關表達式使用中的問題說明
表達式是把常量、變量、函數用各種運算符連接起來的合法的式子。C中的表達式簡練、高效,但有時會出現岐義性,使得程序理解有一定的困難,不同版本的C對表達式的解釋也有所不同。
P58,(1)~(3)
3.9 賦值運算符和賦值表達式
1. 賦值運算符
(1)運算符:=
(2)優先級:僅高于逗號“,”運算,低于其它運算。
(3)結合方向:從右到左
P59,例。
2. 類型轉換
當賦值運算兩邊的類型不一致,且都是數值類型或字符型時,會自動發生類型轉換,轉換以左邊變量的類型為準。
轉換規則:
(1)實型賦給整型:舍去小數。
(2)整型賦給實型:值不變。
(3)雙精度賦給單精度:取其前7位有效數字,反之值不變。P59,例。
(4)字符型賦給整型:低8位照搬,高8位視符號位補0或1。P60,例。
(5)整型賦給字符型:低8位照搬,高8位丟失。P60,例。
(6)整型賦給長整型:值不變,反之低16位照搬。P60,例。
(7)無符號型賦給有符號型:長度相同時最高位變為符號位,長度不同時高位補0或截去高位。P61,例。
(8)有符號型賦給無符號型:長度相同時最高位失去符號位,長度不同時高位補0或截去高位。P61,例。
P61,例3.9。
3. 復合的賦值運算
(1)運算符:+=、-=、*=、/=、%= 等
(2)優先級:與賦值運算“=”相同;
(3)結合方向:從右到左。
P62,例。
4. 賦值表達式
由賦值語句購成的表達式稱為賦值表達式,這種表達式還可以嵌套,從右到左逐一進行賦值運算,表達式的值是最后一次賦值的值。
P63,例。
注意:(1)結合方向是從右到左的;
(2)復合的賦值運算也可購成賦值表達式;
(3)賦值表達式可出現在輸出的語句中。
3.10 逗號運算符和逗號表達式
1. 逗號運算符
(1)運算符: ,
(2)優先級:最低;
(3)結合方向:從左到右。
P63,例。
2. 逗號表達式
格式:表達式1,表達式2,… ,表達式n
求解過程:從左到右逐一求表達式的值,整個表達式的值為最后一個表達式的值。
P64,例。
第4章 順序結構程序設計
4.1 C語句概述
1. C的程序結構
一個C程序由若干個源程序文件組成;一個源程序由預處理命令、全局變量說明和若干個函數組成;一個函數由函數首部和函數體組成;一個函數體由局部變量聲明和執行語句組成。
P67,圖4.1。
2. C程序的語句
C程序的語句的語句分為5類:
(1)控制語句
用來控制程序流程的語句。
P68,①~⑨
P68,例。
注意:( )表示其中是一個條件,~表示內嵌語句。
(2)函數調用語句
由一次函數調用加一個分號購成的語句。
P68,例。
注意:函數有庫函數與自定義函數兩種,自定義函數要先定義后調用。
(3)表達式語句
由一個表達式加一個分號購成的語句。
P68,例。
注意:表達式語句與表達式的區別在于有無分號。
(4)空語句
只由一個分號購成的語句。
P68,例。
注意:空語句不做任何事情。
(5)復合語句
把多個語句用{ }括起來的語句。
P69,例。
注意:復合語句構成一個分程序,內可包含數據聲明和執行語句兩部分。
4.2 賦值語句
賦值語句是表達式語句的一種最常用的形式,與其它高級語言相比,C的賦值語句有其獨特之處:
(1)在C中“=”是一個運算符;
(2)在C中賦值語句可以包括在其它表達式中。
P69,例。
4.3 數據輸入輸出的概念及在C語言中的實現
(1)把數據從外部設備送到計算機內存稱為輸入,把數據從計算機內存送到外部設備稱為輸出。外部設備有鍵盤、顯示器、磁盤等。
(2)C本身沒有輸入輸出的語句,C的輸入輸出是由一批庫函數來實現的。這些庫函數有:scanf、printf、getchar、putchar、gets、puts等,它們放在名為stdio.h的庫函數文件中。
(3)一般要使用這些庫函數時,要在程序頭加上
#include <stdio.h> 或 #include “stdio.h”
的預編譯命令,其作用是把這些庫函數包含到本程序中來。
P71,例。
4.4 字符數據的輸入與輸出
4.4.1 字符輸出函數putchar
格式:putchar(字符變量);
功能:把字符變量中的字符輸出到顯示器。
注意:putchar函數一般作為一個語句來使用。
P71,例4.1。見ex4-1.c。
4.4.2 字符輸入函數getchar
格式:getchar( )
功能:從鍵盤輸入一個字符并通過函數名返回這個字符。
注意:getchar函數一般在在表達式中使用。
P72,例4.2。
4.5 格式輸入與輸出
4.5.1 格式輸出函數printf
1. 一般格式
格式:printf(格式控制,輸出表列);
功能:按照“格式控制”中的格式要求輸出“輸出表列”的值。
P72,例。
(1)“格式控制”是一個用雙撇號括起來的字符串,它包括兩種信息:
①格式說明:由%和格式字符組成,不同的格式字符指明了不同的輸出方式。
②普通字符:即要原樣輸出的字符。
P72,例。
(2)“輸出表列”是要輸出的一些數據,可以是表達式。
P73,例。
2. 格式字符
(1)d格式符:用來輸出十進制整數。
可有四種用法:%d,%md,%ld,%-d。
其中:m表示輸出寬度,l表示輸出長整數,-表示輸出左對齊。
P73,例。
(2)o格式符:用來輸出八進制整數。
同樣可以附加m,l,- 等。
注意:符號位當成數據輸出,不會輸出負數。
P74,例。
(3)x格式符:用來輸出十六進制整數。
同樣可以附加m,l,- 等。
注意:符號位當成數據輸出,不會輸出負數。
P74,例。
(4)u格式符:用來輸出無符號數據。
同樣可以附加m,l,- 等。
P74,例4.3。
(5)c格式符:用來輸出一個字符。
可以附加m,- 等。
P74,例4.4。
(6)s格式符:用來輸出一個字符串。
除了可以附加m,- 外,還可以寫成 %m.ns。
其中:m.n表示寬度為m,只輸出字符串左邊n個字符。
P75,例4.5。
(7)f格式符:用來小數形式輸出一個實數。
除了可以附加m,- 外,還可以寫成 %m.nf。
其中:m.n表示寬度為m,保留n位小數。
P76,例4.6,例4.7,例4.8。
(8)e格式符:用來指數形式輸出一個實數。
除了可以附加m,- 外,還可以寫成 %m.nf。
其中:m.n表示寬度為m,小(尾)數部分保留n位小數。
P77,例。
(9)g格式符:用來輸出一個實數,形式自動取小數和指數中的較短者。
P77,例。
P77,表4.1。
4.5.2 格式輸入函數scanf
1. 一般格式
格式:scanf(格式控制,地址表列);
功能:按照“格式控制”中的格式要求輸入數據到“地址表列”的相應變量中。
(1)“格式控制”是一個用雙撇號括起來的字符串,它包括兩種信息:
①格式說明:由%和格式字符組成,不同的格式字符指明了不同的輸入方式。
②普通字符:即要原樣輸入的字符。
P72,例。
(2)“地址表列”是要輸入的變量的地址,一般用地址運算符&求得。
P79,例4.9。
2. 格式字符
scanf函數的格式字符與printf函數類似,但有微小區別。
P80,表4.3,表4.4。
說明:P80,(1)~(4)。
3. 使用scanf函數應請注意的問題
(1)“格式控制”后面是變量的地址,而不是變量。
P81,例。
(2)如果在“格式控制”中有格式說明符外的其它字符,要原樣輸入。
P81,例。
(3)用%c輸入字符時,空格、回車符等都作為有效字符輸入。
P82,例。
(4)在輸入數據時,遇到空格、回車、跳格、限寬、非法等會結束輸入。
P82,例。
4.6 順序結構程序設計舉例
P82,例4.10。見ex4-10.c。
P83,例4.11。見ex4-11.c。
P84,例4.12。見ex4-12.c。
第5章 選擇結構程序設計
5.1 關系運算符和關系表達式
5.1.1 關系運算符及其優先次序
(1)運算符:>、>=、<、<=、= =、!=
(2)優先級:①>、>=、<、<= ②= =、!=
低于算術運算,高于賦值運算
(3)結合方向:從左到右
P88,例。
5.1.2 關系表達式
用關系運算符把兩個表達式連接起來的式子稱為關系表達式。
關系表達式的值為真(1)或假(0)。
P88,例。
5.2 邏輯運算符和邏輯表達式
5.2.1 邏輯運算符及其優先次序
(1)運算符:&&、||、!
(2)優先級:①! ②&& ③||
!與單目+、-同級,&&、||低于關系運算
(3)結合方向:! 從右到左,&&、|| 從左到右
P89,例。
5.2.2 邏輯表達式
用邏輯運算符把兩個表達式連接起來的式子稱為邏輯表達式。
邏輯表達式的值為真(1)或假(0),判斷時非0是真、0是假。
P89,例。
注意:(1)a&&b&&c的判斷,a為0則表達式為0,a為1、b為0則表達式為0,a為1、b為1、c為0則表達式為0,否則表達式為1。
(2)a||b||c的判斷,a為1則表達式為1,a為0、b為1則表達式為1,a為0、b為0、c為1則表達式為1,否則表達式為0。
P91,例。
5.3 If語句
5.3.1 if語句的三種形式
1. 單分支if語句
格式1:if (表達式) 語句
功能1:如果表達式為真,則執行語句。
P91,例。
2. 雙分支if語句
格式2:if (表達式) 語句1
else 語句2
功能2:如果表達式為真,則執行語句1,否則執行語句2。
P92,例。
3. 多分支if語句
格式3:if (表達式1) 語句1
else if (表達式2) 語句2
… …
else if (表達式n) 語句n
else 語句n+1
功能3:如果直到表達式i為真,則執行語句i,否則表達式全為假,則執行語句n+1。
P92,例。
注意:(1)每個語句都是以分號結束的;
(2)if或else后只能一個語句,如有多個語句要用{ }括起來。
P93,例5.1,例5.2。
5.3.2 if語句的嵌套
if語句可以嵌套,原則是else與它最近的if配對,如果在內層嵌套中要使用單分支if語句,要用{ }把它括起來。
P94,例,例5.3。
5.3.3 條件運算符
1 運算符:? :
2 優先級:低于邏輯運算,高于賦值運算
3 結合方向:從右向左
(4) 條件表達式:
格式:表達式1? 表達式2: 表達式3
功能:若表達式1為真,則條件表達式取表達式2,否則取表達式3。
P96,例。
注意:表達式2與表達式3二者的類型取高的。P37。
P98,例,例5.4。
5.4 Switch語句
格式:switch (表達式)
{case 常量表達式1:語句1
case 常量表達式2:語句2
… …
case 常量表達式n:語句n
[default:語句n+1]
}
功能:如果表達式的值等于常量表達式i,則執行語句i及其后面的語句,否則如果都不等,則執行語句n+1。
P99,例。
注意:(1)表達式可以是任何類型的;
(2)常量表達式的值不能相同;
(3)各case和default出現次序無關;
(4)可用break中斷執行后續語句;
(5)多個case可共用一組執行語句。
P99,例。
5.5 程序舉例
P100,例5.5。見ex5-5-1.c,ex5-5-2.c。
P101,例5.6。
P103,例5.7。見ex5-7。
第6章 循環結構程序設計
6.1 概述
在C語言中,構成循環的語句有4種:
1 用goto和if語句;
2 用while語句;
3 用do-while語句;
4 用for語句。
6.2 goto語句以及用goto語句構成循環
格式:goto 語句標號;
功能:無條件轉到語句標號指定的語句中去執行。
注意:(1)語句標號應是合法的標識符,可放在任何語句的前面。
(2)用goto語句構成循環不是一種很好的方法。
P106,例,例6.1。
6.3 while語句
格式:while (表達式)
循環體;
功能:當表達式為真時執行循環體的語句,直到表達式為假時退出循環。
P107,例6.2。
注意:(1)循環體只能一個語句,如有多個語句要用{ }括起來。
(2)循環體內應有使循環趨于結束的語句,否則構成死循環。
(3)循環體可能一次也沒執行到,當條件表達式為真時進入循環體,故也稱當型循環。
6.4 do-while語句
格式:do
循環體;
while (表達式);
功能:先執行一次循環體,然后當表達式為真時再執行循環體,直到表達式為假時退出循環。
P108,例6.3,例6.4。
注意:(1)循環體只能一個語句,如有多個語句要用{ }括起來。
(2)循環體內應有使循環趨于結束的語句,否則構成死循環。
(3)循環體至少執行一次,直到條件表達式為假時退出循環,故也稱直到型循環。
6.5 for語句
格式:for (初值表達式;條件表達式;修正表達式)
循環體;
功能:先執行一次初值表達式,再執行條件表達式,若為真則執行循環體,然后執行修正表達式,再次執行條件表達式進行判斷,直到條件表達式為假時退出循環。
P110,例。
注意:(1)循環體只能一個語句,如有多個語句要用{ }括起來。
(2)可以明顯看出循環體執行的次數,故也稱計數循環。
(3)三個表達式在一定的條件下都可省。
P111,說明(1)~(7)。
6.6 循環的嵌套
四種循環可以互相嵌套,此時外層循環的每一取值,內層循環要轉一圈。但是循環嵌套不得交叉進行。
P113,說明(1)~(6)。
6.7 幾種循環的比較
4 四種循環可以用來處理同一問題,但一般不用goto循環。
5 while和do-while循環在循環體內應有使循環趨于結束的語句,for可用修正表達式來實現。
6 while和do-while循環在循環前應有初始化的操作,for可用初值表達式來實現。
7 while和do-while及for循環可用break語句跳出循環和用continue語句結束本次循環,而goto循環不可以用。
6.8 break語句和continue語句
6.8.1 break語句
格式:break;
功能:退出switch選擇或while、do-while、for循環結構。
P114,例。
6.8.2 contiune語句
格式:contiune;
功能:本次while、do-while、for循環提前結束,進入下次循環。
P115,例。
P115,例6.5。
6.9 程序舉例
P116,例6.6。見ex6-6。
P116,例6.7。見ex6-7。
P118,例6.8。
P118,例6.9。見ex6-9。
P119,例6.10。見ex6-10。
第7章 數組
數組是由相同類型的一組數據構成的。前面我們所學的類型都是基本類型,而本章所學的數組是一種構造類型。
7.1 一維數組的定義和引用
7.1.1 一維數組的定義
格式:類型標識符 數組名[常量表達式],…;
其中:數組名是標識符,常量表達式是元素個數。
功能:定義一維數組,其數組名由其“數組名”指定,元素個數由“常量表達式”指定,元素類型由“類型標識符”指定。
P122,例。
注意:(1)C語言中數組的下標從0開始;
(2)常量表達式中可以有符號常量,但不能含有變量;
(3)數組一旦定義,系統為它分配一個連續的存儲空間。
7.1.2 一維數組元素的引用
格式:數組名[下標表達式]
功能:引用已定義的數組元素
P123,例,例7.1。
注意:(1)下標可以是表達式。
(2)下標的取值為0~常量表達式-1,超出范圍可能有不可預料的后果。
7.1.3 一維數組的初始化
在定義一維數組時,可對數組進行初始化。
方法:在定義數組時在數組名后加上={初始值,初始值,…,初始值}
P123,例。
注意:(1)可對部分元素初始化。
(2)數組有進行初始化時常量表達式可省。
7.1.4 一維數組程序舉例
P124,例7.2。
P124,例7.3。見ex7-3.c。
7.2 二維數組的定義和引用
7.2.1 二維數組的定義
格式:類型標識符 數組名[常量表達式][ 常量表達式],…;
功能:定義二維數組,其數組名由其“數組名”指定,每維下標的取值范圍由該維的“常量表達式”指定,元素類型由“類型標識符”指定。
P125,例。
注意:(1)多維數組的定義與二維數組類似;
(2)二維數組常用來描述數學中的矩陣;
(3)對于一個m×n的二維數組,二維數組與一維數組元素的對應:
二維中第i,j個元素←→一維中第i×n+j個元素
P126,例。
7.2.2 二維數組的引用
格式:數組名[下標表達式] [下標表達式]
功能:引用已定義的二維數組元素
P126,例。
注意:設a是一個m×n二維數組;則
(1)a[i] (對任意固定的i=0,1,…,m-1)是一個長度為n的一維數組,它的數組名就是a[i],每個元素是a[i][j];
(2)a可認為是一個長度為m一維數組,它的數組名就是a,每個元素是a[i];
(3)由上可知,二維數組可認為是一個元素是一維數組的一維數組。
7.2.3 二維數組的初始化
在定義二維數組時,也可對數組進行初始化。
方法:在定義數組時在數組名后加上={{初始值,…},{初始值,…},…,{初始值,…}}或者加上={初始值,初始值,…,初始值}
P127,例。
注意:(1)可對部分元素初始化;
(2)二維以上數組有進行初始化時第一維的常量表達式可省。
P128,例。
7.2.4 二維數組應用舉例
P128,例7.4。
P129,例7.5。見ex7-5.c。
7.3 字符數組和字符串
7.3.1 字符數組
字符數組:元素類型為字符型的數組稱為字符數組。
格式:char 數組名[常量表達式],…;
P130,例。
注意:長度為n的字符數組可用來存放n個字符。
7.3.2 字符數組的初始化
與普通數組一樣,可對字符數組進行初始化。
方法:在定義數組時在數組名后加上={字符,字符,…,字符}
P130,例。
注意:初始化時元素個數可不寫。
7.3.3 字符數組的引用
字符數組的每個元素存放的是一個字符。
格式:數組名[下標表達式]
P131,例7.6,例7.7。
7.3.4 字符串和字符串結束標志
(1)字符串
由若干個字符兩邊用雙撇號括起來的稱字符串。
字符串存放時應在尾部加一個\0作為結束標志。
長度為n的字符存儲時占用n+1個字節的存儲空間。
P131,例。
(2)用字符數組存放字符串
長度為n的字符數組可用來存放一個長度為n-1的字符串。
字符數組可用字符串進行整體初始化,且此時會自動在尾部加一個\0。
P132,例。
7.3.5 字符數組的輸入與輸出
字符數組輸入輸出的方法有兩種:
(1)逐個元素用scanf和printf函數輸入輸出
格式:scanf(“%c”,&數組元素);
printf (“%c”,數組元素);
功能:前者從鍵盤上取得一個字符送給相應的數組元素;
后者把數組元素中的字符輸出到顯示器上。
P131,例7.6。
(2)整個字符數組用scanf和printf函數輸入輸出
格式:scanf(“%s”,數組名);
printf (“%s”,數組名);
功能:前者從鍵盤上取得一個字符串送給相應的數組;
后者把數組中的整個字符串輸出到顯示器上。
P133,例。
注意:(1)整個字符數組中的字符串輸出時,\0本身不輸出, 且輸出不換行;
(2)整個字符數組中的字符串輸出時,是從首地址逐一輸出的,直到遇到第一個\0為止;
(3)C語言中數組名表示該數組的首地址,故整個字符數組輸入時不能在數組名前加&;
(4)整個字符數組輸入時遇空格而停止,且會自動在尾部加一個\0。
P133,例。
7.3.6 字符串處理函數
1. 字符串輸出函數puts
格式:puts(字符數組名);
功能:輸出字符數組中的字符串。
P135,例。
2. 字符串輸入函數gets
格式:gets(字符數組名);
功能:從鍵盤輸入一個字符串到字符數組中。
P135,例。
注意:(1)gets與puts一次只能輸入輸出一個字符串;
(2)gets輸入時不會遇空格而停止,而是遇換行符而停止,也會在尾部自動加上一個\0;
(3)puts輸出時也是到\0為止,還會把\0轉成換行符輸出。
3. 字符串連接函數strcat
格式:strcat(字符串1, 字符串2);
功能:把字符串2的內容連接到字符串1之后,函數返回字符串1。
注意:連接時把第二個字符串的第一個字符覆蓋到第一個字符串的\0上
P136,例。
4. 字符串拷貝函數strcpy
格式:strcpy(字符串1,字符串2);
功能:把字符串2的內容拷貝到字符串1中,函數返回字符串1。
注意:(1)拷貝時也是到第一個\0為止,連同\0一起拷貝;
(2)對字符串不可有賦值語句:字符串1=字符串2;
P136,例。
5. 字符串比較函數strcmp
格式:strcmp(字符串1,字符串2);
功能:比較字符串1與的字符串2內容:如果字符串1= =字符串2,則返回0;如果字符串1>字符串2,則返回正整數;如果字符串1<字符串2,則返回負整數。
注意:比較時是以字符的ASCII值進行的。
P137,例。
6. 測字符串長度函數strlen
格式:strlen(字符串)
功能:返回字符串的實際字符數。
注意:(1)測字符串長度包括空格,但不包括\0;
(2)遇到\開頭的特殊字符也當一個字符對待。
P138,例。
7. 字符換小寫函數strlwr
格式:strlwr(字符串)
功能:把字符串中的大寫字母換成小寫字母。
8. 字符換大寫函數strupr
格式:strupr(字符串)
功能:把字符串中的小寫字母換成大寫字母。
7.3.7 字符數組應用舉例
P138,例7.8。見ex7-8.c。
P140,例7.9。見ex7-9.c。
第8章 函數
8.1 概述
一個C程序是由函數組成的,所以函數是C語言中最重要的概念,本章專門討論函數的定義、函數的調用及參數傳遞等問題。
P143,例8.1。
說明:
(1)一個源程序文件是由一個或多個C函數組成的,一個源程序文件是一個編譯單位。
(2)一個C程序由一個或多個源程序文件組成,一個源程序文件可以為多個C程序共用。
(3)一個C程序中一定要有一個名為main的主函數,執行時總是從主函數開始,其它函數只有被調用時才會執行,執行完畢返回到調用處繼續執行,正常情況下總是在主函數結束執行。
(4)所有的函數是平行的,即在定義時是互相獨立的,主函數可以調用其它函數,其它函數之間可以互相調用,但其它函數不能調用主函數。
(5)從用戶使用的角度看,函數可分為標準函數(庫函數)和用戶自定義函數。
(6)從函數的形式看,函數可分為無參函數和有參函數。
8.2 函數定義的一般形式
1. 無參函數的定義形式
格式:函數類型 函數名()
{
數據聲明部分;
執行語句部分;
}
說明:(1)函數名:函數名是函數調用的依據,函數值的返回也是通過函數名實現的,函數名要符合標識符的定義。
(2)函數體:由數據聲明和執行語句兩部分組成,數據聲明是對數據特征的描述,執行語句是對數據處理的描述,函數的功能由它們實現。
(3)函數類型:函數類型規定了函數返回值的類型,int或char可不寫,如不要返回值可定義為void型。
P144,例。
2. 有參函數的定義形式
格式:函數類型 函數名(形式參數表列)
{
數據聲明部分;
執行語句部分;
}
說明:(1)形式參數表列:由格式為“形參類型 形參名”組成的表列,規定了形參的類型及數目。
(2)形參是用來接收或傳遞函數調用時實參的數據的。
P145,例。
3. 空函數的定義形式
格式:函數類型 函數名()
{ }
說明:(1)空函數什么事情也不做,沒有什么實際作用。
(2)編寫程序時如果某處要寫一個函數,可以先寫一個空函數放在那里,等后面再來補寫完整,這樣做對編程是有益的。
4. 對函數聲明的傳統方式
格式:函數類型 函數名(形式參數名表列)
形式參數名表列類型說明;
{
數據聲明部分;
執行語句部分;
}
P146,例。這種方法現一般不用,只了解一下就可。
8.3 函數參數和函數的值
8.3.1 形式參數和實際參數
函數定義時的參數稱為形式參數,函數調用時的參數稱為實際參數。形式參數和實際參數負責函數調用時的數據傳遞。
P146,例8.2。
說明:(1)函數定義中的形式參數,在函數未調用時并不占用存儲空間,只有當函數調用時才分配存儲空間,函數調用完畢這些存儲空間被釋放。
(2)實際參數可以是常量、變量或表達式,但它們一般必須有確定的值,函數調用時它們的值被傳給形式參數。
(3)實參和形參的類型要相同或賦值兼容。對變量參數而言,實參對形參的數據傳遞是“值傳遞”,即數據有傳入沒傳出。
P146,例8.2。
8.3.2 函數的返回值
函數調用后一般通過函數名返回一個值,但有的函數可能不需要返回值。
P146,例8.2。
說明:(1)函數的返回值是由return語句獲得的;一個函數如果不需要返回值,可以不用return語句;一個函數也可以有多個return語句,執行到哪一個就那個return語句起作用。
P148,例。
(2)函數的類型指函數返回值的類型,由定義函數時的函數類型來確定。定義函數時return語句后表達式的類型要與函數的類型相一致。
(3)如果定義函數時return語句后表達式的類型與函數的類型不相一致,則以函數的類型為準進行強制類型轉換。
P148,例8.3。
(4)如果函數沒有return語句,則函數調用后將返回一個不確定的值。為了明確表示不需返回值可把函數定義為void類型。
P149,例。
8.4 函數的調用
8.4.1 函數的一般調用方法
格式:函數名(實際參數表列)
功能:調用函數名指定的函數。
說明:(1)如果函數定義時沒有形參,則不要實參,但()不能省。
(2)實參要與形參在數目、類型、次序上一一對應。
(3)Turbo C中實參傳遞是從右到左進行的。
P150,例8.4。
8.4.2 函數調用的方式
按函數在程序中出現的位置來分,函數有三種調用方式:
1. 函數語句
就是把函數調用作為一個語句,此時函數的返回值無法使用。
P151,例。
2. 函數表達式
就是把函數調用放在一個表達式中,此時函數的返回值參加表達式的運算。
P151,例。
3. 函數參數
就是把函數調用作為另一個函數調用的實參,此時函數的返回值將傳給另一個函數的形參。
P151,例。
8.4.3 函數的聲明
1. 函數調用的條件
(1)被調用的函數必須是已存在的函數,即要么是庫函數要么是已定義好的函數。
(2)如果是庫函數,一般要在本文件頭用#include命令把有關庫函數文件(*.h)包含到本文件中來。
P152,例。
(3)如果是用戶自定義函數,函數定義必須在函數調用之前,否則要在函數調用之前進行函數聲明。
P152,例8.5。
2. 函數聲明的方法
格式:函數類型 函數名(形參類型 形參,…);
功能:聲明一個函數,以便在程序中調用。
P152,例8.5。
說明:(1)函數聲明就是把函數頭重抄一遍(故函數聲明也叫函數原型),形參可省或形參及形參類型都省。
P153,例。
(2)函數類型為int的函數調用之前還未定義也可不要聲明,但最好還是聲明一下。
P146,例8.2。
(3)如果函數定義出現在函數調用之前,則不需要作函數聲明。
P154,例。
(4)如果函數聲明在所有的函數之前,則不必每個函數中再作聲明,每個函數都可以調用這個函數。
P154,例。
8.5 函數的嵌套調用
在C語言中,函數不能嵌套定義,但可以嵌套調用。即主函數可以調用子函數,子函數可以調用子子函數。
P155,圖8.5。
P155,例8.6。
說明:P157,(1)~(4)
8.6 函數的遞歸調用
在C語言中,函數可以調用它本身,函數自己調用自己稱為函數的遞歸調用。遞歸調用有兩種情況:直接遞歸和間接遞歸。
P158,圖8.9,圖8.10。
P158,例8.7。
注意:編寫遞歸程序的關鍵是寫出問題的遞歸描述。
P160,例8.8。
8.7 數組作為函數參數
1. 數組元素作為函數的參數
數組元素作為函數的參數,其用法與普通變量相同,數組元素可以是一維的也可以是多維的。
P164,例8.10。
說明:數組元素其實與普通變量的性質一樣,故數組元素作為函數的參數,其傳遞是“值傳遞”。即變量的數據有傳入沒傳出。
2. 一維數組名作為函數的參數
一維數組名也可作為函數的參數,這時實參和形參都是一維數組。
P165,例8.11。
說明:(1)實參數組與形參數組應分別在它們所在函數中定義,但數組名可以不一樣。
(2)實參數組與形參數組的類型要一致,否則出錯。
(3)形參數組定義中的元素個數不起作用,程序編譯時并不對形參數組的元素個數進行檢查。
(4)形參數組定義中的元素個數可空,并可另設一個變量形參用來傳遞數組元素個數。
P166,例8.12。
(5)數組名作為函數的參數,是把實參數組的首地址傳給形參數組,即讓兩個數組共享同一存儲空間,其傳遞是“地址傳遞”,即對數組而言,其數據有傳入也有傳出。
P166,例8.13。
3. 多維數組名作為函數的參數
二維數組名也可作為函數的參數,這時實參和形參可以都是二維數組,也可以實參是二維數組而形參是一維數組。
P168,例8.14。
說明:(1)如果二維數組作為形參,其第一維的元素個數可空。
(2)如果二維數組作為實參而一維數組作為形參,則數據按二維數組與一維數組元素的對應關系進行傳遞。
8.8 局部變量和全局變量
8.8.1 局部變量
在一個函數的內部定義的變量稱為局部變量,它從定義時刻開始到本函數結束范圍內有效。
P169,例。
說明:(1)主函數內定義的變量也只在主函數內有效。
(2)不同函數可以使用同名的變量,它們互相沒有關系。
(3)形式參數也是局部變量。
(4)在一個函數內部中的復合語句可以定義自己的變量,它只在本復合語句內有效。
P169,例。
8.8.1 全局變量
在一個函數的外部定義的變量稱為全局(外部)變量,它從定義時刻開始到本文件結束范圍內有效。
P170,例。
說明:(1)設全局變量的作用是增加了函數間數據聯系的渠道,最好全局變量第一個字母大寫。
P170,例8.15。
(2)建議在不必要時不要作用全局變量,因為:①可節省存儲空間,②可使程序通用性強,③可使程序可讀性強。
(3)如果全局變量與局部變量不同名,則全局變量與局部變量在本函數內均有效,如果全局變量與局部變量同名,則當進入本函數時,全局變量會隱藏起來,局部變量起作用,一旦退出本函數,全局變量恢復原值。
P172,例8.16。
8.9 變量的存儲類別
8.9.1 動態存儲方式和靜態存儲方式
靜態存儲方式:程序運行期間分配固定的存儲空間;
動態存儲方式:程序運行期間分配動態的存儲空間。
程序運行期間用戶使用的存儲區域稱為用戶區,C語言中用戶區由三部分組成:
①程序區:用于存放用戶程序;
②靜態存儲區:用于存放需要固定存儲空間的數據;
③動態存儲區:用于存放隨時可能建立或撤消的數據。
P173,例。
8.9.2 自動(auto)變量
定義:在函數內部定義的前加auto或省缺的變量。
特征:放在動態存區,定義變量時建立,退出本函數時撤消。
P173,例。
說明:(1)自動變量是局部變量
(2)自動變量在賦值前其值是不確定的。
(3)在函數多次被調用的過程中,自動變量的值是不保留的。
8.9.3 局部靜態(static)變量
定義:在函數內部定義的前加static的變量。
特征:放在靜態存區,程序編譯時創建,結束執行時撤消。
P173,例8.17。
說明:(1)靜態變量的存儲空間在整個程序運行期間是固定的。
(2)靜態變量的初始化是在程序編譯時進行的,未顯式初始化時自動賦0或空串。
(3)在函數多次被調用的過程中,靜態變量的值具有繼承性。
(4)局部靜態變量只能在本函數中使用。
P175,例8.18。
8.9.4 寄存器(register)變量
定義:在函數內部定義的前加register的變量。
特征:放在寄存器,定義變量時建立,退出本函數時撤消。
P175,例8.19。
說明:(1)只有局部自動變量和形式參數可以作為寄存器變量。
(2)寄存器變量與自動變量性質一樣,但速度快、數量有限。
(3)局部靜態變量不能定義為寄存器變量。
P176,例。
8.9.5 外部變量及其擴展(extern)
定義:定義在所有函數之外的變量稱為外部變量。
特征:(1)放在靜態存區,程序編譯時創建,結束執行時撤消。
(2)外部變量可以用extern來擴展它的作用域。
1. 作用域擴充到本文件內
方法:在本文件要用的地方之前使用extern重聲明。
P176,例8.20。
2. 作用域擴充到其它文件
方法:在其它文件要用的地方之前使用extern重聲明。
P176,例8.21。
注意:含有多個文件的C程序的執行見P183,8.11如何運行一個多文件的程序。
8.9.6 外部靜態(static)變量
定義:在函數外部定義的前加static的變量。
特征:放在靜態存區,程序編譯時創建,結束執行時撤消。
P178,例。
說明:(1)外部靜態變量具有靜態變量的所有性質;
(2)外部靜態變量只能在本文件中使用,而不能被其它文件引用。
8.9.7 關于變量的聲明和定義
在C語言中,定義和聲明兩個詞是混淆的,實際上,我們可把聲明分為定義性聲明和引用性聲明。
定義性聲明(簡稱定義):是要分配存儲空間的。如int a;
引用性聲明(簡稱聲明):是不要分配存儲空間的。如extern a;
P179,例。
說明:一個變量定義只能一次,聲明可以多次。
8.9.8 存儲類別小結
可從不同的角度來分類歸納:
(1)作用域:可分為全局的和局部的。
(2)存放時間:可分為動態存儲和靜態存儲。
(3)存放位置:可分為動態存區、靜態存區和寄存器。
P180,小結。
說明:(1)作用域、存放時間、存放位置是不同的概念,它們有區別也有聯系。
(2)static對局部變量和全局變量的作用不同。
P181,例。
8.10 內部函數和外部函數
8.10.1 內部函數
定義:在函數定義前加static的函數,稱為內部函數或靜態函數。
說明:內部函數只能在本文件中被調用,而不能被其它文件調用。
P182,例。
8.10.1 外部函數
定義:在函數定義前加extern或省缺的函數,稱為外部函數。
說明:外部函數可以在其它文件中被調用,使用前要用extern重聲明。
P177,例8.21。見ex8-21。
P182,例8.22。
8.11 如何運行一個多文件的程序
C程序可以由多個文件組成,由多個文件組成的C程序可有兩種編譯運行方法:
1. 用Turbo C的集成環境
多個文件組成的C程序執行的步驟為:
4 先把多個文件的內容編輯并存盤為file1.c,file2.c,…,filen.c
5 在編輯狀態下建立一個項目文件,內容為:file1.c file2.c …filen.c,并存盤為:file.prj
6 把Project菜單的子菜單project neme的值修改為:file.prj
7 打編譯執行的命令Ctrl+F9,并用Alt+F5查看結果。
P177,例8.21。見ex8-21-1.c,ex8-21-2.c,ex8-21.prj。
P184,例8.22。
注意:項目文件的內容中文件之間用空格隔開,擴展名.c可省,也可以寫成一列。
2. 用#include命令
多個文件組成的C程序執行的步驟為:
4 先把多個文件的內容編輯并存盤為file1.c,file2.c,…,filen.c
5 設file1.c中含有main函數,則在file1.c的開頭加入如下#include命令:#include “file2.c”
… … …
#include “filen.c”
8 打編譯執行的命令Ctrl+F9,并用Alt+F5查看結果。
P185,例8.22。
注意:此時實際上編譯程序不再認為是多個文件,而是用#include命令把其它文件包含到本文件中來一起進行編譯。
第9章 預處理命令
C程序中可以加入一些預處理命令,其目的是改進程序設計環境,提高編程效率。這類命令主要包括:宏定義、文件包含和條件編譯三種,為了區別一般的C語句,這類命令都以#開頭。
9.1 宏定義
9.1.1 不帶參數的宏定義
格式:#define 宏名 宏體
其中:宏名是一個標識符,宏體是一個表達式字符串。
功能:程序編譯時,用宏體代替宏名。
P187,例,例9.1。
說明:P188,(1)~(9)
P188,例,例9.2。
9.1.2 帶參數的宏定義
格式:#define 宏名(形參表) 宏體
其中:宏名是一個標識符,宏體是一個帶有形參的表達式字符串。
功能:程序編譯時,用實參代替形參,再用宏體代替宏名(形參表)。
P190,例,例9.3。
說明:P190,(1)~(2)
9.1.3 帶參數的宏與函數的區別
P191,(1)~(6)
P191,例9.4,例9.5。
9.2 文件包含處理
格式1:#include “文件名”
格式2:#include <文件名>
其中:文件名一般是 *.h 的函數庫文件,也可以是 *.c 的源程序文件,且可帶盤符路徑。
功能:把文件名指定的文件內容包含到當前文件中來。
注意:使用格式1時,編譯程序先在當前目錄上找指定文件,如沒找到就到系統規定的目錄上找找指定文件。使用格式2時,編譯程序只在系統規定的目錄上找找指定文件。
P195,例9.6。
說明:P196,(1)~(5)。
9.3 條件編譯
條件編譯是指某些程序段一定的條件下參加編譯或不參加編譯,有關條件編譯的預處理命令有三種格式:
1 #ifdef格式
格式:#ifdef 標識符
程序段1
[#else
程序段2]
#endif
功能:如果標識符用#define命令定義過,則編譯程序段1,否則編譯程序段2。
P197,例。
2 #ifndef格式
格式:#ifndef 標識符
程序段1
[#else
程序段2]
#endif
功能:如果標識符未用#define命令定義過,則編譯程序段1,否則編譯程序段2。
P198,例。
3 #if格式
格式:#if 表達式
程序段1
[#else
程序段2]
#endif
功能:如果表達式的值為真,則編譯程序段1,否則編譯程序段2。
P198,例。
半期考試
試卷講評
第10章 指第11章 針
指針是C語言中一個最重要而又較難掌握的一個概念,也是C語言優于其它高級語言的關鍵所在。掌握指針的應用,可以使程序簡潔、緊湊、高效。
10.1 地址和指10.2 針概述
1. 地址與地址運算
地址:計算機中存儲單元的編號稱為地址。在內存中每一個字節都有地址,一個存儲區域的地址是這個區域的第一個字節的地址。
地址運算符&:求出變量所占用存儲區域的地址
P201,例。
注意:(1)地址運算符是單目運算,與單目+、-相同;
(2)結合方向同:從右到左。
2. 指針與指針變量
指針:一個存儲區域的地址稱為指針。
指針變量:用來存放存儲區域的地址的變量稱為指針變量。
P202,例。
注意:(1)變量的值可以通過變量直接訪問,也可通過指針變量間接訪問;
(2)指針變量只能用來存放地址,不能存放其它類型數據。
10.3 變量的指10.4 針和指10.5 向變量的指10.6 針變量
1. 變量的指針和指向變量的指針變量
指向變量的指針:一個變量的地址稱為指向該變量的指針。
指向變量的指針變量:用來存放變量的地址的變量稱為指向該變量的指針變量。
例:int a;則&a就是指向a的指針;若p為指針變量,且p=&a;則p是指向a的指針變量。
2. 指針運算符
指針運算符*:求出指針變量所指向存儲區域的值或所指向變量的值
例:int a;若p為指針變量,且p=&a;則*p是p指向的存儲區域的值,即*p的值就是a的值。
注意:(1)指針運算符是單目運算,與單目+、-相同;
(2)結合方向同:從右到左。
P203,例。
10.2.1 指針變量的定義
1. 指針變量的定義
格式:類型名 *指針變量名,…;
功能:定義指向類型名變量的指針變量。
例:int *p;定義一個指向整形變量的指針p。
P203,例。
2. 指針變量的賦值
格式:指針變量=&變量;
功能:把=號右邊變量的地址賦給=號左邊的指針變量。
P203,例。
注意:(1)指針變量賦值后的圖表示。
(2)指向不同類型的指針不能互相賦值。
(3)加了#include “stdio.h”后,指針變量可賦值為NULL。
10.2.2 指針變量的引用
指針變量的引用主要用到地址運算符&和指針運算符*。
P204,例10.1。見ex10-1.c。
說明:P204,(1)~(4).
注意:(1)若p=&a;則&*p為a的地址,即&a。P205。
(2)若p=&a;則*&a為a的值,即就是a。
(3)(*p)++與a++等價,因*與++同級,又結合方向為從右向左,故在此()不可省,否則變為*(p++)。若i=3;p=&i;則這兩個表達式的值都為3,但執行后前者p仍指向i,且i的值會加1,后者p指向i的后一個區域,i的值未加1。見ex205.c。
P206,例10.2。
說明:此例中p1,p2的指向進行變換,而a,b的值并未交換。
10.2.3 指針作為函數參數
用指針作為函數的參數,可以實現“通過被調函數改變主調函數中變量的值”的目的。
P207,例10.3。
說明:此例中p1,p2的指向并未進行變換,而它們指向的值進行了交換。
注意:(1)用指針作為函數的參數,就其指針變量而言仍然是有傳入沒傳出,但它傳送的是地址,故這時是傳址調用,即對指針所指向的值是有傳入也有傳出,故改變指針指向的值可以實現上述目的。
(2)用指針作為函數的參數,不能通過改變形參指針的值來達到“改變主調函數中變量的值”的目的。P209。
P210,例10.4。
10.7 數組與指10.8 針
10.3.1 指向數組元素的指針
設a為元素個數為n的一維數組,p為指向數組a的元素類型的指針,如果p=a或p=&a[0],即p指向a[0],則p+i指向a[i],此時可把a[i]寫成p[i]。
P211,例。
注意:(1)一維數組名a表示數組a的首地址,即a[0]的地址,故a與&a[0]等價。
(2)一維數組a的第i個元素a[i]的地址可以用a+i表示,故a+i與&a[i]等價。
10.3.2 通過指針引用數組元素
設a為元素個數為n的一維數組,p為指向數組a的元素類型的指針,如果p=a或p=&a[0],則數組a的第i個元素有兩種表示法:
a[i] 或p[i] 下標表示法
*(a+i)或*(p+i) 地址表示法
P212,例。
P212,例10.5。見ex10-5-1.c,ex10-5-2.c,ex10-5-3.c。
說明:三種方法比較,P213,(1)~(3)
注意:(1)可以改變p的值,但不能改變a的值;
(2)要注意指針的當前值。P214,例10.6。
(3)指針值超出數組范圍時系統不提示出錯。
(4)要注意指針變量的運算。P215①~⑤。
10.3.3 用數組名作為函數參數
在函數的參數中,實參與形參可以都是數組,也可以都是指針,還可以一個是數組一個是指針。
P216,例,P221,(1)~(4)。
P217,例10.7。見ex10-7-1.c,ex10-7-2.c。
P219,例10.8。
注意:(1)用指針和數組作為參數,它們傳送的是地址,故是傳址調用,它們所指向的數組的值是有傳入也有傳出的。
(2)當數組作為形式參數時,數組名不再是常量,與指針意義相同。
P217,例。
P222,例10.9。見ex10-9-1.c,ex10-9-2.c。
P223,例10.10。
10.3.4 多維數組與指針
1. 多維數組元素的地址
設a為元素個數為m×n的二維數組,則a+i表示第i行a[i]的地址,*(a+i)+j表示第i行第j個元素a[i][j]的地址,于是數組a的第i,j個元素有三種表示法:
a[i][j] 下標表示法
*(a[i]+j) 下標地址表示法
*(*(a+i)+j) 二級地址表示法
P225,例。
P227,例10.11。
注意:(1)二維數組名a表示數組a的第0行的地址,即a[0]的地址,故a與&a[0]等價。
(2)二維數組a的第i個元素a[i]表示第i行第0個元素的地址,即a[i][0]的地址,故a[i]與& a[i][0]等價。
2. 指向多維數組元素的指針變量
(1)指向數組元素的指針
設a為元素個數為m×n的二維數組,p為指向a的元素類型的指針,如果p=a[0],即p指向a[0][0],則p+i×n+j指向a[i][j]。
P228,例10.12。
(2)指向一維數組的指針
指向一維數組的指針稱為數組指針。
格式:類型名 (*數組指針名)[常量表達式],…;
功能:定義指向元素個數為常量表達式的一維數組的指針。
注意:數組指針用來存放一維數組的首地址;
P229,例10.13。
(3)數組指針與二維數組的行
數組指針可用來指向二維數組的行,故也稱行指針。
設a為元素個數為m×n的二維數組,p為指向元素個數為n的一維數組的指針,如果p=a,即p指向a[0],則p+i指向a[i],* (p+i)+j指向a[i][j]。
P229,例10.13。
3. 用指向數組的指針作為函數的參數
普通指針作為函數的參數,因為可以讓p+i指向a[i](一維數組元素),故可以用來傳遞一維數組元素的地址;同樣的道理,指向數組的指針作為函數的參數,因為可以讓p+i指向a[i](二維數組的行),故可以用來傳遞二維數組的行地址。
P230,例10.14。
P231,例10.15。
10.9 字符串與指10.10 針
10.4.1 字符串的表示形式
在C語言中,字符串有兩種表示形式。
1 用字符數組存放一個字符串;
2 用字符指針指向一個字符串。
P232,例10.16,例10.17。
注意:(1)字符數組占有固定的存儲空間,字符數組名是常量,故不能賦值、不能自增減。
(2)字符指針只是用來存放字符串的首地址,字符指針是變量,故可以賦值、可以自增減。
P234,例10.18,例10.19。
10.4.2 字符串指針作為函數的參數
把字符串從一個函數傳遞到另一個函數,可有兩種方法。
1 用存放一個字符串的字符數組;
2 用指向一個字符串的字符指針。
P235,例10.20。
解法:(1)用字符數組作為形參,P235。
(2)用字符指針作為形參,P236。
(3)對copy_string函數的簡化,P237,①~⑥。
10.4.3 對使用字符指針和字符數組的討論
(1)字符數組存放的是若干個字符,字符指針存放的是字符串的首地址。
(2)字符數組不能對數組名賦值,字符指針可以對指針名賦值。P238。
(3)字符數組和字符指針都可以初始化。P239。
(4)字符數組定義后有分配存儲空間存放字符串,字符指針只分配一個單元存放字符地址(字符串的首地址)。P239。
(5)字符數組名不能增值,字符指針名可以增值。P240,例10.21,例10.22。
(6)當字符數組存放一個字符串或字符指針指向一個字符串時,可用作printf語句的格式控制。P240。
10.11 指10.12 向函數的指10.13 針
10.5.1 用函數指針調用函數
一個函數是一個指令的序列,函數執行時是從第一條指令開始直到最后一條指令結束,第一條指令的地址稱為函數的入口地址,函數名代表這個函數的入口地址。用來存放函數入口地址的指針稱為指向函數的指針,簡稱函數指針。
(1)指向函數的指針定義
格式:類型名 (*函數指針變量名)( );
功能:定義一個指向函數的指針。
P241,例。
(2)指向函數的指針的賦值和引用
格式:函數指針變量=函數名;
(*函數指針變量)(實參,…)
功能:前者是把函數的入口地址賦給指向函數的指針,后者是用指向函數的指針調用該函數。于是函數的調用方法有兩種:
函數名(實參,…) 用函數名調用
(*函數指針變量)(實參,…) 用函數指針調用
P242,例。
P241,例10.23。
注意:(1)用函數指針調用函數,必須先給函數指針賦函數名;
(2)函數指針雖然是變量,但p+n、p++、p--等無意義。
10.5.2 用函數指針作為函數的參數
有了函數指針,可以用一個語句調用不同的函數;用函數指針作為函數的參數,可以把不同的函數傳遞到同一個子函數。因此函數指針可以簡化多個函數的調用。
P243,例。
P243,例10.24。
10.14 返回指10.15 針值的函數
一個函數的返回值可以是指針類型的,這樣的函數稱為返回指針值的函數,簡稱指針函數。
格式:函數類型 *函數名(形式參數表列)
{
數據聲明部分;
執行語句部分;
}
功能:定義一個指向類型名的指針函數。
P246,例10.25。
P247,例10.26。
注意:字符串運算函數strcat、strcpy等都是返回指針的函數。
P136。
10.16 指10.17 針數組和指10.18 向指10.19 針的指10.20 針
10.7.1 指針數組的概念
數組的元素為指針類型的數組稱為指針數組。
格式:類型名 *指針數組名[常量表達式],…;
功能:定義指向類型名的指針數組。
注意:(1)指向字符型的指針數組稱為字符指針數組;
(2)m×n的二維字符數組可以用來存放m個長度為n-1的字符串;
元素個數為m的字符指針數組可用來指向m個隨意長度的字符串。
P249,例。
P249,例10.27。
10.7.2 指向指針的指針
(1)二級指針與多級指針
指向指針的指針稱為二級指針。
格式:類型名 **指針變量名,…;
功能:定義二級指針。
P251,例。
注意:同理可以定義多級指針。
(2)二級指針與多級指針的引用
設p為二級指針,則*p為一級指針,**p為所指類型的變量。
P251,例。
注意:不同級別的指針不能互相賦值。
P252,例10.28。
P252,例10.29。
*10.7.3 指針數組作為main的形參
(1)main函數的參數
main函數一般是不帶參數的,因為沒有函數可以調用main函數。但main函數實際上也是可以帶參數的,一般格式為:
main(int argc,char *argv[])
其中:形參argc是一個整型變量,形參argv是一個字符指針數組。
(2)DOS下執行程序的命令行
C源程序*.c被編譯連接后生成可執行程序*.exe,可以DOS下通過命令行執行該程序。命令行的一般格式為:
可執行程序名 參數 參數 …↙
其中:可執行程序名、參數、參數等都是字符串,↙表示回車符。
P253,例。
(3)命令行與源程序的參數傳遞
當用戶鍵入命令行執行時,字符串:可執行程序名、參數、參數、…將傳送給argv[0]、argv[1]、argv[2]、…。Argc將取得命令行中字符串的個數。
P254,例。
10.21 有關指10.22 針的數據類型和指10.23 針運算小結
10.8.1 有關指針的數據類型小結
涉及到指針的類型主要有:
變量,一級指針,一維數組,指針數組,數組指針,函數,指針函數,函數指針,二級指針等。
P255,表10.2。
10.8.2 指針運算小結
(1)指針與整數相加減
設指針p是指向某類型的,這個類型占用c個字節,i為整數,則
1 p++,2 p--,3 p+i,4 p-i,5 p+=i,6 p-=i等都是合法的;
7 p+i的值(地址)=p的值(地址)+i×c
P256,例。
(2)指針變量的賦值
可以給指針變量賦值的有:
1 相應類型變量的地址值;
2 一維數組名或其元素的地址值;
3 函數的入口地址;
4 相應類型指針變量。
P256,例。
(3)指針變量可以有空值
空指針值用NULL表示,它是一個符號常量,它在stdio.h中,可以把它賦給指針變量,這時表示指針變量有確定值但沒有指向任何有用單元。
P256,例。
注意:定義了指針變量還末賦值前它是一個不確定的地址值,不是空指針值。
(4)兩個指針的相減
指向同一數組元素的兩個指針可以相減,其值為兩個指針所指元素之間的元素個數。
P257,例。
(5)兩個指針的比較
指向同一數組元素的兩個指針可以比較大小,其大小取決于所指向元素的序號,相等表示它們指向同一元素。
P257,例。
10.8.3 void指針類型
指向void(空)類型的指針只能用來存放一個地址,但這個地址不與任何類型掛鉤。不同類型的指針之間不能相互賦值,但可強制轉換后進行賦值。
P257,例。
第12章 結構體與共用體
11.1 結構體類型概述
結構體是由不同類型的一組數據構成的。與數組比較,數組是由相同類型的一組數據構成的。結構體與數組都是一種構造類型。
結構體類型的定義:
格式:struct 結構體類型名
{類型名 成員名;
… …
};
其中:類型名 成員名;… … 稱為“成員表列”。
功能:定義一個結構體類型。
P260,例。
注意:這是我們所見的第一個用戶自定義類型,以前我們學過的類型全是C系統預定義的。數組類型雖然也是構造類型,但不需用戶自定義類型。
11.2 定義結構體類型變量的方法
定義了結構體類型后,就可以用它來定義結構體類型的變量。結構體類型變量的定義方法有三種:
1. 分步定義
格式:struct 結構體類型名 結構體變量名,…;
其中:結構體類型名是事先已定義的。
功能:用已定義的結構體類型定義結構體變量。
P261,例。
2. 同時定義
格式:struct 結構體類型名
{類型名 成員名;
… …
}結構體變量名,…;
其中:結構體類型名事先是未定義的。
功能:同時定義結構體類型與結構體變量。
P262,例。
3. 直接定義
格式:struct
{類型名 成員名;
… …
}結構體變量名,…;
其中:結構體類型被定義但并未取名。
功能:直接定義結構體變量。
P262,例。
說明:
(1)定義一個結構體類型,系統并未為它分配存儲空間。用結構體類型定義變量后才為變量分配存儲空間,其空間大小等于各成員所占空間之和。P261,例。
(2)結構體類型中的成員相當于普通變量,但它們與普通變量屬于不同的層次,故成員與程序中的普通變量可以同名。P262,例。
(3)成員也可以是結構體變量,即結構體類型可以嵌套。P262,例。
(4)系統沒有預定義結構體類型,要用結構體類型,必須先定義后使用。
P261,例。
11.3 結構體變量的引用
定義了結構體變量后,我們可以引用結構體變量及其成員,引用結構體變量的成員格式為:
格式:結構體變量.成員名
功能:引用結構體變量的一個成員
說明:(1)“.”稱為成員運算符,其優先級最高,與( )相同。
(2)“結構體變量.成員名”的類型與結構體類型定義時的成員名類型相同。
P263,例。
引用規則:
(1)結構體變量不能整體輸入與輸出,必須要用成員引用的方法來進行。P263,例。
(2)如果成員本身又屬于一個結構體類型,則要用多個成員運算符,一級一級地找到最低一級的成員。P263,例。
(3)結構體變量的成員可象普通變量一樣進行各種運算。P264,例。
(4)可以引用結構體變量成員的地址,也可以引用結構體變量的地址。
P264,例。
(5)兩個相同類型的結構體變量可以整體賦值,但結構體變量不能整體賦給一組常量。P262,例。
11.4 結構體變量的初始化
在定義結構體變量時,可對結構體變量進行初始化。
方法:在定義結構體變量時加上={初始值,初始值,…,初始值}
P264,例11.1。
注意:(1)結構體變量不能整體賦給一組常量。
(2)兩個相同類型的數組不可以整體賦值。
11.5 結構體數組
每個元素為結構體類型的數組稱為結構體數組。
11.5.1 結構體數組的定義
與定義普通數組一樣,定義結構體數組只要在定義變量的后面加[常量表達式]即可。如int a; 是定義整型變量a;
int a[5]; 是定義整型數組a;
因為定義結構體變量的方法有三種,故定義結構體數組的方法也有三種:
(1)分步定義
(2)同時定義
(3)直接定義
P265,例。
11.5.2 結構體數組的初始化
在定義結構體數組時,可對結構體數組進行初始化。
方法:在定義結構體數組時加上={{初始值,…},…,{初始值,…}}
P266,例。
11.5.3 結構體數組的應用舉例
P266,例11.2。
說明:(1)引用結構體數組某一元素的成員要寫成:結構體數組[i].成員名;
(2)注意leader[j].count++的運算次序。
11.6 指11.7 向結構體類型數據的指11.8 針
11.6.1 指向結構體變量的指針
用來存放結構體變量的地址的指針稱為結構體指針。
1. 結構體指針的定義
與定義普通指針一樣,定義結構體指針只要在定義變量的前面加個*即可。如 int a; 是定義整型變量a;
int *a; 是定義整型指針a;
因為定義結構體變量的方法有三種,故定義結構體指針的方法也有三種:
(1)分步定義
(2)同時定義
(3)直接定義
P268,例11.3。
2. 結構體指針的引用
定義了結構體指針p后,可以用來存放結構體變量s的地址,即p=&s;這時,設s有成員num,則結構體變量的成員有三種等價的表示法:
1 s.num
2 (*p).num
3 p->num
P268,例11.3。
注意:“->”稱為指向運算符,優先級最高,與( )相同。
P269,例。
11.6.2 指向結構體數組元素的指針
結構體指針可以用來存放結構體數組的首地址或數組元素的地址。
設p為結構體指針,stu為結構體數組,且p=stu或p=&stu[0],則p++指向結構體數組stu的下一個元素。于是其下個元素的成員num可表示為:(*p). num或p->num。
P269,例11.4。
注意:(1)(++p)->num與(p++)->num的含義;
(2)p不能用來存放結構體數組元素成員的地址,但可強制轉換。
P270,例。
11.9 用指11.10 針處理鏈表
11.7.1 鏈表概述
鏈表的定義:
4 有一個首指針,指向第一個結點;
5 每個結點有一個或多個數據成員和一個指針成員,指針成員指向下一個結點;
6 末結點指針成員的值為NULL。
P273,圖11.10。
注意:(1)鏈表是一種常見的數據結構,如一個班的學生成績可用鏈表來存放,一個程序(指令的有序集)在計算機內也是用鏈表的方式來存放的;
(2)鏈表結構可以是動態地分配存儲空間的,即結點是可以動態的建立或刪除的;
(3)鏈表的一個結點是一個結構體類型的存儲空間,可用結構體類型來描述。
P273,例。
11.7.2 簡單鏈表
建立和輸出一個簡單鏈表的步驟:
2 定義一個含有數據成員和指針成員的結構體類型;
3 用這個結構體類型定義若干個變量(即開創若干個結點空間)和一個首指針及一個遍歷指針;
4 對這些變量的數據成員輸入數據,并用首指針和這些這些變量的指針成員把結點連接成一個鏈表;
5 用遍歷指針遍歷所有的結點,輸出各結點數據成員的值。
P274,例11.7。見ex11-7.c。
注意:用這種方法建立鏈表還不是動態分配存儲空間的,因為需要幾個結點必須事先用變量來定義,故稱為靜態鏈表。
11.7.3 處理動態鏈表所需的函數
建立動態鏈表需要如下幾個庫函數:
1. malloc函數
原型:void *malloc(unsigned size);
功能:在內存開辟一個大小為為size個字節的存儲空間,并返回這個存儲空間的首地址。
例:int *p;
p=(int *)malloc(2);
2. calloc函數
原型:void *calloc(unsigned n,unsigned size);
功能:在內存開辟n個大小為為size個字節的存儲空間,并返回這個存儲總空間的首地址。
例:int *p;
p=(int *)calloc(5,2);
通過p++可以遍歷這5個大小為兩個字節的存儲空間。
3. free函數
原型:void free(void *p);
功能:釋放由malloc或calloc開辟的且由p指向的存儲空間,本函數無返回值。
例:int *p;
p=(int *)malloc(2);
free(p);
11.7.4 建立動態鏈表
建立一個動態鏈表的步驟:
4 用結構體類型定義一個首指針、一個開辟指針和一個末指針;
5 用開辟指針和malloc函數開辟一個結點,并對這個結點的數據成員輸入數據;
6 當這個結點的數據成員的值不為0,則用首指針或前一結點的指針成員指向它,并讓末指針也指向它;
7 用開辟指針和malloc函數開辟一個新結點,并對這個結點的數據成員輸入數據,回到(3);
8 置末結點的指針成員值為NULL。
P276,例11.8。見ex11-8.c。
注意:用這種方法建立鏈表是動態分配存儲空間的,因為需要幾個結點事先并未確定,故稱為動態鏈表。
11.7.5 輸出動態鏈表
輸出一個動態鏈表的步驟:
2 用結構體類型定義一個遍歷指針;
3 用遍歷指針遍歷所有的結點,輸出各結點數據成員的值。
P279,例11.9。見ex11-8.c。
11.7.6 動態鏈表的刪除結點
動態鏈表刪除結點的步驟:
3 用結構體類型定義一個搜索指針和一個跟蹤指針;
4 用搜索指針遍歷所有的結點,目的是查找要刪除的結點,并用跟蹤指針跟蹤搜索指針指向結點的前一個結點;
5 如果搜索指針找到要刪除的結點,則讓跟蹤指針所指結點的指針成員指向搜索指針所指結點的后一結點(即刪除了搜索指針所指的結點)。
P280,例11.10。見ex11-8.c。
11.7.7 動態鏈表的插入結點
動態鏈表插入結點的步驟:
4 用結構體類型定義一個插入指針、一個搜索指針和一個跟蹤指針;
5 用搜索指針遍歷所有的結點,目的是查找要插入的位置,并用跟蹤指針跟蹤搜索指針所指結點的前一個結點;
6 如果搜索指針找到要(前)插入結點的位置,則讓跟蹤指針所指結點的指針成員指向插入指針所指的結點,讓插入指針所指結點的指針成員指向搜索指針所指的結點(即在搜索指針所指結點之前插入新結點)。
P282,例11.11。見ex11-8.c。
11.7.8 動態鏈表的綜合操作
動態鏈表的綜合操作步驟:
2 在所有函數外定義一個含有數據成員和指針成員的結構體類型;
3 在主函數中定義一個首指針,一個刪除數據變量和一個插入結點;
4 調用建立鏈表、輸出鏈表進行鏈表的建立與輸出的操作;
5 輸入必要的數據,調用刪除結點、插入結點的子函數進行刪除與插入的操作,并輸出操作之后的鏈表。
P284,例。見ex11-8.c。
11.11 共用體
11.8.1 共用體類型的概念
共用體類型一種與結構體類型有點類似的構造類型。
格式:union 共用體類型名
{類型名 成員名;
… …
};
其中:類型名 成員名;… … 稱為“成員表列”。
功能:定義一個共用體類型。
與結構體類型類似,共用體類型變量的定義有三種:(1)分步定義,(2)同時定義,(3)直接定義。
P287,例。
結構體與共用體的區別:
(1)結構體每個成員占用不同的存儲空間,故結構體變量占用的存儲空間是各成員占用空間的總和。
(2)共用體每個成員占用相同的存儲空間,故共用體變量占用的存儲空間是各成員占用空間的最大者。
P288,例。
11.8.2 共用體變量的引用
格式:共用體變量.成員名
功能:引用共用體變量的一個成員
說明:可見形式上引用方法與結構體相同。
P288,例。
11.8.3 共用體類型數據的特點
(1)每一瞬時只有一個成員起作用,其它成員不起作用。
(2)起作用的成員是最后一次存放的成員,其它成員的值無意義。
(3)各成員的地址是相同的。
(4)不能對共用體變量賦值,也不能進行初始化。
(5)不能把共用體變量作為函數的參數,但可以用指向共用體變量的指針。
(6)定義共用體與結構體類型時可以互相嵌套。
P289,例。
P289,例11.12。
11.12 枚舉類型
枚舉類型是可以把變量的可能值一一列出的一種構造類型。
格式:enum 枚舉類型名
{枚舉值,…,枚舉值};
功能:定義一個枚舉類型。
枚舉類型變量的定義也有三種:(1)分步定義,(2)同時定義,(3)直接定義。
P291,例。
定義了枚舉型變量后,可以使用枚舉型變量,但它的取值只可能是這些枚舉值之一。
說明:
3 枚舉值是常量,不能對枚舉值賦值。
4 枚舉值的值就是定義它時的序號(從0開始,按次序遞增),定義時也可改變枚舉值的值。
5 枚舉值可以作關系運算,大小取決于它的序號。
6 枚舉變量不能直接賦給一個整數,但可強制轉換后進行賦值。
P291,例。
P292,例11.13。
11.13 用typedef定義類型
用typedef可以定義新的類型名,主要有如下幾種情況:
(1)簡單的類型名替換
格式:typedef 原類型名 新類型名
P294,例。
(2)定義一個類型名代表一個結構體類型
格式:typedef strut
{成員列表;
}類型名;
P294,例。
(3)定義一個類型名代表某一個數據類型
格式:typedef 數組元素類型 類型名[元素個數];
typedef 指針指向類型 *類型名;
typedef 函數返回類型 (*類型名)( );
P295,例。
定義新類型名方法步驟小結:
1 先按定義變量的方法寫出定義體;
2 將變量名換成新類型名;
3 在最前面加上typedef;
4 然后用可以用新類型名去定義變量。
P295,例。
第13章 位運算
可以進行位運算是C語言的重要特色,因此,C語言具有高級語言的特點,又具有低級語言的功能。
12.1 位運算符和位運算
位運算符共有6個,見P298表12.1。
說明:(1)~是單目運算,其它是雙目運算。
(2)運算量只能是整型或字符型。
(3)優先級:① ~ ②<<,>>③ & ④ ^ ⑤ |
12.1.1 按位與運算&
運算規則:0&0=0,0&1=0,1&0=0,1&1=1。
P298,例。
按位與運算的用途:
(1)指定位清0:用一個原數指定位上為0的數進行按位與運算。
(2)取指定位:用一個原數指定位上為1的數進行按位與運算。
(3)保留指定位:與取指定位相同。
P299,例。
12.1.2 按位或運算|
運算規則:0|0=0,0|1=1,1|0=1,1|1=1。
P299,例。
按位或運算的用途:
(1)指定位置1:用一個原數指定位上為1的數進行按位或運算。
P300,例。
12.1.3 按位異或運算^
運算規則:0^0=0,0^1=1,1^0=1,1^1=0。
P300,例。
按位異或運算的用途:
(1)指定位翻轉:用一個原數指定位上為1的數進行按位異或運算。
(2)保留指定位:用一個原數指定位上為0的數進行按位異或運算。
(3)交換兩個值:只要執行a=a^b;b=b^a;a=a^b;則a,b值交換。
P300,例。
12.1.4 按位反運算~
運算規則:~0=1,~1=0。
P301,例。
按位反運算的用途:
(1)最低位清0:只要執行a=a&~1;則a的最低位被清0。
P301,例。
12.1.5 按位左移運算<<
運算規則:低位補0,高位丟失。
P302,例。
按位反運算的用途:
(1)在不溢出的情況下,左移n位,相當于原數乘以2n。
P302,例。
12.1.6 按位右移運算>>
運算規則:(1)無符號數,高位補0,低位丟失;
(2)有符號數,補與高位相同的數,低位丟失。
P302,例。
按位反運算的用途:
(1)右移n位,相當于原數除以2n。
P303,例。
12.1.7 位運算賦值
位運算賦值符有:
&=、|=、>>=、<<=、^=
其意義與“+=”等類似,也是復合賦值運算符。
P303,例。
12.1.8 不同長度的位運算
運算規則:(1)無符號數,較短的高位補0,再參與運算;
(2)有符號數,較短的補與高位相同的數,再參與運算。
P303,例。
12.2 位運算應用舉例
P303,例12.1。見ex12-1.c。
P304,例12.2。
12.3 位段
1. 位段的定義
位段是由若干個位組成的,C語言充許對由若干個位組成的位段進行存取操作。位段用類似于結構體成員的方式來描述,定義格式如下:
格式:struct 結構體類型名
{類型名 成員名:位數;
… …
};
其中:“類型名 成員名:位數”是定義位段成員。
功能:定義一個含有位段成員的結構體類型。
P306,例。
注意:定義位段成員的類型名必須是unsigned或int。
2. 位段的引用
定義了含有位段成員的結構體類型后,可以用來聲明這種結構體類型的變量,方法仍有分步定義、同時定義、直接定義三種。
P306,例。
含有位段成員結構體變量的位段成員的引用,方法與結構體變量成員的引用一樣,用“.”成員運算符。
P307,例。見ex12-3.c。
注意:位段成員值不能溢出;位段不能引用地址。
說明P307(1)~(7)
第14章 文件
13.1 C文件概述
文件:是存儲在外部介質上的指令或數據的集合。
分類:(1)文件可分為程序文件和數據文件;
(2)文件保存有ASCII形式和二進制形式兩種;
(3)文件中數據的輸入輸出要有一個緩沖區;
(4)緩沖區可由系統自動開辟(緩沖文件系統)和人工開辟(非緩沖文件系統)。
注意:本章只討論緩沖文件系統下數據文件的讀寫。
P309,例。
13.2 文件類型指13.3 針
在C中,文件的讀寫是通過文件類型指針來進行的。
1. 文件類型
文件類型是一個結構體類型,已由系統預定義,且放在庫函數文件“stdio.h”中,名為FILE。
P310,文件類型定義原型。
注意:(1)要使用文件類型,程序頭要有:#include “stdio.h”
(2)FILE是系統預定義的,無須用戶定義,只能大寫。
2. 文件指針
格式:FILE *文件指針名;
功能:定義一個文件指針。
P311,例。
注意:(1)文件指針是用來指向文件中的數據的,一般開始指向文件中的第一個數據,即開始存放的是文件的起始地址。
(2)系統預定義了兩個文件指針:stdin和stdout,分別指向鍵盤和顯示器。
13.4 文件的打開與關閉
13.3.1 文件的打開
格式:fopen(文件名,文件使用方式)
其中:(1)文件名是一個字符串,指明了要打開的文件的路徑和名字;
(2)文件使用方式由特定字符串組成,含義見P312表13.1。
功能:以指定的使用方式打開文件,為該文件開辟一個緩沖區,并返回該文件的起始地址。
P311,例。
注意:(1)以讀的方式打開,若不存在該文件,或無法打開,則出錯,返回NULL;
(2)以寫的方式打開,若已存在該文件,則覆蓋;若不存在該文件,則新建;
(3)文件使用方式要與文件的類別(文本還是二進制)相匹配。
13.3.2 文件的關閉
格式:fclose(文件指針)
其中:文件指針是指向要關閉的文件的。
功能:關閉文件指針所指向的文件,并釋放該文件的緩沖區。
P312,例。
注意:fclose也有一個返回值,正常關閉返回0,否則返回EOF(-1)。
13.5 文件的順序讀寫
13.4.1 輸入和輸出一個字符
1. 把一個字符寫到文件中
格式:fputc(ch,fp)
功能:把ch中的字符寫到fp指向的文件中。
P314,例。
注意:(1)fputc函數正常返回字符ch,輸出失敗返回EOF(-1)。
(2)fputc(ch,stdout)等價于putchar(ch)。
2. 從文件中讀取一個字符
格式:fgetc(fp)
功能:從fp指向的文件中讀取一個字符。
P314,例。
注意:(1)fgetc函數正常返回一個字符,輸入失敗返回EOF(-1)。
(2)fgetc(stdin)等價于getchar()。
(3)可用feof(fp)來檢測是否讀到文末符,是返回1,不是返回0。
3. fput和fget函數應用舉例
P315,例13.1。見ex13-1.c。
P316,例13.2。見ex13-2.c。
(下面的次序與書不同,見P332)
13.4.2 輸入和輸出一個整數或一個字符串
1. 輸入和輸出一個整數
格式:putw(i,fp)
功能:把i中的整數寫到fp指向的文件中。
格式:getw(fp)
功能:從fp指向的文件中讀取一個整數。
P322,例。見ex13-6.c。
注意:(1)有的C語言不提供putw與getw函數,這時我們可以自己定義;
(2)Turbo C提供putw與getw函數。
2. 輸入和輸出一個字符串
格式:fputs(str,fp)
功能:把字符串str寫到fp指向的文件中,但不寫\0。
格式:fgets(str,n,fp)
功能:從fp指向的文件中讀取n-1個字符到str中,包括\n并自動加上\0。
P323,例。
(下面的內容見P321)
13.4.3 格式化輸入和輸出
格式:fprintf(fp,格式控制,輸出表列)
功能:把輸出表列中的數據按格式控制寫到fp指向的文件中,但不寫\0。
格式:fscanf(fp,格式控制,輸入表列)
功能:從fp指向的文件中按格式控制讀取數據到輸入地址表列的變量中,如果是字符串會自動加上\0。
P321,例。
注意:(1)讀取時的格式要與寫入文件時的格式相匹配。
(2)fprintf(stdout,格式控制,輸出表列)等價于printf(格式控制,輸出表列)
(3)fscanf(stdin,格式控制,輸入表列) 等價于scanf(格式控制,輸入表列)
(下面的內容見P317)
13.4.4 按記錄輸入和輸出
格式:fwrite(buffer,size,count,fp)
功能:從buffer指向的存儲區域中count次讀取大小size的數據寫到fp指向的文件中。
格式:fread(buffer,size,count,fp)
功能:從fp指向的文件中count次讀取大小size的數據送到buffer指向的存儲區域中。
其中:buffer 為內存中要讀寫數據的存儲地址;
size 為要讀寫數據的字節數;
count 為要讀寫數據的次數;
fp 為要進行讀寫操作的文件指針。
P318,例。
注意:(1)按記錄讀寫只能是二進制文件;
(2)函數的返回值是成功讀寫的次數。
P318,例13.3。見ex13-3.c。
(下面的內容見P323)
13.6 文件的定位
13.5.1 指針重置文首函數rewind
格式:rewind(fp);
功能:使fp重新指向文件開頭。
P323,例13.4。
13.5.2 指針重定位函數fseek
格式:fseek(fp,m,n);
其中:(1)m為字節數,要在后面加L;
(2)n為起始點,可取0、1、2,見P324,表13.2。
功能:使fp移到離起始點n的m個字節處。
P324,例13.5。
13.7 出錯的檢測
略
13.8 文件輸入輸出小結
P326,表13.3。