昨天几乎解决了指针的问题,于是趁机将256路的TRIE给实现了,然后问题来了。 VS2005命令行下编译得到的程序可以正确运行,2008则不行;同时,我的程序可以接受命令行的关键字进行查询,一旦关键字长度超过6个英文字符,即使之前正确执行的程序也会报错。当然2008报的更早。很成问题哪! 今天又用VC6编译了,耶,命令行参数再长也没有关系了,但是放到2005/2008的命令行提示符下运行,对不起,照样出错。微软的东西啦,怎么说啊,又爱又恨,郁闷。 然后我查了下刚分配内存的root结点中的256个元素,发现有接近1/5的元素的指针都 !=NULL(VC6)。当然,在之前我就发现2008中的错误就在于结点的数组元素不为NULL,于是没有分配新的空间,所以出现错误。 使用如下程序:
#include <stdio.h>
#define len sizeof(struct node)
struct node
{
int id;
struct node* child[256];
};
int main(int argc, char *argv[])
{
struct node *root = (struct node *)malloc(len);
for (i=0; i<256 ;i++ )
{
if (root->child[i]!=NULL)
{
printf("%3d is NOT NULL/n", i);
}
}
return 0;
}
这个程序分别用VC6(盗版)、VS2005Team(盗版)、VS2008Professional得到的结果为: VC6: 0~~51、53~~56 is NOT NULL 2005:0 is NOT NULL 2008:0~~255 is NOT NULL 这个测试的目的仅仅是为了我之前的设想,看是否需要在每次分配空间之后将所有的元素指针设为NULL。现在看来是势在必行了。所以如下TRIE的实现中改来改去最后添加了一个方法:init()才解决饿了问题的,而且这样的方法无论哪个版本编译之后在另一个版本的命令行下都可以正确自行。
#include <stdio.h>
#include <string.h>
struct node
{
int id;
struct node* child[256];
};
struct node* root;
/*函数定义*/
struct node* lookup(const char *);
static struct node* find(int place, const char* word, struct node* n);
void addvalue(int id, char * word, struct node* nd);
void init(struct node* nd);
/* 搜索时所用的方法 */
struct node* lookup(const char * word)
{
return find(0, word, root);
}
/*内部查找方法,在添加之前也需要提前调用以确定需要的结点*/
static struct node* find(int place, const char* word, struct node* n)
{
int p;
if (NULL == n)
{
printf("出现错误。/n");
exit(-1);
}
if (place >= strlen(word))
{
return n;
}
p = word[place] & 0xFF;
if (n->child[p] == NULL)
{
n->child[p] = (struct node*)malloc(sizeof(struct node));
init(n->child[p]);
n->child[p]->id = -1;/*inialize as -1*/
}
return find(place+1, word, n->child[p]);
}
/*将word所对应的id添加进trie树的对应地方*/
void addvalue(int id, char * word, struct node* nd)
{
struct node* n;
int i = 0;
int place = 0;
n = find(0, word, nd);
if (NULL == n)
{
printf("返回值不应该为空。/n");
exit(-1);
}
n->id = id;
}
/*main方法*/
int main(int argc, char *argv[])
{
char* word = NULL;
int id = -1;
struct node* s = NULL;
const char* default_test_string = "美国";
FILE * f;
char *search = (char *)malloc(20);
if (argc > 1)
{
if (strlen(argv[1]) > 19)
{
printf("请输入关键字少于20个英文字符./n");
exit(-1);
}
search = strcpy(search, argv[1]);
argv[1] = NULL;
}
else
{
search = strcpy(search, default_test_string);
}
f = fopen("trie.txt", "r");
if (NULL == f)
{
printf("文件打开错误,请检查。/n");
exit(-1);
}
root = (struct node*)malloc(sizeof(struct node));
init(root);
word = (char *)malloc(10);
while (fscanf(f, "%d %s", &id, word)!=-1)
{
printf("读取到:%d %s/n", id, word);
addvalue(id, word, root);
if (word)
{
free(word);
}
word = (char *)malloc(10);
}
if (f)
{
fclose(f);
}
printf("***search test***/n");
s = lookup(search);
if (NULL==s || -1==s->id)
{
printf("没有找到[ %s ]./n", search);
exit(-1);
}
printf("Find[%s]: Id is %d/n", search, s->id);
return 0;
}
/*初始化,使新建立的结构中每个数组元素的指针均为null*/
void init(struct node* nd)
{
int i=0;
for (i=0 ;i<256 ;i++ )
{
nd->child[i] = NULL;
}
}
程序并没有考虑过多的安全或者细节问题,只是大致实现了而已,估计在正确的情况下效率是高的。测试仅仅使用了如下的测试文件(如果命令行没有参数,如程序将测试“美国”的搜索)-----trie.txt:
1234 China
1345 RPC
1987 中华
2356 民族
4578 振兴
9876 中国
文件中都是这样的格式“id 关键字”。献丑了,还希望各位多多指教。以前用java实现了256路trie的,当时觉得比现在简单多了,C语言实在有点麻烦啊。我也还没有入道。