当前位置: 首页 > news >正文

C语言进阶之泛型列表(Generic List)

1.前言

        数据结构是需要泛型的,而在C语言中实现泛型就只能去用指针魔法了,来跟我一起实现吧!所有代码经测试未发现明显bug,可放心食用.

2.代码截图展示

1.list.h

2.main.c

3.list.c

3.结语

        这次分享的列表采用动态数组的方式实现,下次我会去用链表实现,两种实现方式各有优劣,希望初学者能够自己去实现一下.本次分享到此结束,记得点赞加收藏,你的点赞是我更新的动力!!!

4.可复制代码展示

//list.h
#pragma once
#include <assert.h>
#include <crtdefs.h>
#include <stdbool.h>
#include <stdio.h>   // IWYU pragma: export
#include <stdlib.h>  // IWYU pragma: export
#include <string.h>  // IWYU pragma: export
#include <time.h>    // IWYU pragma: exporttypedef struct {void *data;size_t dataSize;size_t size;size_t capacity;
} List;#define DEFAULT_CAPACITY 4
#define DRFPTR(type, ptr) (*(type *)ptr)List *ListCreate(size_t dataSize);
#define mListCreate(TYPE) ListCreate(sizeof(TYPE))
void ListDestory(List *pList);
bool CheckCapacity(List *pList, size_t insertSize);
void ListPushBack(List *pList, const void *data);
void ListPopBack(List *pList);
void ListPrint(const List *pList, void (*pfPrint)(const void *));
size_t ListSize(List *pList);
size_t ListCapacity(List *pList);
void ListPushFront(List *pList, const void *data);
void ListPopFront(List *pList);
void ListPosInsert(List *pList, size_t pos, const void *data);
void ListPosErase(List *pList, size_t pos);
void ListRandomInsertIntData(List *pList,size_t count,size_t maxNum);
void ListSort(List *pList, int (*pfCmp)(const void *, const void *));
void ListRandomInsertDoubleData(List *pList, size_t count);
void ListDataModify(List *pList,size_t pos,void (*pfModify)(void *));
bool ListIsEmpty(List *pList);
bool ListReserve(List *pList, size_t size);
size_t ListResize(List *pList, size_t size);
void *ListDataAt(List *pList, size_t index);
void *ListHeadData(List *pList);
void *ListTailData(List *pList);
void ListClear(List *pList);
size_t ListFindData(List *pList,const void *findData,int (*pfCmp)(const void *, const void *));
void ListIndexAccess(const List *pList,const size_t index,void (*pfPrint)(const void *));
//main.c
#include "list.h"typedef struct {char name[20];int age;
} People;int CmpPeopleAge(const void *e1, const void *e2) {return DRFPTR(People, e1).age - DRFPTR(People, e2).age;
}
int CmpPeopleName(const void *e1, const void *e2) {return strcmp(DRFPTR(People, e1).name, DRFPTR(People, e2).name);
}
void PrintPeople(const void *data) {printf("name:%-10s\tage:%2d\n", DRFPTR(People, data).name,DRFPTR(People, data).age);
}
void ModifyInt(void *data) {int *d = (int *)data;*d = 666666;
}
void ModifyDouble(void *data) {// printf("输入>>>");// scanf("%lf", (double *)data);*(double *)data = 0.123456;
}
void PrintInt(const void *data) {printf("%d ", *(int *)data);
}
void PrintDouble(const void *data) {printf("%.5lf ", *(double *)data);
}
int CmpInt(const void *e1, const void *e2) {return *(int *)e1 - *(int *)e2;
}
int CmpDouble(const void *e1, const void *e2) {return (*(double *)e1 > *(double *)e2? 1: (*(double *)e1 < *(double *)e2 ? -1 : 0));
}
void test_int() {List *list = mListCreate(int);printf("list size: %zu\n", ListSize(list));printf("list capacity: %zu\n", ListCapacity(list));// for (int i = 0, data; i < 3; i++) {//   data = rand() % 10;//   ListPushBack(list, &data);// }// ListPrint(list, PrintInt);// for (int i = 0, data; i < 3; i++) {//   data = rand() % 10;//   ListPushFront(list, &data);// }// int a = 666;// ListPosInsert(list, 2, &a);// ListPrint(list, PrintInt);// for (int i = 0; i < 1; i++) {//   ListPopBack(list);//   ListPopFront(list);// }// ListPosErase(list, 1);// ListPosErase(list, 0);// ListPosErase(list, ListSize(list) - 1);ListRandomInsertIntData(list, 1234, 666);// ListPrint(list, PrintInt);ListSort(list, CmpInt);// ListPrint(list, PrintInt);printf("list size: %zu\n", ListSize(list));printf("list capacity: %zu\n", ListCapacity(list));size_t index;while (1) {int data;printf("输入>>>");scanf("%d", &data);index = ListFindData(list, &data, CmpInt);if (index == ListSize(list)) {printf("找不到该数据,请重新输入!\n");} else {break;}}printf("find data index is %zu\n", index);ListIndexAccess(list, index, PrintInt);ListDestory(list);
}
void test_double() {List *list = mListCreate(double);ListRandomInsertDoubleData(list, 13);ListPrint(list, PrintDouble);// ListSort(list, CmpDouble);ListDataModify(list, 0, ModifyDouble);ListDataModify(list, 4, ModifyDouble);printf("list new size:%zu:\n", ListResize(list, 5));ListPrint(list, PrintDouble);// printf("list[last] is %lf\n",//        *(double *)ListDataAt(list, ListSize(list) - 1));printf("list head data is %lf\n",DRFPTR(double, ListHeadData(list)));printf("list tail data is %lf\n",DRFPTR(double, ListTailData(list)));// ListClear(list);printf("list size: %zu\n", ListSize(list));printf("list capacity: %zu\n", ListCapacity(list));size_t index;while (1) {double data;printf("输入>>>");scanf("%lf", &data);index = ListFindData(list, &data, CmpInt);if (index == ListSize(list)) {printf("找不到该数据,请重新输入!\n");} else {break;}}printf("find data index is %zu\n", index);ListIndexAccess(list, index, PrintDouble);ListDestory(list);
}
void test_struct() {List *list = mListCreate(People);People p;for (int i = 0; i < 3; i++) {printf("输入姓名>>>");scanf("%s", p.name);printf("输入年龄>>>");scanf("%d", &p.age);ListPushBack(list, &p);}ListPrint(list, PrintPeople);// ListSort(list, CmpPeopleAge);ListSort(list, CmpPeopleName);ListPrint(list, PrintPeople);size_t index;while (1) {People p;printf("输入>>>");scanf("%s", p.name);// scanf("%d", &p.age);// index = ListFindData(list, &p, CmpPeopleAge);index = ListFindData(list, &p, CmpPeopleName);if (index == ListSize(list)) {printf("找不到该数据,请重新输入!\n");} else {break;}}printf("find data index is %zu\n", index);ListIndexAccess(list, index, PrintPeople);ListDestory(list);
}
int main(void) {srand((unsigned int)time(NULL));// test_int();// test_double();test_struct();return 0;
}
//list.c#include "list.h"List *ListCreate(size_t dataSize) {List *list = (List *)malloc(sizeof(List));if (NULL == list) {printf("malloc fail!\n");exit(-1);}void *ptr = malloc(DEFAULT_CAPACITY * dataSize);if (NULL == ptr) {printf("malloc fail!\n");exit(-1);}list->data = ptr;list->dataSize = dataSize;list->capacity = DEFAULT_CAPACITY;list->size = 0;return list;
}
void ListDestory(List *pList) {assert(pList);free(pList->data);pList->data = NULL;free(pList);pList = NULL;
}
bool CheckCapacity(List *pList, size_t insertSize) {assert(pList && insertSize);if (insertSize <= pList->capacity - pList->size) {return true;}if (insertSize > 1) {void *ptr = realloc(pList->data, (pList->capacity + insertSize) *pList->dataSize);if (NULL == ptr) {printf("realloc fail!\n");return false;}pList->data = ptr;pList->capacity = pList->capacity + insertSize;return true;} else {void *ptr =realloc(pList->data, 2 * pList->capacity * pList->dataSize);if (NULL == ptr) {printf("realloc fail!\n");return false;}pList->data = ptr;pList->capacity = 2 * pList->capacity;return true;}
}
void ListPushBack(List *pList, const void *data) {assert(pList && data);if (CheckCapacity(pList, 1)) {memcpy(pList->data + pList->dataSize * pList->size, data,pList->dataSize);pList->size++;}
}
void ListPopBack(List *pList) {assert(pList);if (pList->size) {pList->size--;}
}
void ListPrint(const List *pList, void (*pfPrint)(const void *)) {assert(pList);for (int i = 0; i < pList->size; i++) {pfPrint(pList->data + pList->dataSize * i);}printf("\n");
}
size_t ListSize(List *pList) {assert(pList);return pList->size;
}
size_t ListCapacity(List *pList) {assert(pList);return pList->capacity;
}
void ListPushFront(List *pList, const void *data) {assert(pList && data);if (CheckCapacity(pList, 1)) {for (int i = pList->size; i > 0; i--) {memcpy(pList->data + i * pList->dataSize,pList->data + (i - 1) * pList->dataSize,pList->dataSize);}memcpy(pList->data, data, pList->dataSize);pList->size++;}
}
void ListPopFront(List *pList) {assert(pList);if (pList->size) {for (int i = 0; i < pList->size; i++) {memcpy(pList->data + i * pList->dataSize,pList->data + (i + 1) * pList->dataSize,pList->dataSize);}pList->size--;}
}
void ListPosInsert(List *pList, size_t pos, const void *data) {assert(pList && data);assert(pos < pList->size);if (CheckCapacity(pList, 1)) {for (int i = pList->size; i > pos; i--) {memcpy(pList->data + i * pList->dataSize,pList->data + (i - 1) * pList->dataSize,pList->dataSize);}memcpy(pList->data + pos * pList->dataSize, data,pList->dataSize);pList->size++;}
}
void ListPosErase(List *pList, size_t pos) {assert(pList);assert(pos < pList->size);if (pList->size) {for (int i = pos; i < pList->size; i++) {memcpy(pList->data + i * pList->dataSize,pList->data + (i + 1) * pList->dataSize,pList->dataSize);}pList->size--;}
}
void ListRandomInsertIntData(List *pList,size_t count,size_t maxNum) {assert(pList);assert(maxNum + 1 < RAND_MAX);if (CheckCapacity(pList, count)) {int data = 0;for (int i = 0; i < count; i++) {data = rand() % (maxNum + 1);memcpy(pList->data + pList->dataSize * pList->size, &data,sizeof(int));pList->size++;}}
}
void ListSort(List *pList,int (*pfCmp)(const void *, const void *)) {assert(pList && pfCmp);if (pList->size > 1) {// qsort(void *Base, size_t NumOfElements, size_t SizeOfElements,// int (*PtFuncCompare)(const void *, const void *)// __attribute__((cdecl)))qsort(pList->data, pList->size, pList->dataSize, pfCmp);}
}
void ListRandomInsertDoubleData(List *pList, size_t count) {assert(pList);if (CheckCapacity(pList, count)) {double data = 0;for (int i = 0; i < count; i++) {data = (double)rand() / RAND_MAX;memcpy(pList->data + pList->dataSize * pList->size, &data,sizeof(double));pList->size++;}}
}
void ListDataModify(List *pList,size_t pos,void (*pfModify)(void *)) {assert(pList && pfModify);assert(pos < pList->size);pfModify(pList->data + pList->dataSize * pos);
}
bool ListIsEmpty(List *pList) {assert(pList);if (0 == pList->size) {return true;} else {return false;}
}
bool ListReserve(List *pList, size_t size) {assert(pList);return CheckCapacity(pList, size);
}
size_t ListResize(List *pList, size_t size) {assert(pList);if (size <= pList->size) {pList->size = size;} else {if (CheckCapacity(pList, size - pList->size)) {memset(pList->data + pList->dataSize * pList->size, 0,(size - pList->size) * pList->dataSize);pList->size = size;}}return pList->size;
}
void *ListDataAt(List *pList, size_t index) {assert(pList);assert(index < pList->size);return pList->data + pList->dataSize * index;
}
void *ListHeadData(List *pList) {assert(pList);if (pList->size) {return pList->data;} else {return NULL;}
}
void *ListTailData(List *pList) {assert(pList);if (pList->size) {return pList->data + pList->dataSize * (pList->size - 1);} else {return NULL;}
}
void ListClear(List *pList) {assert(pList);pList->size = 0;
}
size_t ListFindData(List *pList,const void *findData,int (*pfCmp)(const void *, const void *)) {assert(pList && findData && pfCmp);for (int i = 0; i < pList->size; i++) {if (0 == pfCmp(findData, pList->data + pList->dataSize * i)) {return i;}}return pList->size;
}
void ListIndexAccess(const List *pList,const size_t index,void (*pfPrint)(const void *)) {assert(pList && pfPrint);assert(index < pList->size);pfPrint(pList->data + pList->dataSize * index);
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • java通过webhook给飞书发送群消息
  • 力扣 简单 876.链表的中间结点
  • 微服务-流量染色
  • Windows安装openssl开发库
  • 『功能项目』宠物的攻击巨型化【80】
  • 手机也可以更换任意IP地址吗?
  • Linux中修改MySQL密码
  • 自学网络安全(黑客技术)2024年 —90天学习计划
  • java中的动态代理
  • 驱动开发系列18 - PAGE_SHIFT 解释
  • Golang | Leetcode Golang题解之第438题找到字符串中所有字母异位词
  • 智能监控,守护绿色能源:EasyCVR在电站视频监控中心的一站式解决方案
  • 华为GaussDB数据库(单机版)在ARM环境下的安装指南
  • 【C++笔试强训】如何成为算法糕手Day5
  • Html jquery下拉select美化插件——selectFilter.js
  • 分享的文章《人生如棋》
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • Effective Java 笔记(一)
  • go语言学习初探(一)
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • laravel 用artisan创建自己的模板
  • mockjs让前端开发独立于后端
  • Node项目之评分系统(二)- 数据库设计
  • quasar-framework cnodejs社区
  • select2 取值 遍历 设置默认值
  • storm drpc实例
  • Travix是如何部署应用程序到Kubernetes上的
  • vue中实现单选
  • 不上全站https的网站你们就等着被恶心死吧
  • 给github项目添加CI badge
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 什么软件可以剪辑音乐?
  • 一文看透浏览器架构
  • 移动端解决方案学习记录
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​linux启动进程的方式
  • ​第20课 在Android Native开发中加入新的C++类
  • ​探讨元宇宙和VR虚拟现实之间的区别​
  • # C++之functional库用法整理
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (0)Nginx 功能特性
  • (二刷)代码随想录第15天|层序遍历 226.翻转二叉树 101.对称二叉树2
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (十六)Flask之蓝图
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (转载)Google Chrome调试JS
  • (转载)PyTorch代码规范最佳实践和样式指南
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • .【机器学习】隐马尔可夫模型(Hidden Markov Model,HMM)
  • .Net接口调试与案例
  • .NET中分布式服务
  • @Not - Empty-Null-Blank
  • [ A*实现 ] C++,矩阵地图