《C語言程序設計新視角》課件第4章_第1頁
《C語言程序設計新視角》課件第4章_第2頁
《C語言程序設計新視角》課件第4章_第3頁
《C語言程序設計新視角》課件第4章_第4頁
《C語言程序設計新視角》課件第4章_第5頁
已閱讀5頁,還剩199頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第4章數(shù)組4.1數(shù)組概念的引入4.2數(shù)組和普通變量的類比4.3如何把數(shù)組存入機器中4.4對數(shù)組的操作4.5本章小結

【主要內容】

數(shù)組的概念、使用規(guī)則及方法實例;

通過數(shù)組與數(shù)組元素和單個變量的類比,說明其表現(xiàn)形式與本質含義;

數(shù)組的空間存儲特點及調試要點;

多維數(shù)組的編程要點;

自頂向下算法設計的訓練。

【學習目標】

掌握定義數(shù)組、初始化數(shù)組及引用數(shù)組元素的方法;

能夠定義和使用多維數(shù)組;

掌握字符數(shù)組的特殊處理。

我們前面學習了基本的數(shù)據(jù)類型,知道了如何把數(shù)據(jù)存入計算機的方法,同時學完了C語言的語句,知道了程序的三種基本結構及算法的基本實現(xiàn)方法,那么,按照圖4.1所示的程序的構成公式,是不是就能編程解決所有的實際問題了呢?4.1數(shù)組概念的引入

圖4.1程序的構成公式先請看下面的引例。

【引例1】2個數(shù)由小到大排序;3個數(shù)由小到大排序;10個數(shù)由小到大排序;100個數(shù)由小到大排序;……

(1)對于100個數(shù)的排序,至少需要設置多少個變量?

(2)應如何設置變量,使程序能以一種簡便的方式統(tǒng)一處理數(shù)據(jù)?

從算法上講,無論需要排序的數(shù)的量是多少,都可以用相同的方法處理,但是,在處理之前,這些數(shù)據(jù)應如何合理地存到計算機中呢?具體對程序員來說,就是如何設置變量的問題。3個數(shù),可以設成a、b、c;那10個數(shù)呢?100個數(shù)呢?如果每個變量名都是無規(guī)律的,那么要做循環(huán)處理,幾乎是不可行的。

當數(shù)據(jù)的數(shù)量達到一定的規(guī)模時,首先的問題就是如何合理有效地把它們存入計算機,使程序能以一種簡便的統(tǒng)一的方式引用數(shù)據(jù),然后才能考慮如何設計算法,完成所要求的功能。通常,計算機解題的兩大步驟如下:

(1)用合理的數(shù)據(jù)結構描述問題。

(2)用相應的算法解決問題。

【引例2】從鍵盤輸入100個數(shù),然后逆序輸出之。

為方便循環(huán)處理時對變量的引用,我們把這100個變量的名稱設置成有規(guī)律的形式,處理流程如圖4.2所示。

圖4.2引例2處理流程說明:Xi隨i作變化,因為下標用鍵盤輸入不方便,故Xi在程序中的表示方法就寫為X[i]。

寫出對應的程序語句:

inti;

intx[100];

for(i=1;i<=100;i++)scanf("%d",&x[i]);

for(i=100;i>=1;i--)printf("%d",x[i]);說明:

(1)intx[100]表示定義100個int類型的變量,這是一組同類型數(shù)據(jù)的集合,稱做數(shù)組,其中帶下標的變量稱做數(shù)組元素。

(2)此程序只是為了和流程圖對應,在循環(huán)中將x的下標變化從1變至100。實際在C語言中,規(guī)定下標從0開始使用,對于intx[100],下標的變化應該是從0到99。

【引例3】有一位同學,學習了6門課程,其成績如表4.1所示,求平均分數(shù)。

表4.1成績表1對于這樣的問題,我們按照引例2設置變量的方法,第i門課的成績用grade[i]表示,用數(shù)組的形式存儲課程成績,然后再完成求平均分的操作,這樣比較方便。該引例的偽代碼見表4.2。

表4.2引例3偽代碼如果問題的數(shù)據(jù)量增加,變成:有4位同學,學習了6門課程,其成績如表4.3所示,求平均分。此時,每個學生的成績又該如何表示呢?

表4.3成績表2觀察可知,表中每個學生的成績所在位置都是由行和列兩個信息唯一確定的,我們用i表示行,j表示列,則第i位同學第j門課的成績可以用帶兩個下標的變量來表示:grade[i][j]。成績表各個元素與下標的關系見表4.4。

表4.4數(shù)

據(jù)

標把表中每個數(shù)據(jù)都以有規(guī)律的方式命名存儲后,按照上面只有一位學生求平均分的算法將其循環(huán)執(zhí)行4次,即可分別求得4位同學的平均分,完成題目的要求。

綜上,我們可以說,數(shù)組是在程序設計中,為了處理方便,把相同類型的若干變量按有序的方式組織起來的一種形式。

數(shù)組:一組帶下標的同類型數(shù)據(jù)的集合。

我們知道,普通變量的三個要素是變量名、變量值和存儲單元。數(shù)組既然是一組同類型變量的集合,也應該具有同普通變量類似的要素和相關的用法,參見表4.5。4.2數(shù)組和普通變量的類比

表4.5變

數(shù)

4.3.1數(shù)組的定義

C語言的數(shù)組定義形式:

數(shù)據(jù)類型數(shù)組名[常量1][常量2]…[常量n];4.3如何把數(shù)組存入機器中說明:

(1)數(shù)據(jù)類型可以是任何一種基本數(shù)據(jù)類型或構造數(shù)據(jù)類型。

(2)數(shù)組名是用戶定義的數(shù)組標識符。

(3)方括號的對數(shù)表示數(shù)組的維數(shù)。方括號中的常量表達式表示數(shù)據(jù)元素的個數(shù)。如果只有一對括號,則表示一維數(shù)組,有兩對括號表示二維數(shù)組,以此類推。本書只介紹一維和二維數(shù)組。

數(shù)組元素:數(shù)組中帶下標的變量。數(shù)組元素的使用規(guī)則和普通同類型變量類似。其引用形式如下:

數(shù)組名[下標1][下標2]

[下標n]

關于數(shù)組及數(shù)組的下標要注意以下幾點:

·定是0開始:C語言規(guī)定,數(shù)組的下標一定是從0開始的;

·數(shù)值表達式:數(shù)組下標所在位置可以是數(shù)值表達式;

·越界要制止:不能使用超出定義空間的數(shù)組元素。4.3.2數(shù)組的初始化

數(shù)組初始化:指在定義數(shù)組的同時給數(shù)組元素賦初值。

數(shù)組初始化的各種情形見表4.6。

表4.6數(shù)組初始化的情形4.3.3數(shù)組的存儲

數(shù)組的存儲有以下特點:

(1)定義分空間:與一般的普通變量一樣,數(shù)組的存儲空間也是在定義時分配的,可以使用sizeof運算符測試數(shù)組占用內存空間的大小:

數(shù)組的空間大小=sizeof(數(shù)組的數(shù)據(jù)類型)*數(shù)組元素的個數(shù)

(2)運行不能變:數(shù)組的存儲空間大小一旦分配好了,在程序運行過程中就不能改變了。

(3)元素都相連:數(shù)組元素的空間是按下標順序連續(xù)分配的。

【例4-1】數(shù)組的空間分配。

(1)intx[100]={1,3,5,7};

根據(jù)一維數(shù)組x的定義,系統(tǒng)給它分配100個存儲單元,每個單元長度都是一個int的長度。一維數(shù)組x的空間分配見表4.7。

表4.7一維數(shù)組x的空間分配

(2)inta[2][3]={{1,3,5},{2,4,6}};

根據(jù)二維數(shù)組a的定義,系統(tǒng)給它分配2×3=6個存儲單元,每個單元長度都是一個int的長度。二維數(shù)組a的空間分配見表4.8。

表4.8二維數(shù)組a的空間分配說明:

(1)C語言中規(guī)定數(shù)組的名字代表數(shù)組的起始地址。這里的地址是指內存中存儲單元的位置。

(2)二維數(shù)組是按行優(yōu)先順序存儲的,即是先存第0行的元素,再存第1行,以此類推。第一個下標代表行,第二個下標代表列。

(3)C語言規(guī)定,二維數(shù)組每一行的起始地址由數(shù)組名加一維下標構成。例如數(shù)組inta[2][3],a[0]表示第0行的起始地址,a代表a數(shù)組的起始地址,所以a[0]和a的值是一樣的。

數(shù)組在定義時若沒有賦初值,存儲單元的值會是什么?

答:同普通變量定義的情形類似,是一組隨機值。(全局量時例外,全局量的含義參見第5章。)

下面兩種情形,會給數(shù)組a分配空間嗎?

情形一:

intx;

inta[x];

情形二:

intx=100;

inta[x];答:根據(jù)數(shù)組的定義形式

數(shù)據(jù)類型數(shù)組名[常量];

數(shù)組的空間長度分配是根據(jù)數(shù)組的數(shù)據(jù)類型和方括號中的常量值確定的,在程序的運行中不能被改變。

對于情形一:

數(shù)組a的括號中是變量,在數(shù)組a定義時無法確定x的值,所以inta[x]是非法的。

對于情形二:數(shù)組a的括號中是變量,在數(shù)組a定義時,x雖然賦了初值,但數(shù)組的定義形式要求數(shù)組長度是常量,故這種數(shù)組定義法也是非法的。以上兩種情形都是初學者容易犯的錯誤,要特別注意。

數(shù)組的長度應在定義時確定,在程序運行中不能被改變。4.3.4數(shù)組存儲空間的查看方法

【例4-2】使用初始值列表來初始化數(shù)組。

1 /*使用初始值列表來初始化數(shù)組*/

2 #include<stdio.h>

3 intmain()

4 {

5 /*使用初始值列表來初始化數(shù)組*/

6 intm[5]={1,3,5,7,9};

7 inta[2][3]={{1,3,5},{2,4,6}};

8 intb[6]={1,3,5};

9 intx[100]={1,3,5,7};

10 intn[]={1,3,5,7,9};

11 charc[]="abcde";

12 inti,j;

13

14 /*以列表形式輸出一維數(shù)組m*/

15 printf("一維數(shù)組m[5]\n");

16 printf("%s%13s\n","Element","Value");

17 for(i=0;i<5;i++)

18 {

19 printf("%7d%13d\n",i,m[i]);

20 }

21 printf("\n");

22

23 /*以列表形式輸出二維數(shù)組a*/

24 printf("二維數(shù)組a[2][3]\n");

25 for(i=0;i<2;i++)

26 {

27 for(j=0;j<3;j++)

28 {

29 printf("%d",a[i][j]);

30 }

31 printf("\n");

32 }

33 return0;

34 }程序結果:

一維數(shù)組m[5]

ElementValue

01

13

25

37

49

二維數(shù)組a[2][3]

135

246

圖4.3~圖4.13分別為例4-2的調試步驟1~調試步驟11。

調試要點:

·一維數(shù)組的整體查看方法;

·一維數(shù)組元素的查看方法;

·二維數(shù)組的整體查看方法;

·二維數(shù)組元素的查看方法;

·字符串的結束標志問題。

1.查看一維數(shù)組

1)整體查看

(1)直接在Watch窗口的Name欄鍵入數(shù)組名。比如要查看m數(shù)組,鍵入m后,Watch窗口中顯示的內容如圖4.3所示。

注意:數(shù)組名m左側是一個帶框的加號,表明用鼠標點開后,里面還有內容;Value的部分是一個十六進制的數(shù),這是數(shù)組m在內存中的起始地址,C語言規(guī)定數(shù)組名是一個地址常量。

(2)點開數(shù)組名前的加號,則Name欄顯示m數(shù)組的元素m[0]~m[4],如圖4.4所示。

圖4.3例4-2調試步驟1

圖4.4例4-2調試步驟2注意:元素的值是隨機值,而不是我們賦的1、3、5、7、9。這是因為,程序部分顯示跟蹤步驟的箭頭當前指向的是“intm[5]={1,3,5,7,9};”,表明此條定義初始化語句處于還未執(zhí)行而將要執(zhí)行的狀態(tài)。

(3)按F10鍵,再向下執(zhí)行一步,完成m數(shù)組的初始化,如圖4.5所示。

圖4.5例4-2調試步驟3

2)單個元素值的查看

在Name欄中輸入元素名即可,如圖4.6所示。圖4.6例4-2調試步驟4

2.查看二維數(shù)組

1)整體查看

(1)輸入數(shù)組名,如圖4.7所示。圖4.7例4-2調試步驟5二維數(shù)組名也是一個地址值,是二維數(shù)組的起始地址。

(2)點開數(shù)組名前的加號,如圖4.8所示。圖4.8例4-2調試步驟6

a[0]和a[1]也是地址值。C語言規(guī)定,二維數(shù)組名加一維下標表示行地址,即a[0]表示第0行的起始地址,a[1]表示第1行的起始地址。

(3)點開行地址前的加號,如圖4.9所示。

(a)數(shù)組初始化前(b)數(shù)組初始化后圖4.9例4-2調試步驟7

2)查看一行元素

輸入行地址a[1],點開a[1]前的加號,如圖4.10所示。

3)查看數(shù)組元素

鍵入元素名,如圖4.11所示。

圖4.10例4-2調試步驟8

圖4.11例4-2調試步驟9

2.其他情形的說明

(1)intb[6]={1,3,5};

這是b數(shù)組初始化的情形,未賦值的單元系統(tǒng)自動清零,如圖4.12所示。

(2)charc[]="abcde";

這是字符數(shù)組初始化的情形,如圖4.13所示。C語言允許用字符串的形式對數(shù)組作初始化賦值。

(1)地址后的字符串"abcde"是數(shù)組c的內容。

(2)c[0]行中的97是字符a的ASCII碼。

(3)c[5]的值為0,稱為空字符,是系統(tǒng)自動添加的。

(4)c數(shù)組的長度為串"abcde"中字符的個數(shù)5加上空字符的個數(shù)1。

圖4.12例4-2調試步驟10

圖4.13例4-2調試步驟11注意:字符串總是以‘\0’作為串的結束符,這個‘\0’空字符是系統(tǒng)自動添加的,因此當把一個字符串存入一個數(shù)組時,也把空字符存入數(shù)組,并以此作為該字符串是否結束的標志。

如果一個數(shù)組未初始化,那么數(shù)組元素的初始值會是什么呢?

答:這和普通變量定義時的情形是類似的,讀者可自行上機查看。

4.4.1數(shù)組的賦值方法

給數(shù)組賦值的方法有下面兩種:

(1)初始化:在數(shù)組的定義中使用初始值列表。

(2)循環(huán)賦值:包括鍵盤輸入和表達式賦值。

·鍵盤輸入:用輸入函數(shù)接收數(shù)據(jù);

·表達式賦值:數(shù)組元素的值變化是有規(guī)律的,可以用表達式表示出來。4.4對數(shù)組的操作

【例4-3】對一維數(shù)組的循環(huán)賦值。求斐波那契(Fibonacci)數(shù)列的前20項。

注:斐波那契數(shù)列即0112358132134…,其遞推公式為

F(0)=0,F(xiàn)(1)=1,

F(n)=F(n-1)+F(n-2)

【解】思路:按斐波那契數(shù)列的構成規(guī)律,先把全部20項構造出來存放到數(shù)組,然后再輸出。

算法的頂部及分步細化描述如表4.9~表4.11所示。

表4.9例4-3偽代碼1

表4.10例4-3偽代碼2表4.11例4-3偽代碼3

忘記對需要初始化的數(shù)組元素進行初始化。

第二步細化完成后,就可以方便地寫出程序了:

1 /*求斐波那契數(shù)列的前20項*/

2 #include<stdio.h>

3 intmain()

4 {

5 inti;

6 intf[20]={0,1}; /*數(shù)組初始化*/

7

8 for(i=2;i<20;i++) /*生成數(shù)列內容*/

9 {

10 f[i]=f[i-1]+f[i-2]; /*Fibonacci數(shù)列遞推式*/

11 }

12 for(i=0;i<20;i++) /*輸出數(shù)組內容*/

13 {

14 if(i%5==0)printf("\n"); /*輸出為每行5個*/

15 printf("%8d",f[i]);

16 }

17 return0;

18 }程序結果:

01123

58132134

5589144233377

610987159725844181

表4.12所示為讀程分析表。

表4.12讀

表注意:數(shù)組下標從0開始,最后一個元素的下標應該為數(shù)組長度減1。

(1)如何讓程序方便地構造任意項的斐波那契數(shù)列?

答:將數(shù)組的大小定義為符號常量,可以使程序的可伸縮能力更強。

(2)對于上述程序中的第一個for循環(huán)(第8行),如果循環(huán)運行條件寫成i<=20,會造成什么問題?

答:會造成數(shù)組下標越界,因為要對f[20]單元寫操作,但f[20]并不在數(shù)組的定義范圍之內,這是程序設計的邏輯錯誤。4.4.2一維數(shù)組的元素引用

【例4-4】對數(shù)組元素進行求和。

1 /*計算數(shù)組中元素的總和*/

2#include<stdio.h>

3#defineSIZE10

4

5intmain()

6{

7 inta[SIZE]={2,5,18,4,7,6,54,46,32,17};

8 inti;/*計數(shù)器*/

9 inttotal=0;/*總和*/

10

11 for(i=0;i<SIZE;i++)

12 {

13 total+=a[i];/*對數(shù)組a中的元素求和*/

14 }

15 printf("Totalofarrayelementvaluesis%d\n",total);

16 return0;

17 }

程序結果:

Totalofarrayelementvaluesis42

圖4.14~圖4.18所示分別為例4-4的調試步驟1~調試步驟5。調試要點:

·對一維數(shù)組元素的引用、迭代;

·數(shù)組下標的越界現(xiàn)象。

圖4.14所示為調試步驟1,這是首次進入循環(huán),此時i=0,a[i]=a[0]=2,程序左側指示箭頭指向total+=a[i]語句,total值為0。

圖4.14例4-4調試步驟1圖4.15所示為調試步驟2,此時將a[i]累加進total,Total=2。圖4.15例4-4調試步驟2圖4.16所示為調試步驟3,這是第二次循環(huán),此時i=1,a[i]=a[1]=5,total+=a[i]語句執(zhí)行前total值為2,這是上次迭代的結果。

圖4.17所示為調試步驟4,total+=a[i]語句執(zhí)行后,total值為7,這是本次迭代的結果。

圖4.16例4-4調試步驟3

圖4.17例4-4調試步驟4圖4.18所示為調試步驟5,循環(huán)結束后,i=6,a[i]=a[6]=1245120,a[6]下標越界,因此得到了數(shù)組定義外的內存單元的值,total=42。

圖4.18例4-4調試步驟5

數(shù)組下標越界

數(shù)組越界錯誤主要包括數(shù)組下標值越界和指向數(shù)組的指針的指向范圍越界。

數(shù)組下標取值越界主要是指訪問數(shù)組的時候,下標的取值不在已定義好的數(shù)組取值范圍。

指向數(shù)組的指針的指向范圍越界問題在第6章中將會討論到。

C語言編譯器一般不檢查數(shù)組的下標范圍,程序中數(shù)組下標的越界使用可能會造成以下兩個問題:

(1)對越界的元素做讀操作,不會破壞內存單元的值,但用這個值參與運算,會直接造成本程序結果錯誤。

(2)對越界的元素做寫操作,會破壞內存單元的值,若此單元另有變量定義,也會造成程序結果錯誤,而且這種錯誤現(xiàn)場很難跟蹤查找,因為被改寫的單元值在什么時刻被引用是不可預計的。

數(shù)組下標越界是程序初學者最容易犯的錯誤之一。我們在使用數(shù)組時要特別注意,數(shù)組元素下標一定不能越界。4.4.3對多個一維數(shù)組的操作

【例4-5】順序結構程序的例子。用數(shù)組實現(xiàn)例3-1,從鍵盤輸入4位學生的學號和英語考試成績,打印這4人的學號和成績,最后輸出4人的英語平均成績。(成績?yōu)榘俜种频膶崝?shù)。)

【解】我們用數(shù)組的形式來處理,把學號和分數(shù)都存放在數(shù)組中。算法的頂部及分步細化描述如表4.13~表4.15所示。

表4.13例4-5偽代碼1

表4.14例4-5偽代碼2

表4.15例4-5偽代碼3根據(jù)表4.15所示的第二步細化的偽代碼,可以寫出以下程序:

1 /*順序結構程序的例子*/

2 intmain()

3 {

4 inti;/*計數(shù)器*/

5 intnumber[4];/*學號*/

6 floatgrade[4];/*分數(shù)*/

7 floattotal=0;/*總分*/

8 floataverage;/*平均分*/

9

10 /*輸入數(shù)據(jù)*/

11 for(i=0;i<4;i++)

12 {

13 printf("Enternumber:\n");/*提示輸入學號*/

14 scanf("%d",&number[i]);/*讀入學號*/

15 printf("Entergrade:\n");/*提示輸入分數(shù)*/

16 scanf("%f",&grade[i]);/*讀入分數(shù)*/

17 }

18 /*處理數(shù)據(jù)*/

19 for(i=0;i<4;i++)/*累加總分*/

20 {

21 total=total+grade[i];

22 }

23 average=total/4;/*求均分*/

24

25 /*輸出結果*/

26 for(i=0;i<4;i++)

27 {

28 printf("%d:",number[i]);/*輸出學號*/

29 printf("%f\n",grade[i]);/*輸出分數(shù)*/

30 }

31 printf("totalis%f\n",total);

32 printf("averageis%f\n",average);

33 return0;

34 }

程序結果:

Enternumber:

1001

Entergrade:

78.5

Enternumber:

1002

Entergrade:

89

Enternumber:

1003

Entergrade:

83.5

Enternumber:

1004

Entergrade:

92.5

1001:78.500000

1002:89.000000

1003:83.500000

1004:92.500000

totalis343.500000

averageis85.875000

西安電子科技大學開通了網(wǎng)上評教系統(tǒng),對教師的教學按照6~10分進行評價,現(xiàn)抽取50名學生對某教師的評分存于一數(shù)組中,編程序對各分數(shù)出現(xiàn)的頻度進行匯總。

1 #include<stdio.h>

2 #defineRESPONSE_NUM50/*評分數(shù)組大小*/

3 #defineRATING_SIZE5/*等級數(shù)組大小*/

4

5 intmain()

6 {

7 intanswer;/*計數(shù)器*/

8 intcounter;

9

10 intrating[RATING_SIZE]={0};/*評定等級數(shù)組*/

11 intresponses[RESPONSE_NUM]/*評分數(shù)組,放評分結果*/

12 ={6,8,9,10,6,9,8,7,7,10,6,9,7,7,7,6,8,10,7,

13 10,8,7,7,6,7,8,9,7,8,7,10,6,7,6,7,7,10,8,

14 6,7,7,8,6,6,7,8,9,7,7,10

15 };

16

17 /*用評分值作為評定等級數(shù)組的下標,同一種評分累加進同一下標元素中*/

18 for(answer=0;answer<RESPONSE_NUM;answer++)

19 {

20 rating[responses[answer]-6]++;

21 }

22

23 /*列表打印結果*/

24 printf("%s%17s\n","Rating","Frequency");

25 for(counter=0;counter<RATING_SIZE;counter++)

26 {

27 printf("%6d%17d\n",counter,rating[counter]);

28 }

29 return0;

30 }程序結果:

RatingFrequency

610

719

89

95

10

74.4.4對二維數(shù)組的操作

【例4-6】在N行M列的二維數(shù)組a中,找出數(shù)組的最大值以及此最大值所在的行、列下標。

【解】設二維數(shù)組如表4.16所示,N=2,M=3。

表4.16數(shù)組中的數(shù)據(jù)二維數(shù)組元素的查找順序和存儲順序是一致的,即先找第一行,再找第二行,以此類推,其下標變化規(guī)律見表4.17。

表4.17二維數(shù)組掃描順序數(shù)組元素按序查找步驟可如下進行:

先掃描i=0行有M個元素:

for(j=0;j<M;j++)

再掃描i=1行有M個元素:

for(j=0;j<M;j++)

i的值從0變化到N-1,所以,掃描完一個二維數(shù)組,需要兩個循環(huán)嵌套才能完成:

for(i=0;i<N;i++)

for(j=0;j<M;j++)

算法描述:在給定的一組數(shù)里找最大值,思路同第3章的3個數(shù)中求最大值的例子,只是這些數(shù)據(jù)放在數(shù)組里,對變量的引用需要使用二維數(shù)組元素。該例的偽代碼如表4.18~表4.20所示。

表4.18例4-6偽代碼1

表4.19例4-6偽代碼2

表4.20例4-6偽代碼3由表4.20所示的第二步細化的偽代碼,可以寫出以下程序:

1 /*二維數(shù)組的例子*/

2 #defineN2

3 #defineM3

4 #include"stdio.h"

5 intmain()

6 {

7 inti,j,a[N][M],max,line,col;

8

9 /*通過鍵盤給數(shù)組賦值*/

10 printf("inputarraynumbers:\n");

11 for(i=0;i<N;i++)

12 {

13 for(j=0;j<M;j++)

14 {

15 scanf("%d",&a[i][j]);

16 }

17 }

18

19 /*在數(shù)組中找最大值*/

20 max=a[0][0];/*取數(shù)組的第一個值做比較基準max*/

21 line=col=0;/*行、列下標與max值位置對應*/

22 for(i=0;i<N;i++)

23 {

24 for(j=0;j<M;j++)

25 {

26 if(max<a[i][j])/*在數(shù)組中按行優(yōu)先順序逐個與max比較*/

27 {

28 max=a[i][j];

29 line=i;

30 col=j;

31 }

32 }

33 }

34 printf("\nmax=%d\tline=%d\tcol=%d\n",max,line,col);

35 return0;

36 }程序結果:

inputarraynumbers:

2351076

max=10line=1col=0

圖4.19~圖4.25所示分別為例4-6的調試步驟1~調試步驟7。

調試要點:

·二維數(shù)組的查看;

·數(shù)組元素的引用順序;

·控制臺窗口的數(shù)據(jù)輸入;

·嵌套循環(huán)的執(zhí)行順序。

注意:在單步跟蹤時,若遇到scanf輸入數(shù)據(jù),要在控制臺窗口一次性將全部的數(shù)據(jù)按要求的格式輸入,如圖4.19所示的控制臺窗口中顯示的那樣。如果輸入一個數(shù)就回車,系統(tǒng)會一直在此窗口等待,不會轉向程序所在的窗口。這是調試時遇到輸入函數(shù)需要特別注意的問題。

圖4.19中,Watch窗口中的i、j為0,但數(shù)據(jù)已經(jīng)在控制臺窗口中輸入完畢。

圖4.19例4-6調試步驟1圖4.20中,i=0,j的變換從0至2,a[0][0]、a[0][1]、a[0][2]被順序賦值。圖4.20例4-6調試步驟2圖4.21中,查找最大值的嵌套循環(huán)i、j均從0開始,比較基準值取數(shù)組的第一個值a[0][0]。圖4.21例4-6調試步驟3圖4.22中,i=0,j從0變至1,max<a[i][j]條件成立,max值將被修改。

圖4.22例4-6調試步驟4圖4.23中,max值被修改,其對應的a元素行列下標值記錄在line和col中。

圖4.23例4-6調試步驟5圖4.24中,i=0,j從1變至2,行地址a[0]所在行的元素查找完畢。

圖4.24例4-6調試步驟6圖4.25中,i=1,從行地址a[1]開始查找,j從0開始。

圖4.25例4-6調試步驟7

從上面的調試中,我們可以得到循環(huán)嵌套的執(zhí)行順序如下:

(1)外層判斷循環(huán)條件,滿足則進入外層循環(huán)體,不滿足則跳出

外層循環(huán)。

(2)內層判斷循環(huán)條件,不滿足則跳出內層循環(huán)至步驟(5)。

(3)內層循環(huán)體執(zhí)行。

(4)內層循環(huán)變量累加,回到步驟(2)執(zhí)行。

(5)外層循環(huán)變量累加,回到步驟(1)執(zhí)行。

表4.21循環(huán)嵌套4.4.5對字符數(shù)組的操作

【例4-7】字符數(shù)組的初始化賦值與輸出方法。對字符數(shù)組的初始化賦值,可以按字符賦值,也可以按字符串賦值。

1 /*字符數(shù)組的初始化賦值*/

2 #include"stdio.h"

3 intmain()

4 {

5 charca[10]={'I','

','a','m','','h','a','p','p','y'};

/*按單個字符給數(shù)組賦初值*/

6 charcb[]="Iamhappy";/*以字符串方式給數(shù)組賦初值*/

7 inti;

8

9 printf("ca數(shù)組按單個字符格式輸出:\n");

10 for(i=0;i<10;i++)printf("%c",ca[i]);

11 printf("\n");

12 printf("ca數(shù)組按字符串格式輸出:\n");

13 printf("%s",ca);

14 printf("cb數(shù)組按單個字符格式輸出:\n");

15 for(i=0;i<10;i++)printf("%c",cb[i]);

16 printf("\n");

17 printf("cb數(shù)組按字符串格式輸出:\n");

18 printf("%s",cb);

19 printf("\n");

20 return0;

21 }

程序結果:

ca數(shù)組按單個字符格式輸出:

Iamhappy

ca數(shù)組按字符串格式輸出:

Iamhappy燙?

cb數(shù)組按單個字符格式輸出:

Iamhappy

cb數(shù)組按字符串格式輸出:

Iamhappy提醒:C允許存儲任意長度的字符串。當在字符數(shù)組中存儲字符串時,要確保數(shù)組足夠大,以容納將存儲的最長字符串。如果字符串的長度超過將存儲它的字符數(shù)組長度,則超出數(shù)組邊界的字符將覆蓋內存中數(shù)組后面的數(shù)據(jù)。

為什么ca數(shù)組地址后顯示的字符串最后是亂碼,而cb數(shù)組就沒有這個現(xiàn)象?答:字符串的顯示,應該是以‘\0’做結束標志的,對ca數(shù)組來說,數(shù)組下標是從0到9,通過查看圖4.26所示的Memory窗口,可看到ca[10]不是‘\0’,按%s輸出格式的要求,會一直顯示相應非0字節(jié)對應的ASCII碼字符,直到遇到‘\0’為止。所以ca數(shù)組后會顯示上面的漢字及其他信息。

cb數(shù)組后有系統(tǒng)自動添加的字符串結束標志'\0',故顯示到cb[9]會停止。

對數(shù)組ca和cb的查看結果如圖4.27所示。

圖4.26Memory窗口

(a)查看ca數(shù)組(b)查看cb數(shù)組圖4.27數(shù)組ca和cb的查看

【例4-8】對字符數(shù)組操作。輸入一個整數(shù),判斷該整數(shù):若全部由奇數(shù)字組成或全部由偶數(shù)字組成,輸出“YES!”,否則輸出“NO!”。

【解】下面分步對此題進行分析。

(1)數(shù)據(jù)的存儲問題。若輸入的整數(shù)按一個int型變量接收,則需要按位拆分后再逐位判斷奇偶,這樣比較麻煩;若按字符串方式接收輸入的整數(shù),放在字符數(shù)組里,則省去了上面的按位拆分的步驟。如輸入的整數(shù)是12345,則可以這樣接收信息:

chars[20]=“12345”;

s數(shù)組中,每個數(shù)組元素值都是一個字符,如表4.22所示。

表4.22數(shù)據(jù)分析問題是,數(shù)字字符如何轉換成真正意義上的數(shù)字呢?根據(jù)ASCII碼表可知,阿拉伯數(shù)字是按其大小順序編碼的,所以有:

‘3’-‘0’=‘0’+3-‘0’=3

48是字符‘0’的ASCII碼;s[i]-48=s[i]-‘0’。

(2)算法的設計問題。算法的關鍵問題是奇偶的判別問題,這可以通過設置標志來處理。

開始時,設置奇數(shù)標志odd初始值=1,偶數(shù)標志初始值even=1,其含義如表4.23所示。

表4.23奇偶標志按位判斷s各元素的奇偶,如果是奇數(shù),則even=0;反之,則odd=0,將s的元素全部檢查完,如果odd和even標志有一個仍然為1,則說明s全部由奇數(shù)字組成或全部由偶數(shù)字組成。

該例的偽代碼如表4.24~表4.26所示。

表4.24例4-8偽代碼1

表4.25例4-8偽代碼2

表4.26例4-8偽代碼3根據(jù)細化的偽代碼,程序實現(xiàn)如下:

1 /*字符數(shù)組及漢字問題*/

2 #include<stdio.h>

3 intmain()

4 {

5 chars[20];

6 intodd=1,even=1;/*設置奇偶標志*/

7 inti=0;

8

9 printf("enteranumber:");

10 gets(s);/*輸入字符串到s數(shù)組*/

11 while(s[i]!='\0')/*'\0'為字符串的結束標志*/

12 {

13 if((s[i]-'0')%2==0)

14 {

15 odd=0;

/*按位判奇偶*/

16 }

17 else

18 {

19 even=0;

20 }

21 i++;

22 }

23 if(odd==1||even==1)

24 {

25 printf("YES!");

26 }

27 else

28 {

29 printf("NO!");

30 }

31 return0;

32 }

圖4.28~圖4.34所示分別為例4-8的調試步驟1~調試步驟7。調試要點:

·字符數(shù)組的查看;

·表達式的查看方法;

·單步跟蹤時程序窗口和控制臺窗口數(shù)據(jù)輸入的配合問題。

調試思路:跟蹤過程即是設計思路的驗證過程。

圖4.28顯示了程序執(zhí)行至gets(s)處的情形。

圖4.28例4-8調試步驟1注意:單步跟蹤時,當語句指示箭頭指向需要從控制臺窗口輸入數(shù)據(jù)的函數(shù)gets時(scanf、getchar、gets等都一樣),此時再按F10鍵,程序也不會往下執(zhí)行。這時,需要打開控制臺窗口,輸入gets所要求的數(shù)據(jù)并回車(如圖4.29所示),系統(tǒng)才會跳轉到程序界面。

圖4.29例4-8調試步驟2圖4.30中,注意gets(s)中輸入的字符串和chars[20]=

“12345”

的區(qū)別,s初始化的結果是元素s[5]后的所有元素值都是‘\0’,而gets(s)只是s[5]為‘\0’。

直接在Name欄中輸入表達式,其值就會顯示在Value欄中,如圖4.31所示。

首次循環(huán),

i=0,s[i]='1',s[i]-'0'=1

根據(jù)表達式s[i]-'0'=1,可以預計語句elseeven=0將被執(zhí)行。

圖4.30例4-8調試步驟3

圖4.31例4-8調試步驟4圖4.32中顯示了even=0被執(zhí)行的情形。如果顯示的結果和我們預計的一致,則程序的邏輯就是正確的,反之,則有邏輯錯誤。程序跟蹤調試的過程,也就是一個不斷驗證設計思路和實際執(zhí)行結果是否吻合的過程。

圖4.32例4-8調試步驟5圖4.33所示為首次循環(huán)結束后的情形,此時循環(huán)增量i加1,即變?yōu)?。

圖4.33例4-8調試步驟6圖4.34中,當i=5,s[i]=0時,不滿足循環(huán)條件,循環(huán)結束。此時,odd和even標志均為0,所以將輸出“No!”。

圖4.34例4-8調試步驟7

VC6.0使用的漢字是以什么方式存儲的?

我們在Watch窗口中看到有漢字“燙燙”顯示,而在相關數(shù)組元素中卻是一個整數(shù)-52,這個數(shù)字和漢字“燙”有什么關系呢?

答:我們可以做如下測試。

intmain()

{

chara[]="你好Hello123";

printf("%s",a);

return0;

}圖4.35所示為在a數(shù)組未賦值時各數(shù)組元素的內容,a[i]值是以十進制形式顯示的。整數(shù)-52是否就是漢字“燙”的編碼?只由這一個數(shù)據(jù)還不能得出結論。

圖4.36是把字符串"你好Hello123"賦值給數(shù)組a后的情形。

圖4.35漢字問題1

圖4.36漢字問題2現(xiàn)在的問題是要找出漢字和數(shù)組元素的對應關系。我們已經(jīng)知道字母和數(shù)字的ASCII碼是占一個字節(jié)(8

bit),如a[4]=72,是字母'H'的ASCII碼,根據(jù)上面字符串的存儲順序,a[0]、a[1]兩個字節(jié)存放了漢字“你”的編碼,a[2]、a[3]兩個字節(jié)存放了漢字“好”的編碼,故一個漢字占用兩個字節(jié)的內存單元。

在圖4.37中查看a數(shù)組的內容,memory是以單字節(jié)十六進制的形式顯示的:

“你”:0xC4E3

“好”:0xBAC3圖4.37漢字問題3通過與表4.27所示的數(shù)值對比,可以得知圖4.36中,a[0]=-60a[1]=-29,是系統(tǒng)把0xC4和0xE3當有符號數(shù)處理了。

表4.27數(shù)值對比通過和常用的幾種編碼字符集的信息比較,可以知道VC6.0所使用的漢字編碼是GBK編碼,參見圖4.38和圖4.39。

圖4.38GBK字符集“你”的編碼0xC4E3

圖4.39GBK字符集“好”的編碼0xBAC3

(1)通過Watch和Memory窗口可以查看我們感興趣的數(shù)據(jù),再從中找出它們的規(guī)律或聯(lián)系,從而得到我們想要的結果。

(2)程序跟蹤調試的過程,也就是一個不斷驗證設計思路和實際執(zhí)行結果是否吻合的過程。

VC環(huán)境使用的漢字編碼

·漢字存儲規(guī)則:每個漢字占用兩個字節(jié),即一個漢字占兩個char的空間。

·在VC6.0中漢字采用的是GBK編碼(漢字國標擴展碼)。

·GBK的文字編碼也是用雙字節(jié)來表示的,為了區(qū)分中文,將其最高位都設定成1。

·GBK總體編碼范圍為8140-FEFE,共收入漢字21003個。

【例4-9】字符數(shù)組的程序賦值。字符數(shù)組的程序賦值與多個輸入函數(shù)的輸入配合

問題。

1 /*字符數(shù)組的程序賦值*/

2 #include"stdio.h"

3 intmain()

4 {

5 charca[10];

6 charcb[10];

7 inti;

8

9 printf("請給ca輸入10個字符\n");

10 for(i=0;i<10;i++)

11 {

12 scanf("%c",&ca[i]);/*按%c格式讀入字符*/

13 }

14 printf("請給cb輸入10個字符");

15 gets(cb);/*讀取字符串,直至接收到換行符時停止*/

16 printf("\n");

17 printf("ca=%s",ca);/*以字符串形式輸出ca內容*/

18 printf("\n");

19 printf("cb=%s",cb);/*以字符串形式輸出cb內容*/

20 return0;

21 }

程序結果:

請給ca輸入10個字符

abcdefghij

請給cb輸入10個字符

ca=abcdefghij燙?

cb=

此程序運行時,會發(fā)現(xiàn),按程序提示的要求輸入信息并回車,則cb數(shù)組的信息總是無法輸入,這是什么原因呢?

答:這是鍵盤緩沖區(qū)數(shù)據(jù)殘留造成的問題。

從鍵盤輸入的內容存放在鍵盤緩沖區(qū)里。只有當收到Enter鍵信號時,scanf()、getchar()、gets()等輸入函數(shù)才開始從鍵盤緩沖區(qū)讀數(shù),未讀的數(shù)據(jù)則殘留在緩沖區(qū)內。就本程序而言,操作過程如下:

(1)顯示提示信息:“請給ca輸入10個字符”。

(2)鍵盤輸入信息:“abcdefghij<回車>”。

語句for(i=0;i<10;i++)scanf("%c",&ca[i])接收了前10個字符,那后面的gets函數(shù)接收到cb數(shù)組的是什么呢?查看一下,得知是系統(tǒng)自動添加的'\0',如圖4.40所示。所以,表面的現(xiàn)象是cb中沒有接收信息,程序就退出了。

圖4.40cb數(shù)組內容解決上述問題的方法有兩個。

方法一:把scanf和gets需要的數(shù)據(jù)一次性全部連續(xù)輸入后再回車,中間不要回車。

方法二:用fflush(stdin)可以清除掉鍵盤緩沖區(qū)中的殘留數(shù)據(jù)。

具體使用方法如下:

for(i=0;i<10;i++)scanf("%c",&ca[i]);

fflush(stdin);

gets(cb);

fflush(stdin);

說明:fflush(stdin)函數(shù)的功能是清空輸入緩沖區(qū),通常是為了確保不影響后面的數(shù)據(jù)讀取。例如,在讀完一

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論