#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <assert.h> #define LIST_DATA_FILENAME "list.data" //-------------------------------------------------------------------- // Type definition //-------------------------------------------------------------------- typedef struct list_node { int value; char c; // you can define other variables here! struct list_node *prev; struct list_node *next; } list_node_t; typedef struct { list_node_t *list_head; list_node_t *list_tail; } list_t; //-------------------------------------------------------------------- // Function prototype //-------------------------------------------------------------------- list_t *create_list(void); void release_list(list_t * list_p); list_node_t *list_create_node(int value, char c); void list_release_node(list_node_t * node_p); list_node_t *list_locate(list_t * list_p, int value, char c); int list_insert_before_node(list_t * list_p, list_node_t * node_p, int value, char ch); int list_insert_after_node(list_t * list_p, list_node_t * p, int value, char c); int list_insert_first(list_t * list_p, int value, char c); int list_insert_last(list_t * list_p, int value, char c); void list_delete_first_node(list_t * list_p); int list_delete_last_node(list_t * list_p); int list_delete_node(list_t * list_p, list_node_t * node_p); int list_delete(list_t * list_p, int value, char c); void list_print_node(list_node_t * p); void list_print_all(list_t * list_p); int list_get_length(list_t * list_p); void list_modify_node(list_t * list_p, int value, char c, int new_value, char new_c); int list_save_to_file(list_t * list_p, const char *filename); int list_load_from_file(list_t * list_p, const char *filename); void list_make_circle(list_t * list_p); //-------------------------------------------------------------------- // Main function //-------------------------------------------------------------------- int main(int argc, char **argv) { list_t *list1 = NULL; //------------------------------------------------------------------ // Create a empty list //------------------------------------------------------------------ list1 = create_list(); list_print_all(list1); //list_insert_after_node(list1, list1->list_head, 77, 'z'); list_insert_before_node(list1, list1->list_head, 77, 'z'); list_print_all(list1); list_insert_first(list1, 1, 'x'); list_print_all(list1); list_insert_after_node(list1, list1->list_head, 78, 'y'); list_insert_after_node(list1, list1->list_head, 100, 'a'); list_print_all(list1); list_node_t *p = list_locate(list1, 100, 'a'); list_print_node(p); //------------------------------------------------------------------ // Insert 2 nodes after node(100, 'a') //------------------------------------------------------------------ list_insert_after_node(list1, p, 101, 'b'); list_insert_after_node(list1, p, 102, 'c'); list_print_all(list1); fprintf(stdout, "\n---------- insert before node(%d, '%c') ----------\n", p->value, p->c); list_insert_before_node(list1, p, 99, 'w'); list_print_all(list1); list_delete_last_node(list1); list_delete_last_node(list1); list_delete_last_node(list1); list_delete_last_node(list1); list_delete_last_node(list1); list_print_all(list1); fprintf(stdout, "\n---------- delete node(%d, '%c') ----------\n", 1, 'x'); list_delete(list1, 1, 'x'); list_print_all(list1); fprintf(stdout, "\n---------- insert first ----------\n"); list_insert_first(list1, 2, 'm'); // result: 2, 'm' -> 99, 'w' -> ... list_insert_first(list1, 3, 'n'); // result: 3, 'n' -> 2, 'm' -> 99, 'w' -> ... list_insert_first(list1, 4, 'o'); // result: 4, 'o' -> 3, 'n' -> 2, 'm' -> ... list_print_all(list1); fprintf(stdout, "\n---------- insert last ----------\n"); list_insert_last(list1, 5, 'u'); // result: ... -> 101, 'b' -> 5, 'u' -> NULL list_insert_last(list1, 6, 'v'); // result: ... -> 101, 'b' -> 5, 'u' -> 6, 'v' -> NULL list_insert_last(list1, 7, 's'); // result: ... -> 101, 'b' -> 5' 'u' -> 6, 'v' -> 7, 's' -> NULL list_print_all(list1); fprintf(stdout, "\n---------- save & load list ----------\n"); list_save_to_file(list1, LIST_DATA_FILENAME); list_t *list2 = create_list(); list_load_from_file(list2, LIST_DATA_FILENAME); list_print_all(list2); fprintf(stdout, "\n---------- release list2 ----------\n"); release_list(list2); fprintf(stdout, "\n---------- release list1 ----------\n"); release_list(list1); fprintf(stdout, "\n---------- finished ----------\n"); return 0; } list_node_t *list_create_node(int value, char c) { list_node_t *p = malloc(sizeof(list_node_t)); if (!p) { fprintf(stderr, "Allist_locate memory for new node failed.\n"); return NULL; } p->value = value; p->c = c; p->prev = NULL; p->next = NULL; return p; } void list_release_node(list_node_t * node_p) { if (node_p) { // free dynamic allocated resources. free(node_p); } } void list_print_node(list_node_t * node_p) { fprintf(stdout, "p: %8p, value = %8d, char = '%4c', next = %8p, prev = %8p\n", node_p, node_p->value, node_p->c, node_p->next, node_p->prev); } void list_print_all(list_t * list_p) { fprintf(stdout, "\n\n##### Calling %s:%d:%s() ...\n", __FILE__, __LINE__, __func__); fprintf(stdout, "list: %p, list->list_head: %p, list->list_tail: %p\n", list_p, list_p->list_head, list_p->list_tail); list_node_t *p; p = list_p->list_head; while (p) { //fprintf(stdout, "p: %p, value = %d, char = %c, next = %p\n", p, p->value, p->c, p->next); list_print_node(p); p = p->next; if (p == list_p->list_head) { break; } } fprintf(stdout, "##### Leaving from %s:%d:%s() ...\n\n", __FILE__, __LINE__, __func__); } void list_print_all_another(list_t * list_p) { fprintf(stdout, "\n\n##### Calling %s:%d:%s() ...\n", __FILE__, __LINE__, __func__); fprintf(stdout, "list: %p, list->list_head: %p, list->list_tail: %p\n", list_p, list_p->list_head, list_p->list_tail); if (!list_p->list_head) { assert(!list_p->list_tail); return; } list_node_t *p = list_p->list_head; while (p != list_p->list_tail) { //fprintf(stdout, "p: %p, value = %d, char = %c, next = %p\n", p, p->value, p->c, p->next); list_print_node(p); p = p->next; } list_print_node(list_p->list_tail); fprintf(stdout, "##### Leaving from %s:%d:%s() ...\n\n", __FILE__, __LINE__, __func__); } list_node_t *list_locate(list_t * list_p, int value, char c) { list_node_t *p = list_p->list_head; while (p) { if (p->value == value && p->c == c) { // found it! fprintf(stdout, "%s:%d:%s(%d, '%c'): found!\n", __FILE__, __LINE__, __func__, value, c); break; } p = p->next; if (p == list_p->list_head) { p = NULL; } } if (p == NULL) { fprintf(stdout, "%s:%d:%s(%d, '%c'): not found!\n", __FILE__, __LINE__, __func__, value, c); } return p; } int list_insert_first(list_t * list_p, int value, char c) { list_insert_before_node(list_p, list_p->list_head, value, c); return 0; } int list_insert_last(list_t * list_p, int value, char c) { list_insert_after_node(list_p, list_p->list_tail, value, c); return 0; } int list_insert_before_node(list_t * list_p, list_node_t * node_p, int value, char ch) { list_node_t *new_node = list_create_node(value, ch); if (!new_node) { fprintf(stderr, "Create new node failed.\n"); return -1; } if (list_p->list_head == NULL) { list_p->list_head = new_node; list_p->list_tail = new_node; list_make_circle(list_p); return 0; } new_node->next = node_p; new_node->prev = node_p->prev; node_p->prev->next = new_node; node_p->prev = new_node; if (list_p->list_head == node_p) { list_p->list_head = node_p->prev; } list_make_circle(list_p); return 0; } int list_insert_after_node(list_t * list_p, list_node_t * node_p, int value, char c) { // create new_node list_node_t *new_node = list_create_node(value, c); if (!new_node) { fprintf(stderr, "Create new list_node object failed.\n"); return -1; } if (list_p->list_head == NULL) { list_p->list_head = new_node; list_p->list_tail = new_node; list_make_circle(list_p); return 0; } new_node->next = node_p->next; new_node->prev = node_p; node_p->next->prev = new_node; node_p->next = new_node; if (node_p == list_p->list_tail) { list_p->list_tail = node_p->next; } list_make_circle(list_p); return 0; } int list_get_length(list_t * list_p) { int length = 0; list_node_t *p = list_p->list_head; while (p) { length++; p = p->next; if (p == list_p->list_head) { break; } } return length; } void list_modify_node(list_t * list_p, int value, char c, int new_value, char new_c) { //list_node_t *list_locate(list_t * list_p, int value, char c); list_node_t *node_p = list_locate(list_p, value, c); if (node_p) { node_p->value = new_value; node_p->c = new_c; fprintf(stdout, "Modify node %p successfully.\n", node_p); } else { fprintf(stderr, "Cannot locate node(%d, '%c'), failed.\n", value, c); } } void list_delete_first_node(list_t * list_p) { list_delete_node(list_p, list_p->list_head); } int list_delete_last_node(list_t * list_p) { list_delete_node(list_p, list_p->list_tail); return 0; } int list_delete(list_t * list_p, int value, char c) { list_node_t *node_p = list_locate(list_p, value, c); if (!node_p) { fprintf(stderr, "%s:%d:%s(): Cannot locate target node(%d, '%c'), give up.\n", __FILE__, __LINE__, __func__, value, c); return -1; } list_delete_node(list_p, node_p); return 0; } int list_delete_node(list_t * list_p, list_node_t * node_p) { fprintf(stdout, "%s:%d:%s(): deleting node(%d, '%c') ...\n", __FILE__, __LINE__, __func__, node_p->value, node_p->c); if (!list_p->list_head) { assert(!list_p->list_tail); fprintf(stdout, "Empty list.\n"); return -1; } if (list_p->list_head == list_p->list_tail) { // only one node fprintf(stdout, "Free only node.\n"); free(node_p); list_p->list_head = NULL; list_p->list_tail = NULL; } node_p->prev->next = node_p->next; node_p->next->prev = node_p->prev; if (node_p == list_p->list_head) { list_p->list_head = node_p->next; } if (node_p == list_p->list_tail) { list_p->list_tail = node_p->prev; } free(node_p); list_make_circle(list_p); return 0; } //-------------------------------------------------------------------- // save_to_file & load_from_list //-------------------------------------------------------------------- int list_save_to_file(list_t * list_p, const char *filename) { fprintf(stdout, "\n\n##### Calling %s:%d:%s() ...\n", __FILE__, __LINE__, __func__); FILE *fp = fopen(filename, "wb"); if (fp == NULL) { fprintf(stderr, "Open data file %s failed: %s\n", filename, strerror(errno)); return -1; } list_node_t *p = list_p->list_head; while (p) { //size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE * stream); fwrite(p, sizeof(list_node_t), 1, fp); p = p->next; if (p == list_p->list_head) { break; } } fflush(fp); fclose(fp); fprintf(stdout, "##### Leaving from %s:%d:%s() ...\n\n", __FILE__, __LINE__, __func__); return 0; } int list_load_from_file(list_t * list_p, const char *filename) { fprintf(stdout, "\n\n##### Calling %s:%d:%s() ...\n", __FILE__, __LINE__, __func__); FILE *fp = fopen(filename, "rb"); if (fp == NULL) { fprintf(stderr, "Open list data file %s failed: %s\n", filename, strerror(errno)); return -1; } while (1) { list_node_t new_node; size_t n; //size_t fread(void *ptr, size_t size, size_t nmemb, FILE * stream); n = fread(&new_node, sizeof(list_node_t), 1, fp); if (n < 1) { if (feof(fp)) { // reach end-of-file break; } else { // error occur break; } } else { list_insert_last(list_p, new_node.value, new_node.c); } } fclose(fp); fprintf(stdout, "##### Leaving from %s:%d:%s() ...\n\n", __FILE__, __LINE__, __func__); return 0; } //-------------------------------------------------------------------- // list management functions //-------------------------------------------------------------------- list_t *create_list(void) { list_t *p = malloc(sizeof(list_t)); if (!p) { fprintf(stderr, "Create new list failed.\n"); return NULL; } p->list_head = NULL; p->list_tail = NULL; return p; } void release_list(list_t * list_p) { list_node_t *p = list_p->list_head; while (p) { list_node_t *current = p; p = p->next; fprintf(stdout, "Release node: "); list_print_node(current); free(current); if (p == list_p->list_head) { break; } } free(list_p); } void list_make_circle(list_t * list_p) { //list_print_all(list_p); if (list_p->list_head) { assert(list_p->list_tail); list_p->list_tail->next = list_p->list_head; list_p->list_head->prev = list_p->list_tail; } } // vim: tabstop=8