【编程范式】C语言泛型

C语言中使用void *指针实现泛型编程

1.swap函数——实现交换任意类型的两个元素
2.lsearch函数——线性查找数组中的元素
swap函数——实现交换任意类型的两个元素

void swap(void *vp1, void *vp2, int size)
{
char buffer[size];
memcpy(buffer, vp1, size);
memcpy(vp1, vp2, size);
memcpy(vp2, buffer, size);
}
注:通用的C编译器,不能给数组指定一个变量,可用动态内存分配malloc解决
swap的测试用例

void Test()
{
int x = 17, y = 37;
swap(&x, &y, sizeof(int));//正确

double d = 3.1415 e = 1.12121
swap(&d, &e, sizeof(int));//错误,只交换了8字节的前四个字节

int i = 44;
short s = 5;
swap(&i, &s, sizeof(short));//错误,大端结果为5*2的16次方,加上44,小端结果略有不同
}
注:使用swap时交换要注意不能"越界"(字符串的交换容易出错,对缓存大小、字符串长度也有要求,往往用c++中的string类型实现)

lsearch函数——线性查找数组中的元素

void *lsearch(void *key, void *base, int n, int elemSzie, int (*cmpfn)(void *, void *))
{
for (int i = 0; i < n; i++) {
void *elemAddr = (char *)base + i*elemSize;//void* 技巧,使指针算数运算和平常的运算效果相同
if (cmpfn(key, elemAddr) == 0)
return elemAddr;
}
return NULL;
}
注:void *型指针做偏移时,强转为char *型(c语言中常称为void *技巧)

比较函数

int IntCmp(void *elem1, void *elem2)
{
int *ip1 = elem1;
int *ip2 = elem2;
return *ip1 - *ip2;
}

int StrCmp(void *vp1, viod *vp2)
{
char *s1 = *(char **)vp1;
char *s2 = *(char **)vp2;
return strcmp(s1, s2);//strcmp()为库函数
}

lsearch的测试用例

char *strs[]={"Ag", "Fb", "B", "Gb", "D"};
char *foundStr = "Eb";
char **found = lsearch(&foundStr, strs, 5, sizeof(char *), StrCmp);

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编程是一种编程范式,其目的是通过在代码中使用抽象类和算法,使得代码能够适用于多种数据类而不需要重复编写代码。在C语言中,编程的实现通常使用宏和void指针。 在Apollo中,有一个叫做ADT(抽象数据类)的模块,它提供了一种编程的方法。ADT模块定义了一些通用的数据结构和算法,这些数据结构和算法可以应用于不同的数据类上。例如,ADT模块中定义了一个叫做“链表”的数据结构,它可以用于存储任何类的数据,而不需要对每种数据类都写一个独立的链表实现。 ADT模块中的编程主要使用了void指针和函数指针。在ADT模块中,每个数据类都需要提供一组对应的函数指针,这些函数指针定义了对该数据类进行操作的一组基本操作。例如,对于链表数据结构,需要提供函数指针来定义链表的创建、插入、删除、遍历等操作。 在使用ADT模块时,可以通过传递不同的函数指针,将不同类的数据应用于相同的算法或数据结构中。例如,可以使用ADT模块中的“排序”算法对不同类的数据进行排序,只需要传递不同的比较函数即可。 下面是一个示例代码,演示了如何使用ADT模块中的链表数据结构和函数: ```c #include <stdio.h> #include "adt/list.h" int main() { list_t* list = list_create(); // 创建链表 int a = 1, b = 2, c = 3; list_push_back(list, &a); // 在链表末尾插入元素 list_push_back(list, &b); list_push_back(list, &c); // 遍历链表 list_iterator_t* iter = list_iterator_create(list); while (list_iterator_has_next(iter)) { int* data = (int*)list_iterator_next(iter); printf("%d ", *data); } printf("\n"); list_iterator_destroy(iter); list_destroy(list); // 销毁链表 return 0; } ``` 在这个示例代码中,我们使用了ADT模块中的list_t数据结构和相应的操作函数,创建了一个链表并向其中添加了三个整数元素。然后,我们使用list_iterator_t遍历链表,并打印出其中的每个元素。需要注意的是,在遍历过程中,我们将void指针转换为了int指针,这是因为我们知道这个链表中存储的是int类的元素。 通过使用ADT模块,我们可以编写出更加通用、灵活的代码,并且可以将相同的算法和数据结构应用于不同的数据类上,从而提高代码重用性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值