想結識更多新朋友嗎?想尋找你(妳)的另一半嗎?按此即開始完全免費.
☆ (按此) 最 新 遊 戲 得 分 及 勳 章 排 行 榜 ☆

 
標題: 【分享】C語言初學者入門講座 第十二講 多維陣列的指標變數
yslee
版主
Rank: 7Rank: 7Rank: 7



UID 0056761
精華 0
積分 372
帖子 131
威望 372
金錢 12283
存款 0
閱讀權限 250
註冊 18-4-2007
狀態 離線
 
發表於 18-4-2007 18:38  資料  個人空間  短消息  加為好友 
【分享】C語言初學者入門講座 第十二講 多維陣列的指標變數@ngchk.com E-Mail 此主題給朋友
【分享】C語言初學者入門講座 第十二講 多維陣列的指標變數


C語言初學者入門講座 第十二講 多維陣列的指標變數
 一、多維陣列位址的表示方法

  設有整型二維陣列a[3][4]如下:

  0 1 2 3
  4 5 6 7
  8 9 10 11

  設陣列a的首位址爲1000,各下標變數的首位址及其值如圖所示。  

在前面曾經介紹過, C語言允許把一個二維陣列分解爲多個一維陣列來處理。因此陣列a可分解爲三個一維陣列,即a[0],a[1],a[2]。每一個一維陣列又含有四個元素。例如a[0]陣列,含有a[0][0],a[0][1],a[0][2],a[0][3]四個元素。 陣列及陣列元素的位址表示如下:a是二維陣列名稱,也是二維陣列0行的首位址,等於1000。a[0]是第一個一維陣列的陣列名稱和首位址,因此也爲1000。*(a+0)或*a是與a[0]等效的, 它表示一維陣列a[0]0 號元素的首位址。 也爲1000。&a[0][0]是二維陣列a的0行0列元素首位址,同樣是1000。因此,a,a[0],*(a+0),*a,&a[0][0]是相等的。同理,a+1是二維陣列1行的首位址,等於1008。a[1]是第二個一維陣列的陣列名稱和首位址,因此也爲1008。 &a[1][0]是二維陣列a的1行0列元素位址,也是1008。因此a+1,a[1],*(a+1),&a[1][0]是等同的。 由此可得出:a+i,a,*(a+i),&a[0]是等同的。 此外,&a和a也是等同的。因爲在二維陣列中不能把&a理解爲元素a的位址,不存在元素a。

  C語言規定,它是一種位址計算方法,表示陣列a第i行首位址。由此,我們得出:a,&a,*(a+i)和a+i也都是等同的。另外,a[0]也可以看成是a[0]+0是一維陣列a[0]的0號元素的首位址, 而a[0]+1則是a[0]的1號元素首位址,由此可得出a+j則是一維陣列a的j號元素首位址,它等於&a[j]。由a=*(a+i)得a+j=*(a+i)+j,由於*(a+i)+j是二維陣列a的i行j列元素的首位址。該元素的值等於*(*(a+i)+j)。

[Explain]

#define PF "%d,%d,%d,%d,%d,\n"
main(){
static int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
printf(PF,a,*a,a[0],&a[0],&a[0][0]);
printf(PF,a+1,*(a+1),a[1],&a[1],&a[1][0]);
printf(PF,a+2,*(a+2),a[2],&a[2],&a[2][0]);
printf("%d,%d\n",a[1]+1,*(a+1)+1);
printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1));
}

  二、多維陣列的指標變數

  把二維陣列a 分解爲一維陣列a[0],a[1],a[2]之後,設p爲指向二維陣列的指標變數。可定義爲: int (*p)[4] 它表示p是一個指標變數,它指向二維陣列a 或指向第一個一維陣列a[0],其值等於a,a[0],或&a[0][0]等。而p+i則指向一維陣列a。從前面的分析可得出*(p+i)+j是二維陣列i行j 列的元素的位址,而*(*(p+i)+j)則是i行j列元素的值。

  二維陣列指標變數說明的一般形式爲: 類型說明符 (*指標變數名)[長度] 其中“類型說明符”爲所指數組的資料類型。“*”表示其後的變數是指標類型。 “長度”表示二維陣列分解爲多個一維陣列時, 一維陣列的長度,也就是二維陣列的列數。應注意“(*指標變數名)”兩邊的括弧不可少,如缺少括弧則表示是指標陣列(本章後面介紹),意義就完全不同了。

[Explain]

main(){
static int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
int(*p)[4];
int i,j;
p=a;
for(i=0;i<3;i++)
for(j=0;j<4;j++) printf("%2d ",*(*(p+i)+j));
}

  'Expain字串指標變數的說明和使用字串指標變數的定義說明與指向字元變數的指標變數說明是相同的。只能按對指標變數的賦值不同來區別。 對指向字元變數的指標變數應賦予該字元變數的位址。如: char c,*p=&c;表示p是一個指向字元變數c的指標變數。而: char *s="C Language";則表示s是一個指向字串的指標變數。把字串的首位址賦予s。

  請看下面一例。

main(){
char *ps;
ps="C Language";
printf("%s",ps);
}

  運行結果爲:

  C Language

  上例中,首先定義ps是一個字元指標變數, 然後把字串的首位址賦予ps(應寫出整個字串,以便編譯系統把該串裝入連續的一塊記憶體單元),並把首位址送入ps。程式中的: char *ps;ps="C Language";等效於: char *ps="C Language";輸出字串中n個字元後的所有字元。

main(){
char *ps="this is a book";
int n=10;
ps=ps+n;
printf("%s\n",ps);
}

  運行結果爲:

  book 在程式中對ps初始化時,即把字串首位址賦予ps,當ps= ps+10之後,ps指向字元“b”,因此輸出爲"book"。

main(){
char st[20],*ps;
int i;
printf("input a string:\n");
ps=st;
scanf("%s",ps);
for(i=0;ps!='\0';i++)
if(ps=='k'){
printf("there is a 'k' in the string\n");
break;
}
if(ps=='\0') printf("There is no 'k' in the string\n");
}

  本例是在輸入的字串中查找有無‘k’字元。 下面這個例子是將指標變數指向一個格式字串,用在printf函數中,用於輸出二維陣列的各種位址表示的值。但在printf語句中用指標變數PF代替了格式串。 這也是程式中常用的方法。

main(){
static int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
char *PF;
PF="%d,%d,%d,%d,%d\n";
printf(PF,a,*a,a[0],&a[0],&a[0][0]);
printf(PF,a+1,*(a+1),a[1],&a[1],&a[1][0]);
printf(PF,a+2,*(a+2),a[2],&a[2],&a[2][0]);
printf("%d,%d\n",a[1]+1,*(a+1)+1);
printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1));
}

  在下例是講解,把字串指標作爲函數參數的使用。要求把一個字串的內容複製到另一個字串中,並且不能使用strcpy函數。函數cprstr的形參爲兩個字元指標變數。pss指向源字串,pds指向目標字串。運算式:

(*pds=*pss)!=`\0'
cpystr(char *pss,char *pds){
while((*pds=*pss)!='\0'){
pds++;
pss++; }
}
main(){
char *pa="CHINA",b[10],*pb;
pb=b;
cpystr(pa,pb);
printf("string a=%s\nstring b=%s\n",pa,pb);
}  

  在上例中,程式完成了兩項工作:一是把pss指向的源字元複製到pds所指向的目標字元中,二是判斷所複製的字元是否爲`\0',若是則表明源字串結束,不再迴圈。否則,pds和pss都加1,指向下一字元。在主函數中,以指標變數pa,pb爲實參,分別取得確定值後調用cprstr函數。由於採用的指標變數pa和pss,pb和pds均指向同一字串,因此在主函數和cprstr函數中均可使用這些字串。也可以把cprstr函數簡化爲以下形式:

cprstr(char *pss,char*pds)
{while ((*pds++=*pss++)!=`\0');}

  即把指標的移動和賦值合併在一個語句中。 進一步分析還可發現`\0'的ASCⅡ碼爲0,對於while語句只看運算式的值爲非0就迴圈,爲0則結束迴圈,因此也可省去“!=`\0'”這一判斷部分,而寫爲以下形式:

cprstr (char *pss,char *pds)
{while (*pdss++=*pss++);}  

  運算式的意義可解釋爲,源字元向目標字元賦值, 移動指標,若所賦值爲非0則迴圈,否則結束迴圈。這樣使程式更加簡潔。簡化後的程式如下所示。

cpystr(char *pss,char *pds){
while(*pds++=*pss++);
}
main(){
char *pa="CHINA",b[10],*pb;
pb=b;
cpystr(pa,pb);
printf("string a=%s\nstring b=%s\n",pa,pb);
}

  使用字串指標變數與字元陣列的區別

  用字元陣列和字元指標變數都可實現字串的存儲和運算。 但是兩者是有區別的。在使用時應注意以下幾個問題:

  1. 字串指標變數本身是一個變數,用於存放字串的首位址。而字串本身是存放在以該首位址爲首的一塊連續的記憶體空間中並以‘\0’作爲串的結束。字元陣列是由於若干個陣列元素組成的,它可用來存放整個字串。

  2. 對字元陣列作初始化賦值,必須採用外部類型或靜態類型,如: static char st[]={“C Language”};而對字串指標變數則無此限制,如: char *ps="C Language";

  3. 對字串指標方式 char *ps="C Language";可以寫爲: char *ps; ps="C Language";而對陣列方式:

static char st[]={"C Language"};

  不能寫爲:

char st[20];st={"C Language"};

  而只能對字元陣列的各元素逐個賦值。

  從以上幾點可以看出字串指標變數與字元陣列在使用時的區別,同時也可看出使用指標變數更加方便。前面說過,當一個指標變數在未取得確定位址前使用是危險的,容易引起錯誤。但是對指標變數直接賦值是可以的。因爲C系統對指標變數賦值時要給以確定的位址。因此,

char *ps="C Langage";

  或者

char *ps;
ps="C Language";

  都是合法的。

頂部
[廣告]
 



當前時區 GMT+8, 現在時間是 21-11-2008 00:58

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz!  © 2001-2009 Comsenz Inc.
Processed in 0.038054 second(s), 6 queries , Gzip enabled

清除 Cookies - 聯繫我們 - 使用條款/免責聲明 - Archiver - WAP
重要聲明:本討論區是以即時上載留言的方式運作,NGC 香港討論區 對所有留言的真實性、完整性及立場等,不負任何 法律責任。而一切留言之言論只代表留言者個人意見,並非本網站之立場,用戶不應信賴內容,並應自行判斷內容之真實性。於有關情形下,用戶應尋求專業意見 (如涉及醫療、法律或投資等問題)。 由於本討論區受到「即時上載留言」運作方式所規限,故不能完全監察所有留言,若讀者發現有留言出現問題,請聯絡我們。NGC 香港討論區 有權刪除任何留言及拒絕任何人士上載留言,同時亦有不刪除留言的權利。切勿撰寫粗言穢語、誹謗、渲染色情暴力或人身攻擊的言論,敬請自律。本網站保留一切法律權利。