《C语言接口与实现》实验——表(Table_T)

来源:互联网 发布:大数据买卖 编辑:程序博客网 时间:2024/05/14 09:39

实验程序是用vc6编译,一定注意文件扩展名为c,不是cpp,在下载:http://download.csdn.net/detail/dijkstar/4036742


注意事项和遇到的问题都已经在实现程序注释中,如下:

#include <stdio.h>#include <stdlib.h>//rand函数使用#include <string.h>#include "include/table.h"#include "include/atom.h"#pragma comment(lib, "libcii.lib")//产生一个[M, N]区间上的随机数int my_rand(int M,int N)  {      return (int)((double)rand()/(double)RAND_MAX*(N-M+1)+M);  }  //遍历输出函数void Print(const void *key, void **val, void *cl){char *k = (char *)key;int **v = (int **)val;printf("%s --- %d\n", k, *v);}//遍历修改函数//简单修改为一个固定的值void Edit(const void *key, void **val, void *cl){int **v = (int **)val;*v = 10000;}void main(){//注意:C语言一定要将这些变量声明放在函数的头部Table_T t1;int i = 0;char tmpKey[100] = {0};char *key = NULL;intval;void **ary;int tmp1 = 0, *tmp = &tmp1;//创建表t1 = Table_new(0, NULL, NULL);//添加数据//注意:本不应该这样向表中添加数据for (; i<10; i++){sprintf(tmpKey, "key%02d", i);//生成临时【key】val = my_rand(1000, 9999);//生成【val】key = Atom_string(tmpKey);//第二项【key】的地址必须是一个“原子”(即每次字符串的地址不能相同!!)//不要简单的传递一个字符串地址,因为字符串地址不同于“原子”的地址//第三项【val】传递时,参见该函数的源码实现——记载的是地址值,而不是将该地址的内容拷贝进去到表中//这里简单传递的值是一个int,如果是一个结构体变量,也应该是将结构体变量的地址值直接传递进去,//再次强调,Table_put内部直接赋值了地址值,而不是拷贝该地址上的内容!!Table_put(t1, key, val);}//输出表长度printf("表长度 = %d\n", Table_length(t1));//返回表中的某一个项//再次注意:不要简单的传递一个字符串地址,而是传递一个原子址val = (int)Table_get(t1, Atom_string("key03"));printf("查找返回:key03 = %d\n", val);//修改返回的这个val值:修改不了,再次验证这个测试程序向表中传递的【val】是一个值,不是地址(指针)*tmp = (int)Table_get(t1, Atom_string("key03"));*tmp = 10000;val = (int)Table_get(t1, Atom_string("key03"));printf("确认不能修改:key03 = %d\n", val);//输出表方式1printf("输出表方式1:Table_toArray\n");ary = Table_toArray(t1, NULL);for (i=0; ary[i]; i+=2){//第二项内容,简单的是一个int:当时传递时就是这个样子!!printf("%s --- %d\n", (char *)ary[i], (int)ary[i+1]);}//输出表方式2printf("\n输出表方式1:Table_map\n");Table_map(t1, Print, NULL);//删除val = (int)Table_remove(t1, Atom_string("key03"));printf("删除的key03 = %d\n", val);//再次输出表方式2,检查“key03”是否存在?printf("\n确认“key03”不存在\n");Table_map(t1, Print, NULL);//遍历修改Table_map(t1, Edit, NULL);//再次输出表方式2,检查每一项是否修改printf("\n确认每一项都已经修改\n");Table_map(t1, Print, NULL);}

输出结果为:

表长度 = 10查找返回:key03 = 8278确认不能修改:key03 = 8278输出表方式1:Table_toArraykey03 --- 8278key04 --- 6265key05 --- 5318key06 --- 4152key07 --- 9063key08 --- 8405key09 --- 7719key00 --- 1011key01 --- 6072key02 --- 2739输出表方式1:Table_mapkey03 --- 8278key04 --- 6265key05 --- 5318key06 --- 4152key07 --- 9063key08 --- 8405key09 --- 7719key00 --- 1011key01 --- 6072key02 --- 2739删除的key03 = 8278确认“key03”不存在key04 --- 6265key05 --- 5318key06 --- 4152key07 --- 9063key08 --- 8405key09 --- 7719key00 --- 1011key01 --- 6072key02 --- 2739确认每一项都已经修改key04 --- 10000key05 --- 10000key06 --- 10000key07 --- 10000key08 --- 10000key09 --- 10000key00 --- 10000key01 --- 10000key02 --- 10000Press any key to continue

通过这个实验,深刻理解了原子的“唯一性”和地址指针。

注:① 实验程序中使用的key是原子,根据Table函数接口说明,是一个void *类型,因此可以传递一个int,一个char等等来做【key】;

② 不清楚的地方,跟踪进入到源程序实现,可以明白怎么回事。如Table_new()的后面两个参数,一个是比较函数,一个是哈希函数,都可以传递为NULL,此时使用了内部函数。

③ Table_put函数,第三个参数(最后一个参数)是一个void *val,是一个指针类型,但是请注意,调用这个函数时,不是将该地址上的内容,拷贝到内部表中,而是简单的讲地址记下来。同时想起了MFC这几个函数:

CComboBox::SetItemDataCListBox::SetItemDataCTreeCtrl::SetItemData
请借助这几个函数来理解Table_put函数。