/*****************************************************************
程序名:单词吸血鬼
作者: 常涛
GNU认证
程序功能简介:可以提取出以ASCII码保存的文件中的单词并以字典顺序输出
*****************************************************************/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
struct node
{
struct node *left; /* tree to the left */
struct node *right; /* three to the right */
char *word; /* word for this tree */
};
/*the top of the tree */
static struct node *root=NULL;
/****************************************************
* 内存出错报警 *
****************************************************/
void memory_error(char* text)
{
fprintf(stderr,text);
exit(8);
}
/****************************************************
* save_string --将string保存到堆防止栈溢出. *
* *
* 参数: *
* string -- 要存的字符串 . *
* *
* 返回值: *
* 指针 *
****************************************************/
char *save_string(char *string)
{
char *new_string; /*初学者易犯的错误,对没有初始化的指针赋值*/
new_string = malloc((unsigned)(strlen(string))+1); //关键步骤,new和malloc一样,都是分配在堆的
if(new_string == NULL)
{
memory_error("没有足够的内存用于分配");
}
strcpy(new_string, string); //相当有用的函数
return(new_string);
}
/****************************************************
* enter -- 向树中加入一个值 *
* *
* 参数 *
* node -- 正在操作的树 *
* word -- 要输入的值 *
****************************************************/
void enter(struct node **node, char *word)
{
int result; /*暂存比较结果p*/
char *save_string(char *); /*s数据入堆*/
/*
* 如果满树开始建立新的内存块
*/
if((*node) == NULL)
{
(*node) = malloc(sizeof(struct node));
if((*node) == NULL)
{
memory_error("没有足够的内存用于分配");
return;
}
(*node) -> left = NULL;
(*node) -> right = NULL;
(*node) -> word = save_string(word); //这步因该想办法理解它的好处
}
/* 选择数据保存的位置 */
result = strcmp((*node) -> word, word);
/*如果已经存在要存入的数据,则返回 */
if(result == 0) return;
/* 数据将会依据result的值来选择存储点 */
if(result < 0)
{
enter(&(*node) -> right, word);
}
else
{
enter(&(*node) -> left, word);
}
}
/*****************************************************************
* scan -- 扫描并读入文件 . *
* *
* 参数: *
* name -- 要读人的文件名和 *
*****************************************************************/
void scan(char *name)
{
char word[100]; /*每次操作的数据*/
int index=0; /* 字符索引 */
int ch = 0; /* 当前字符r */
FILE *in_file; /* 输入的文件指针 */
in_file = fopen(name,"r");
if (in_file == NULL)
{
fprintf(stderr,"Error:Unable to open %s/n", name);
exit(8);
}
while(1)
{
while(1)
{
ch = fgetc(in_file);
if(isalpha(ch) || (ch == EOF))
{
break;
}
}
if(ch == EOF) break;
word[0] = ch;
for(index = 1; index < sizeof(word); ++index)
{
ch = fgetc(in_file);
word[index]=ch;
if(!isalpha(ch)) break;
}
word[index] = '/0';
enter(&root,word);
}
fclose(in_file);
}
/*************************************************************
* print_tree -- 输出整个树 *
* *
* 参数 *
* top -- 要输出树的根节点 *
*************************************************************/
void print_tree(struct node *top)
{
if(top == NULL) return; /* 元树则返回 */
print_tree(top -> left);
printf("%s/n",top -> word);
print_tree(top -> right);
}
int main(int argc, char *argv[])
{
if(argc !=2)
{
fprintf(stderr,"错误:没有足够的参数/n");
fprintf(stderr," 在命令行窗口输入 /n");
fprintf(stderr," 用法如下:/n");
fprintf(stderr," wordsvampire '文件名'(文件名因该是全称就是要有扩展名)/n");
system("pause");
exit(8);
}
scan(argv[1]);
print_tree(root);
system("pause");
return(0);
}