您的位置:首页 > 编程语言 > C语言/C++

C语言实现一个泛型容器

2015-06-07 00:36 417 查看
用C语言实现一个容器,可以装字符串、字符、数字、二进制数据, 其中每一个被装进的数据要附带一个唯一识别码( uid )。
int put_char(List *list,  unsigned int uid, char c);
int put_string(List *list, unsigned int uid, char *str);
int put_integer(List *list, unsigned int uid, int num);
int put_binary(List *list, unsigned int uid, unsigned char* data, unsigned int data_len);


能遍历容器内数据节点,根据uid删除节点,打印节点。
unsigned int getNodeNum(List *list);
int delete_node(List *list, unsigned int uid);
int print_node(List *list, unsigned int uid);
void delete_all_nodes(List *list);


    我的解决方案:使用单链表,结构体里定义各数据类型,用一个标志位来标记数据类型,可以实现每个节点都能具有任意数据类型。

/**
 ******************************************************************************
  * @file    list.h
  * @author  summer
  * @version V1.0
  * @date    2015-05-25
  * @brief   C语言实现一个泛型容器
*           函数声明,功能注释在.c文件中。
  ******************************************************************************
  * @attention
  * IDE:      Visual Studio 2010
  * 
  ******************************************************************************
*/
#ifndef _LIST_H
#define _LIST_H
#define IS_INT  1
#define IS_CHAR 2
#define IS_STR  3
#define IS_BIN  4

#define FALSE   0
#define TRUE    1

typedef struct LIST
{
struct LIST *link;
unsigned int uid;
int          int_value;
char         char_value;
unsigned int mark; // mark来标记类型 IS_INT  1, IS_CHAR 2, IS_STR  3, IS_BIN  4
char         str[100];
}List;

List *create();

int search_node(List *list, unsigned int uid );

int put_char(List *list,  unsigned int uid, char c);
int put_string(List *list, unsigned int uid, const char *str);
int put_integer(List *list, unsigned int uid, int num);
int put_binary(List *list, unsigned int uid, const char* data, unsigned int data_len);

int print_list(List *list, unsigned int uid);
unsigned int getlistNum(List *list);
int delete_list(List *list, unsigned int uid);
void delete_all_nodes(List *list);

#endif

/**
******************************************************************************
* @file list.c
* @author summer
* @version V1.0
* @date 2015-05-25
* @brief C语言实现一个泛型容器
*          具体实现
******************************************************************************
* @attention
* IDE:      Visual Studio 2010
*
******************************************************************************
*/

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<assert.h>

#include"list.h"

/**
*创建链表
*/
List *create()
{
List *_list = (List *)malloc(sizeof(List));     // 分配一个不存放有效数据的头结点
List *_tail = _list;                            // 链表的最后一个节点
_tail->link = NULL;                             // 最后一个节点的指针置为空
int i;
for(i = 0; i < 2; i++)
{
List *pNew = (List *)malloc( sizeof(List) );// 为节点分配空间
pNew->int_value = i;                        // 数据赋给节点的成员
pNew->mark      = IS_INT;                   // 标记数据类型
_tail->link     = pNew;                     // 将最后一个节点的指针指向新节点
pNew->link      = NULL;                     // 将新节点中的指针置为空
_tail           = pNew;                     // 将新节点赋给最后的一个节点
}
return _list;
}

/**
*遍历容器内有多少个数据节点
*/
unsigned int getlistNum(List *list)
{
assert( list != NULL);
unsigned int listNum=0;
for(List *node = list->link; node != NULL ; node = node->link)
{
++listNum;
}
return listNum;
}

/**
* 根据标志码 uid 搜索节点
* 返回值:存在   TRUE
*       不存在  FALSE
*/

int search_node(List *list, unsigned int uid )
{
assert( list != NULL);
List *node = list->link;
while(node && node->uid != uid )
{
node = node->link;
}
return ( node ) ? TRUE : FALSE;
}

/**
*功能:   插入新节点到单链表
*参数:   指向链表第一个节点的指针, 节点唯一标识码
*返回值: 成功   返回指向新节点的指针
*        失败   返回 NULL
*/
List *insert(List *list, unsigned int new_uid  )
{
if ( NULL == list )        // 判断 list是否为空
{
return NULL;
}
List *current = list;      // 当前

if( search_node( list, new_uid ) == TRUE)
{// uid 唯一性检测
printf("The id already exists!\n");
return NULL;
}

List *pNew = (List*)malloc( sizeof(List) );
if(pNew == NULL)
{
printf("插入失败\n");
}

pNew->uid   = new_uid;      //    把输入的数据赋给要插入的节点
List *pNext = current->link;//    下一个节点的地址

current->link = pNew;       //    把要插入的节点的地址,给上个节点的指针域
pNew->link    = pNext;      //    把插入节点的下一个节点的地址,给插入节点的指针域
return pNew;
}
/**
*插入 char
*/
int put_char(List *list,  unsigned int uid, char c)
{
List *next = insert(list, uid );
if(next == NULL)
{
return FALSE;
}
next->char_value = c;
next->mark = IS_CHAR;
printf("插入 char 成功\n");
return TRUE;
}
/**
*插入int
*/
int put_integer(List *list, unsigned int uid, int num)
{
List *next = insert(list, uid );
if(next == NULL)
{
return FALSE;
}
next->int_value = num;
next->mark = IS_INT;

printf("插入int 成功\n");
return TRUE;
}

/**
*插入字符串
*/
int put_string(List *list, unsigned int uid, const char *new_str)
{
//#define STRING
List *next = insert(list, uid );
if(next == NULL)
{
return FALSE;
}
strcpy(next->str, new_str );
next->mark = IS_STR;
printf("插入 string 成功\n");

return TRUE;
}
/**
*插入二进制
*/
int put_binary(List *list, unsigned int uid, const char* data, unsigned int data_len)
{
//#define BINARY
List *next = insert(list, uid );
if(next == NULL)
{
return FALSE;
}
strcpy(next->str, data );
next->mark = IS_STR;
printf("插入 binary 成功\n");

return TRUE;
}

/**
*打印节点
*/
int print_list(List *list, unsigned int uid)
{
List *_list = list;

if( _list->link == NULL)
{
printf("Link is empty!\n");
return FALSE;
}

while( _list->link != NULL)
{
if(_list->uid == uid )
{
switch (_list->mark)
{
case IS_CHAR:
printf("%c", _list->char_value );
break;
case IS_INT:
printf("%d", _list->int_value );
break;
case  IS_BIN:
case  IS_STR:
printf("%s", _list->str );
break;
default:
printf("What happened?\n");
break;
}
return TRUE;
}//if
_list = _list->link;
}//while
printf("Not found!\n");
return FALSE;
}

/**
*根据uid删除节点
*/
int delete_list(List *list, unsigned int uid)
{
List *re_list, *_list = list;;
if(list == NULL)
{
printf("找不到节点!\n");
return FALSE;
}

while( (_list->uid != uid) && (_list->link != NULL) )
{
re_list = _list;
_list = _list->link;
}
return ( _list->uid  != uid) ? (printf("链表不存在此节点!\n"), FALSE)
:  (re_list->link = _list->link, free(_list), printf("删除节点成功!\n"), TRUE);
// 问号表达式省了不少长度
}

void delete_all_nodes(List *list)
{
List *_list = list;
if (list == NULL)            // 入口检测
return;
while(_list->link != NULL)   // 删除链表非首结点元素
{
List *current = _list->link;
_list->link = _list->link->link;
free(current);
}
free(_list);                 // 删除链表首结点
4000
元素
list = NULL;
printf("删除所有节点成功\n");
}


测试程序
#include <stdio.h>
#include <stdlib.h>
#include"list.h"
/* 测试此容器 */
int main(void)
{
List *list = create();
int i;

for(i = 1; i < 10; ++i)
{
put_integer( list, i, i*i ); //测试 put_integer
}
for(i = 1; i < 10; ++i)
{
print_list( list, i ); // 测试 print_list
printf("\n");
}

put_integer(list, 9, 113);

put_char( list, 21, 'a' ); // 测试 put_char

print_list(list, 21);
printf("\n");

put_string(list, 122, "What is it ?");// 测试 put_string
print_list(list, 122);
printf("\n");

put_binary(list, 15, "100010B", 6); // 测试 put_binary
print_list(list, 15);
printf("\n");

printf("len=%d\n", getlistNum(list) );// 测试 getlistNum

if( search_node(list, 15) ) printf("uid 15 存在\n" );
else printf("uid 15 不存在\n");

delete_list(list, 15); // 测试 delete_list

if( search_node(list, 15) ) printf("uid 15 存在\n" );
else printf("uid 15 不存在\n");

printf("\n");

delete_all_nodes(list);

system("pause");
return 0;

}

问题:存储空间浪费,存储char时字符数组的空间被大量浪费,对于我这个写单片机程序过来的人来说无法忍受。去改进还需要技巧,25号搞了后就放在这了。
 /*数据结构起步*/  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 链表 malloc