如下例定義了一個結構 list ,其中有一個成員宣告為指向 list 的指標
#include <stdio.h> struct list { char *name; struct list *nextPtr; }; typedef struct list List; int main(void) { List a, b, c, *startPtr; a.name = "John"; b.name = "Mary"; c.name = "Tony"; startPtr = &a; a.nextPtr = &b; b.nextPtr = &c; c.nextPtr = NULL; while (startPtr != NULL) { printf("%s\n", startPtr->name); startPtr = startPtr->nextPtr; } return 0; } /* 《程式語言教學誌》的範例程式 http://pydoing.blogspot.com/ 檔名:structlist.c 功能:示範自我參考的結構 作者:張凱慶 時間:西元2010年4月 */
編譯後執行,結果如下
第 12 行
List a, b, c, *startPtr;
我們分別宣告了三個 List 型態的結構,另外一個指向 List 型態的指標。
接下來從第 14 行到第 16 行
a.name = "John"; b.name = "Mary"; c.name = "Tony";
各自替三個 List 型態結構的成員 name 給值,然後第 18 行
startPtr = &a;
將 a 的位址指派給額外宣告的指標 startPtr ,這是說我們將 a 作為此資料結構的起始點,同時利用額外的指標進行操作。因為從指標可以輕易的取所指向結構的成員,指標也可以當成控制變數,因而使用指標得以容易遊走在資料結構中。
List 型態結構的另一個成員 nextPtr ,便是指向下一筆資料項目的位址。第 19 到第 21 行
a.nextPtr = &b; b.nextPtr = &c; c.nextPtr = NULL;
此例中,我們把 a 當成第一筆資料,也就是資料結構的起始項目, b 是第二筆資料, c 為第三筆資料,因此 a 的 nextPtr 指向 b 的位址,而 b 的 nextPtr 指向 c 。由於 c 為最後一筆資料,我們將 c 的 nextPtr 設為 NULL , NULL 是 C 語言標準函數庫所定義的一個特別的值,代表無效的指標。
第 23 到第 26 行
while (startPtr != NULL) { printf("%s\n", startPtr->name); startPtr = startPtr->nextPtr; }
我們使用了一個迴圈,這個迴圈的結束條件為 startPtr 等於 NULL 。此迴圈的任務為印出指標所指向結構的 name 成員,然後把 startPtr 重新指派給所指向結構的 nextPtr 成員。
由於 startPtr 最初的值為 a 的位址,所以第一次進入迴圈會印出 a 的 name 成員,同時 a 的 nextPtr 成員的值會重新指派給 startPtr 。我們之前是將 a 的 nextPtr 設定成 b 的位址,所以第二次進入迴圈時, startPtr 指向的是 b ,之後的動作皆可類推。
這樣的資料結構稱之為鍵結串列 (linked list) ,所有的資料可以分開儲存在不同非連續的記憶體位址。需留意一點,我們用一個簡單的方式說明 C 語言的結構與指標的一般應用,而非建立實際可有效運用的資料結構。
沒有留言:
張貼留言