关于C语言通用双向链表实现的测试--回调函数的作用

本文通过C语言实现通用双向链表的测试,强调回调函数在功能实现中的作用,如查找最大值、累加整数等。通过回调函数,避免重复代码,提高代码复用性和可维护性。同时展示了将字符串链表转换为大写字符的案例,探讨了在处理链表数据时应注意的问题。
摘要由CSDN通过智能技术生成

转载请注明出处: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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值