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

实验程序是用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函数。



你可能感兴趣的:(c,String,table,null,mfc,语言)