1. 程式人生 > >contiki之list(2)

contiki之list(2)

有了list(1)的分析,list.c檔案接下來的函式都好說了 /*********************************list.c*******************************/ 值得注意的是,list.c裡傳入函式的引數裡,都是list_t型別,也就是說是指向連結串列頭指標的指標。 void list_init(list_t list) { *list = NULL; } 通俗易懂,也就是說把指向連結串列頭的指標賦值為NULL void * list_head(list_t list) { return *list; } 返回連結串列的頭指標 void list_copy(list_t dest, list_t src) { *dest = *src; } 複製連結串列,可以看到只是把連結串列頭指標賦值給另外一個指標而已。 void * list_tail(list_t list)
{ struct list *l; if(*list == NULL) { return NULL; } for(l = *list; l->next != NULL; l = l->next); return l; } 找到連結串列的尾,並返回指向該單元的指標。先判斷指向連結串列頭的指標是不是空,如果不是空,注意了,這個時候連結串列頭指標指向的將是一個帶有具體資料的結構體,該結構體第一個成員是next。還記得list(1)講的麼,因為我們在函式裡把指向這個結構體的指標強轉成struct list*,所以就算原來的結構體除了next成員還有其他資料結構,我們還是隻能訪問到next成員而已。接下來的for迴圈,就是常規的鏈式檢索,找到一個連結串列成員,它的next變數是NULL的既是尾了。只要把這個函式返回的指標用原來帶有資料的結構體型別強轉解引用就可以正常訪問裡面的資料了。 void list_push(list_t list, void *item)
{ /* struct list *l;*/ /* Make sure not to add the same element twice */ list_remove(list, item); ((struct list *)item)->next = *list; *list = item; } 這個函式把新加入的成員放在連結串列頭。 void * list_chop(list_t list) { struct list *l, *r; if(*list == NULL) {
return NULL; } if(((struct list *)*list)->next == NULL) { l = *list; *list = NULL; return l; } for(l = *list; l->next->next != NULL; l = l->next); r = l->next; l->next = NULL; return r; } 這個函式返回指向連結串列最後一個成員的指標,並把最後一個成員從連結串列裡剔除。 if(((struct list *)*list)->next == NULL)這句是為了判斷這個連結串列是不是才只有一個成員而已。如果才一個成員,那麼剔除最後一個成員後就得讓指向連結串列頭的指標變成NULL for(l = *list; l->next->next != NULL; l = l->next);這句執行完I將是指向倒數第二個成員的指標。 void * list_pop(list_t list) { struct list *l; l = *list; if(*list != NULL) { *list = ((struct list *)*list)->next; } return l; } 這個函式返回指向連結串列第一個成員的指標,並把第一個成員從連結串列裡剔除。 void list_remove(list_t list, void *item) { struct list *l, *r; if(*list == NULL) { return; } r = NULL; for(l = *list; l != NULL; l = l->next) { if(l == item) { if(r == NULL) { /* First on list */ *list = l->next; } else { /* Not first on list */ r->next = l->next; } l->next = NULL; return; } r = l; }///end of for } 這個函式從連結串列裡找到給定的成員,把它從連結串列裡剔除。r變數是為了儲存上一次for迴圈指向的成員。這樣子當找到給定的成員的是,我們可以這個成員的前面一個成員,即r的next指向給定成員的下一個成員,為了安全把找到的給定成員的next變數設定為NULL然後return int list_length(list_t list) { struct list *l; int n = 0; for(l = *list; l != NULL; l = l->next) { ++n; } return n; } 這個就簡單了,數一數連結串列裡總共有多少個成員 void list_insert(list_t list, void *previtem, void *newitem) { if(previtem == NULL) { list_push(list, newitem); } else { ((struct list *)newitem)->next = ((struct list *)previtem)->next; ((struct list *)previtem)->next = newitem; } } 這個函式也很簡單,在把新成員newitem插入到指定成員previtem後面。如果指定成員是NULL,則插入到連結串列頭 void * list_item_next(void *item) { return item == NULL? NULL: ((struct list *)item)->next; } 最後一個函式,返回給定成員的下一個成員指標。