转载请注明出处:http://blog.csdn.net/ecorefeng
作者:朱克锋
把通用双向链表的测试拿出来写不仅仅是应因为和实现写在一起文章太长,而是因为我想在测试中体现一种思想:回调函数,
这里程序实现下列功能。
(1)找出链表中的最大值。
(2) 累加链表中所有整数。
这两个函数的实现与dlist_print的实现很类似,故采用回调函数的方式
不过这两个函数并没有太多实用价值,但是通过它们我们可以学习几点。
1,按传统的方法写出max之后,这个函数与dlist_print很类似,在写出sum_cb之后,那种感觉就更明显了。在这时就应该想办法把这些重复的代码抽出来。
2,重复的代码更容易出错。在写类似代码的时候,几乎所有人都会选择“复制+粘贴”的方法,但使用这种方法很容易犯一些细节上的错误。
3,重复的代码经不起变化。无论是修正bug,还是增加新特性,往往需要修改很多地方,如果不慎忘掉其中一处,会为此付出代价。
这三个函数无非是要遍历双向链表并做一些事情,用dlist_foreach函数来遍历双向链表,至于到底要做什么,这可是千变万化的行为,应该通过回调函数让调用者去做这些事情。
还写了针对一个存放字符串的双向链表,把存放在其中的字符串转换成大写字母。也用回调函数来实现
但是要注意:
1,转换大写的方法不对
应该调用标准C函数islower来判断,同样转换为大写应该调用toupper而不是减去一个常量
if('a' <= *p && *p <= 'z')
{
*p = *p - ('a' - 'A');
}
2,在双向链表中存放的是临时变量
在dlist中存放的是同一个地址。而且这个dlist在当前函数返回后,里面保存的数据都无效了,因为这些数据指向的是临时变量。
3,存放时复制了数据,但没有释放所分配的内存
strdup调用malloc分配了内存
以下是代码的实现(dlisttest.c)
#include "dlist.h"
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
/*
* File: dlisttest.c:关于通用链表的测试
* Author: ecorefeng
* Created on 2010年8月
*/
void test_dlist_int();
void test_dlist_string();
void *str_toupper(void *ctx, void *data);
void delete(DList *dlist, int index);
void *print_string(void *ctx, void *data);
void *max(void *ctx, void *data);
void *sum_cb(void *ctx, void *data);
void *print_int(void *ctx, void *data);
void *destroy_data_p(void *ctx, void *data);
int main (int argc, char* argv[])
{
test_dlist_int();
test_dlist_string();
}
void test_dlist_string()
{
char *a = "AAaa777777abb";
char *b = "bbb444444bbbb";
char *c = "cccc3rrrrr5555555555ccccccc";
char *e = "eeee88888888888eeeee";
int i = 0;
DListNode *dlnode = NULL;
DList *dlist = NULL;
dlist = dlist_create();
assert( 0 == dlist_len(dlist));
for(i=0; i<10; i++)
{
dlist_add(dlist, -1,strdup(a));
}
assert( 10 == dlist_len(dlist));
dlist_add(dlist, 6,strdup(c));
dlist_add(dlist, -1,strdup(c));
dlist_add(dlist, -1,strdup(c));
dlist_destroy(dlist, delete, 13);
dlist_destroy(dlist, delete, 5);
dlist_destroy(dlist, delete, -1);
dlist_destroy(dlist, delete, -1);
dlist_add(dlist, 0,strdup(b));
dlist_add(dlist, 1,strdup(e));
assert( 11 == dlist_len(dlist));
printf("..............链中字母..................../n");
dlist_foreach(dlist, print_string, NULL);
dlist_foreach(dlist, str_toupper, NULL);
printf("..............转换后字母..................../n");
dlist_foreach(dlist, print_string, NULL);
dlist_foreach(dlist, destroy_data_p, NULL);
dlist_destroy(dlist,NULL,0);
}
void *print_string(void *ctx, void *data)
{
printf("%s/n",(char *)data);
return NULL;
}
void delete(DList *dlist, int index)
{
int len = dlist_len(dlist);
if(index < 0 || index == len)
{
free(dlist->current->data);
}
else
{
free(dlist_get(dlist,index)->data);
}
dlist_delete(dlist,index);
}
void *str_toupper(void *ctx, void *data)
{
// char temp_str[256]={0};
// strcpy(temp_str,data);
char *temp = data;
if(temp != NULL)
{
while(*temp != '/0')
{
if(isalpha(*temp))
{
if(islower(*temp))
{
*temp = toupper(*temp);
}
}
temp++;
}
}
}
void *destroy_data_p(void *ctx, void *data)
{
free(data);
return NULL;
}
void test_dlist_int()
{
int p = 0 ;
int a = 111;
int b = 222;
int c = 333;
int e = 444;
int f = 555;
int h = 1000;
int j = 6663;
int k = 777;
DListNode *dlnode = NULL;
DList *dlist = NULL;
dlist = dlist_create();
for(p=0; p<10; p++)
{
dlist_add(dlist, 0,&a);
}
assert( 10 == dlist_len(dlist));
dlist_add(dlist, 4, &j);
dlist_add(dlist, 3, &h);
dlist_add(dlist, -1, &j);
dlist_add(dlist, -1, &j);
dlist_delete(dlist, 14);
dlist_delete(dlist, 8);
dlist_delete(dlist,-1);
assert( 11 == dlist_len(dlist));
printf("........数字..................../n");
dlist_foreach(dlist, print_int, NULL);
long sum = 0;
void *temp = dlist_foreach(dlist, sum_cb, &sum);
printf("======求和=====%d/n",*(long *)temp);
long sum1 = 0;
void *temp1 = dlist_foreach(dlist, max, &sum1);
printf("=====最大值======%d/n",*(long *)temp1);
dlist_destroy(dlist,NULL,0);
}
void *max(void *ctx, void *data)
{
long *result = ctx;
if(*(int *)data >= *result)
{
*result = *(int *)data;
}
return result;
}
void *sum_cb(void *ctx, void *data)
{
long *result = ctx;
*result += *(int *)data;
return result;
}
void *print_int(void *ctx, void *data)
{
printf("%d/n",*(int*)data);
return NULL;
}