2009年8月25日 星期二

實作偽 GLib Singly-Linked Lists

Standard
這些日子以來真的被 GLib 給寵壞,它將什麼東西都包成漂亮的 API,讓人用的很開心。但是在許多環境下,像是有限資源的 Embedded System 之中或是在單純的 DOS 裡,想要使用 GLib 可是難上加難,因此免不了要自己實作同樣的功能。而其中最常見的功能莫過於 Linked-list,雖然觀念和方法在所謂的『資料結構』教課本中有如『解數學的聯立方程式』一般被講到爛,但真要一步步做起來也不免覺得麻煩,於是空閒之於就寫好放著,以後 Copy & Paste 就好了。 :-)

既然已經很熟悉 GLib 的 API,就乾脆實作出一模一樣,也方便記憶和使用。
/*  Singly-Linked Lists structure */
struct Myslist_ {
void *data;
struct Myslist *next;
};
typedef struct Myslist_ Myslist;

/* marco */
#define myslist_next(list) (list->next);

Myslist *myslist_prepend(Myslist *list, void *data)
{
Myslist *new;

new = (Myslist *)malloc(sizeof(Myslist));
new->data = data;
new->next = list;

return new;
}
然後可以這樣使用,修改自舊文『Glib 就是懶.資料處理好手 - GList 雙向鏈結(Doubly-Linked)』:
typedef struct {
char *name;
char *tel;
} ContactNode;

int main() {
Myslist *contactlist = NULL;
Myslist *list = NULL;
ContactNode *node;

/* Fred's contact information */
node = (ContactNode *)malloc(sizeof(ContactNode));
node->name = strdup("Fred Chien");
node->tel = strdup("0926333xxx");

/* add the node to the list */
contactlist = myslist_preppend(contactlist, node);

/* Penx contact information */
node = (ContactNode *)malloc(sizeof(ContactNode));
node->name = strdup("Penx");
node->tel = strdup("09xxxxxxxx");

/* add the node to the list */
contactlist = myslist_preppend(contactlist, node);

/* print all of list */
for (list=contactlist;list;list=myslist_next(list)) {
node = (ContactNode *)list->data;

printf("Name: %s, Tel:%s\n", node->name, node->tel);
}

return 0;