Linux C single linked for any data type

/**************************************************************************
 *            Linux C single linked for any data type
 * 声明:
 *      提供一种单链接口,可以保存保存任何类型的数据,有时候这种需求在
 *  很多场合还是会用到的。
 *                  
 *                                  2015-7-5 晴 深圳 南山平山村 曾剑锋
 *************************************************************************/

                \\\\\\\\\-*- 目录 -*-/////////
                |  一、cat single_linked.h
                |  二、cat myerror.h
                |  三、cat single_linked.c
                |  四、cat main.c
                \\\\\\\\\\\\\\\//////////////

一、cat single_linked.h
    #ifndef __SINGLE_LINKED_H__
        #define __SINGLE_LINKED_H__
    
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        #include "myerror.h"
        
        typedef struct SINGLE_LINKED{
            void* datap;
            int size;
            struct SINGLE_LINKED* next;
        } single_linked;
    
        typedef void (*single_linked_print)(void* data);
        typedef int (*single_linked_delete)(void* data, void* linked_delete);
        /**
         * you should giving a vilid data dan size for save
         */
        int check_data_size(void *data, int size);
        /**
         * create a single linked header
         */
        single_linked* create_single_linked(void* data, int size);
        /**
         * add data to single linked at top
         */
        int top_add_single_linked(void* data, int size, single_linked* header);
        /**
         * add data to single linked at tail
         */
        int tail_add_single_linked(void* data, int size, single_linked* header);
        /**
         * delete data in single linked 
         */
        int delete_single_linked(void* data, single_linked* header, single_linked_delete func);
        /**
         * print all data in single linked
         */
        void print_single_linked(single_linked* header, single_linked_print func);
        /**
         * empty the single linked
         */
        void empty_single_linked(single_linked* header);
        /**
         * free all data in single linked
         */
        void free_single_linked(single_linked* header);
    #endif  //__SINGLE_LINKED_H__

二、cat myerror.h
    #ifndef  _MYERROR_H
    #define  _MYERROR_H
    
    // serial error     1
    // error           2
    // warning         3
    // information     4
    #define    DEBUG1(...)      fprintf(stderr,"SERI ERR: " __VA_ARGS__);
    #define    DEBUG2(...)      fprintf(stderr,"ERR: " __VA_ARGS__);
    #define    DEBUG3(...)      fprintf(stdout,"WARNING: " __VA_ARGS__);
    #define    DEBUG4(...)      fprintf(stdout,"INFORMATION: " __VA_ARGS__);
    #define    DEBUG()            fprintf(stdout,"\033[32mbug at func( %s ) : %d\033[0m\n", __func__, __LINE__);
    
    
    #define    ERR(lever ,con, ret , ...)                    \
               do                                        \
                {                                        \
                    if(con)                                \
                    {                                    \
                        DEBUG##lever(__VA_ARGS__)        \
                        ret;                            \
                    }                                    \
                }while(0)
    
    #endif  //_MYERROR_H

三、cat single_linked.c
    #include "single_linked.h"
    /**
     * create a single linked as header
     */
    single_linked* create_single_linked(void *data, int size){
        single_linked* header = malloc(sizeof(single_linked));
        ERR(1, NULL == header, goto err; "create single linked header fail.\n");
        header->next = NULL;
        header->datap = NULL;
        header->size = 0;
        
        if(check_data_size(data,size)){
            void* new_data = malloc(size);
            ERR(1, NULL == new_data, goto new_data_err; "create single linked header with data fail.\n");
            memcpy(new_data, data, size);
            header->size = size;
            header->datap = new_data;
        }
        return header;
    new_data_err:
        free(header);
    err:
        return NULL;
    }
    
    int check_data_size(void* data, int size){
        return ((data != NULL) && (size > 0));
    }
    
    int top_add_single_linked(void* data, int size, single_linked* header){
        ERR(1, NULL == header, return -1, "the header was NULL in top add single linked\n");
        single_linked* new_node = NULL;
    
        if(check_data_size(data, size)){
            single_linked* new_node = malloc(sizeof(single_linked));
            ERR(1, NULL == new_node, goto err; "top add malloc node fail.\n");
            new_node->next = NULL;
            new_node->datap = NULL;
            new_node->size = 0;
    
            void* new_data = malloc(size);
            ERR(1, NULL == new_data, goto err1; "top add malloc data fail.\n");
            memcpy(new_data, data, size);
            new_node->size = size;
            new_node->datap = new_data;
    
            new_node->next = header->next;
            /**
             * I had pazzled at this point with (header->next = new_node->next)
             */
            header->next = new_node;
            
        }   
        return 0;
    err1:
        free(new_node);
    err:
        return -1;
    }
    
    /**
     * add data to single linked at tail
     */
    int tail_add_single_linked(void* data, int size, single_linked* header){
        ERR(1, NULL == header, return -1, "the header was NULL in tail add single linked\n");
        single_linked* new_node = NULL;
    
        if(check_data_size(data, size)){
            single_linked* new_node = malloc(sizeof(single_linked));
            ERR(1, NULL == new_node, goto err; "top add malloc node fail.\n");
            new_node->next = NULL;
            new_node->datap = NULL;
            new_node->size = 0;
    
            void* new_data = malloc(size);
            ERR(1, NULL == new_data, goto err1; "top add malloc data fail.\n");
            memcpy(new_data, data, size);
            new_node->size = size;
            new_node->datap = new_data;
    
            //new_node->next = header->next;
            while(header->next)
                header = header->next;
            /**
             * I had pazzled at this point with (header->next = new_node->next)
             */
            header->next = new_node;
        }   
        return 0;
    err1:
        free(new_node);
    err:
        return -1;
    }
    
    /**
     * delete data in single linked 
     */
    int delete_single_linked(void* data, single_linked* header, single_linked_delete func){
        ERR(1, ((NULL == data) || (NULL == header) || (NULL == func)), return; "you shouldn't giving NULL for delete single linkde\n");
    
        single_linked* tmp = header->next;
        single_linked* pre = header;
        while(tmp){
            /**
             * you should giving a return value to decision delete this or not
             */
            if(func(data, tmp->datap)){
                pre->next = tmp->next;
                tmp->next = NULL;
                free(tmp->datap);
                free(tmp);
                tmp = pre->next;
            }else{
                pre = tmp;
                tmp = tmp->next;
            }
        }
        return 0;
    }
    
    /**
     * print all data in single linked
     */
    void print_single_linked(single_linked* header, single_linked_print func){
        ERR(1, ((NULL == header) || (NULL == func)), return; "you shouldn't giving NULL for print single linkde\n");
        single_linked* tmp = header->next;
        while(tmp){
            func(tmp);
            tmp = tmp->next;
        }
    }
    
    /**
     * free all data in single linked
     */
    void free_single_linked(single_linked* header){
        ERR(1, NULL == header, return; "free a header with NULL\n");
    
        single_linked* tmp = header->next;
        single_linked* pre = header->next;
        while(tmp){
            pre = tmp;
            tmp = tmp->next;
            free(pre->datap);
            free(pre);
        }
    
        if(header->datap != NULL){
            free(header->datap);
            header->datap = NULL;
        }
        header->next = NULL;
        free(header);
        header == NULL;
    }
    
    void empty_single_linked(single_linked* header){
        ERR(1, NULL == header, return, "empty header was NULL\n");
    
        single_linked* tmp = header->next;
        single_linked* pre = header->next;
        while(tmp){
            pre = tmp;
            tmp = tmp->next;
            free(pre->datap);
            free(pre);
        }
    
        if(header->datap != NULL){
            free(header->datap);
            header->datap = NULL;
        }
        header->next = NULL;
        header->size = 0;
    }

四、cat main.c
    #include "single_linked.h"
    
    #define NR(x) ((sizeof(x))/sizeof(x[0]))
    
    /**
     * test struct
     */
    typedef struct STUDENT{
        int id;
        int score;
    }student;
    
    /**
     * callback function
     */
    void print(void* data);
    int delete(void* data, void* linked_data);
    
    int main(int argc, char** argv){
        /**
         * demo data
         */
        student students[4] = {
            {1,1},
            {2,2},
            {2,2},
            {3,3},
        };
    
        single_linked* header = create_single_linked(NULL, 0);
    
        int i = 0;
        printf("--------------source------------------>\n");
        for(i = 0; i < NR(students); i++){
            printf("student: id = %d, score = %d \n", students[i].id, students[i].score);
        }
    
        printf("--------------tail add---------------->\n");
        for(i = 0; i < NR(students); i++){
            //top_add_single_linked(&students[i], sizeof(student), header);
            tail_add_single_linked(&students[i], sizeof(student), header);
        }
        print_single_linked(header, print);
    
        empty_single_linked(header);
    
        printf("--------------top add---------------->\n");
        for(i = 0; i < NR(students); i++){
            //top_add_single_linked(&students[i], sizeof(student), header);
            top_add_single_linked(&students[i], sizeof(student), header);
        }
        print_single_linked(header, print);
    
        printf("--------------delete---------------->\n");
        student stu = {2,2};
        delete_single_linked(&stu, header, delete);
        print_single_linked(header, print);
    
        printf("---------------free----------------->\n");
        free_single_linked(header);
    }
    
    void print(void* data){
        student* stu = (((single_linked*)data)->datap);
        printf("student: id = %d, score = %d \n", stu->id, stu->score);
    }
    
    int delete(void* data, void* linked_data){
        return (((student*)data)->id == ((student*)linked_data)->id) && (((student*)data)->score == ((student*)linked_data)->score); 
    }

 

posted on 2015-07-05 15:21  zengjf  阅读(300)  评论(0编辑  收藏  举报

导航