实验程序是用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; int val; 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); //输出表方式1 printf("输出表方式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]); } //输出表方式2 printf("\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_toArray key03 --- 8278 key04 --- 6265 key05 --- 5318 key06 --- 4152 key07 --- 9063 key08 --- 8405 key09 --- 7719 key00 --- 1011 key01 --- 6072 key02 --- 2739 输出表方式1:Table_map key03 --- 8278 key04 --- 6265 key05 --- 5318 key06 --- 4152 key07 --- 9063 key08 --- 8405 key09 --- 7719 key00 --- 1011 key01 --- 6072 key02 --- 2739 删除的key03 = 8278 确认“key03”不存在 key04 --- 6265 key05 --- 5318 key06 --- 4152 key07 --- 9063 key08 --- 8405 key09 --- 7719 key00 --- 1011 key01 --- 6072 key02 --- 2739 确认每一项都已经修改 key04 --- 10000 key05 --- 10000 key06 --- 10000 key07 --- 10000 key08 --- 10000 key09 --- 10000 key00 --- 10000 key01 --- 10000 key02 --- 10000 Press any key to continue
通过这个实验,深刻理解了原子的“唯一性”和地址指针。
注:① 实验程序中使用的key是原子,根据Table函数接口说明,是一个void *类型,因此可以传递一个int,一个char等等来做【key】;
② 不清楚的地方,跟踪进入到源程序实现,可以明白怎么回事。如Table_new()的后面两个参数,一个是比较函数,一个是哈希函数,都可以传递为NULL,此时使用了内部函数。
③ Table_put函数,第三个参数(最后一个参数)是一个void *val,是一个指针类型,但是请注意,调用这个函数时,不是将该地址上的内容,拷贝到内部表中,而是简单的讲地址记下来。同时想起了MFC这几个函数:
CComboBox::SetItemData CListBox::SetItemData CTreeCtrl::SetItemData请借助这几个函数来理解Table_put函数。