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);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1547534.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

20 vue3之自定义hooks

Vue3 自定义Hook的作用 主要用来处理复用代码逻辑的一些封装 Vue3 的 hook函数 相当于 vue2 的 mixin, 不同在与 hooks 是函数Vue3 的 hook函数 可以帮助我们提高代码的复用性, 让我们能在不同的组件中都利用 hooks 函数 这个在vue2 就已经有一个东西是Mixins mixins就是将…

代码随想录算法训练营第57天 | 寻宝

寻宝 题目描述 在世界的某个区域&#xff0c;有一些分散的神秘岛屿&#xff0c;每个岛屿上都有一种珍稀的资源或者宝藏。国王打算在这些岛屿上建公路&#xff0c;方便运输。 不同岛屿之间&#xff0c;路途距离不同&#xff0c;国王希望你可以规划建公路的方案&#xff0c;如何…

PostgreSQL 创建表,常规表、外部表、分区表区别讲解

PostgreSQL 创建表&#xff0c;常规表、外部表、分区表区别讲解 创建表&#xff0c;常规表、外部表、分区表区一、常规表1. 定义和特点&#xff1a;2. 适用场景&#xff1a; 二、外部表1. 定义和特点&#xff1a;2. 适用场景&#xff1a; 三、分区表1. 定义和特点&#xff1a;2…

什么是Agent智能体?

你好&#xff0c;我是三桥君 近期&#xff0c;从各大厂商的年度大会到多个大型AI峰会&#xff0c;三桥君明显感受到行业风气的转变。这些会议不仅展示了众多AI Agent的实际应用案例&#xff0c;还有专家们对未来发展的预测。一时间&#xff0c;“Agent”这个词成为了热门词汇&…

【论文阅读】Diffusion Policy: Visuomotor Policy Learning via Action Diffusion

Abstract 本文介绍了扩散策略&#xff0c;这是一种通过将机器人的视觉运动policy表示为条件去噪扩散过程来生成机器人行为的新方法。我们对来自 4 个不同的机器人操作基准的 15 个不同任务的扩散策略进行了基准测试&#xff0c;发现它始终优于现有的 state-of-the-art 机器人学…

【AndroidStudio】关于AndroidStudio的常见控件TextView和Button

作者&#xff1a;CSDN-PleaSure乐事 欢迎大家阅读我的博客 希望大家喜欢 使用环境&#xff1a;AndroidStudio 1.常见控件TextView 1.1基本信息 TextView主要用于在界面上显示一段文本信息。最基本的代码格式如下&#xff1a; <TextView android:id"id/text_vie…

如何在 macOS(MacBook Pro、Air 和 iMac)上恢复未保存的 Word 文档

Microsoft Word 在许多用户中很受欢迎&#xff0c;并且有多种用途。无论是为学校写论文、在办公室写报告还是其他许多事情。但是不保存文档并丢失数据可能是您可能面临的最可怕的噩梦。但是&#xff0c;也有几种方法可以在 macOS 上恢复未保存的 Word 文档。 用户在 Windows P…

智能手机取证: 专家如何从被锁定设备中提取数据?

在数字取证领域&#xff0c;从被锁定的手机中检索数据的能力是决定调查成功与否的关键技能。由于智能手机往往是解决复杂案件的关键&#xff0c;智能手机取证已经成为打击犯罪和恐怖主义战争中的一个关键组成部分。通话记录、短信、电子邮件&#xff0c;甚至位置数据都可能被发…

如何在谷歌浏览器上玩大型多人在线游戏

在如今的数字时代&#xff0c;谷歌浏览器已经成为了许多人上网冲浪的首选工具。除了浏览网页、观看视频之外&#xff0c;你还可以在谷歌浏览器上畅玩各种大型多人在线游戏。本文将为你详细介绍如何在谷歌浏览器上玩大型多人在线游戏的步骤。 &#xff08;本文由https://chrome…

asp.net mvc core 路由约束,数据标记DataTokens

》从0自己搭建MVC 》用 asp.net Core web 应用 空web 应用程序 需要配置 mvc服务 、mvc路由 新建 Controller 、Models、Views 》》》core 6 之前版本 vs2022 asp.net Core Web 应用&#xff08;模型-视图-控制器&#xff09; 不需要配置 就是mvc框架 asp.net Core web 应…

c++算法第二天

温馨提示&#xff1a;本篇文章适合刚开始练算法的小白&#xff0c;大佬若见勿嘲 题目 题目解析 遇到0写两遍&#xff0c;非0写一遍&#xff0c;其余非零数右移即可 编写原理 第一步找到最后一个被复写的数 先根据题目所给的例子找到最后一次要复写的数字 20240923_142843 第…

OpenHarmony(鸿蒙南向)——平台驱动指南【I2C】

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 概述 功能简介 I2C&#xff08;Inter Integrated Circuit&#x…

怎么备考2024年11月软考高级系统架构师 ?

分享下我的系统架构设计师考证之路&#xff0c;希望能对即将参加考试的小伙伴们带来一些启示和帮助。 先贴出自己软考系统架构设计师成绩&#xff0c;备考一次就通过了考试。 一、架构考试教材 架构考试教材目前使用的是系统架构设计师教程&#xff08;第2版&#xff09;&…

Excel锁定单元格,使其不可再编辑

‌在Excel中&#xff0c;锁定单元格后仍然可以编辑‌&#xff0c;这主要涉及到对特定单元格或区域的锁定与保护工作表的设置。以下是实现这一功能的具体步骤&#xff1a; ‌解除工作表的锁定状态‌&#xff1a;首先&#xff0c;需要全选表格&#xff08;使用CtrlA快捷键&#x…

叉车司机信息权限采集系统,保障与优化叉车运输网络的安全

叉车司机信息权限采集系统可以通过监控司机的行车行为和车辆状况&#xff0c;实时掌握车辆位置和行驶路线&#xff0c;从而提高运输安全性&#xff0c;优化运输网络&#xff0c;降低事故风险。同时&#xff0c;该系统还可以通过对叉车司机信息和行车数据的分析&#xff0c;优化…

新书推荐——《Python贝叶斯深度学习》

在过去的十年中&#xff0c;机器学习领域取得了长足的进步&#xff0c;并因此激发了公众的想象力。但我们必须记住&#xff0c;尽管这些算法令人印象深刻&#xff0c;但它们并非完美无缺。本书旨在通过平实的语言介绍如何在深度学习中利用贝叶斯推理&#xff0c;帮助读者掌握开…

vscode使用yarn 启动vue项目记录

第一次启动yarn项目&#xff0c;这个是公司的老项目&#xff0c;遇到了点问题&#xff0c;记录下首先是我一般使用的是npm命令&#xff0c;所以没有安装yarn vscode安装yarn vscode进入到该项目文件夹下&#xff0c;输入命令&#xff1a;npm install -g yarn 安装成功后&…

使用豆包MarsCode 实现高可用扫描工具

以下是「 豆包MarsCode 体验官」优秀文章&#xff0c;作者郝同学测开笔记。 前言&#xfeff; 最近接触K8s&#xff0c;了解到K8s提供了非常方便的实现高可用的能力&#xff0c;再加上掘金推出「豆包MarsCode初体验」征文活动&#xff0c;所以打算使用豆包 MarsCode IDE来实现…

uniapp踩坑 tabbar页面数据刷新了但视图没有更新

问题描述&#xff1a; 有个uni-data-checkbox组件&#xff0c;两个选项&#xff1a;选项1和选项2&#xff08;对应的value值分别为1和2&#xff09;&#xff0c;v-model绑定属性名为value 两个tabbar页面&#xff1a;tab1&#xff0c;tab2。 tab1页面有个逻辑是在onShow中刷新v…

【C++笔试强训】如何成为算法糕手Day5

学习编程就得循环渐进&#xff0c;扎实基础&#xff0c;勿在浮沙筑高台 循环渐进Forward-CSDN博客 目录 循环渐进Forward-CSDN博客 第一题&#xff1a;游游的you 思路&#xff1a; 第二题&#xff1a;腐烂的苹果 思路&#xff1a; 第三题&#xff1a;孩子们的游戏 思路&…