项目实现第二阶段
实现代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char * key; //单词的指针
int ntrans; //解释的个数
char ** trans; //解释的指针数组
}WORD, * pW;
//词典使用帮助信息
void show_help()
{
printf("./main -opt <-r/-w>\n");
printf("-text load dict.txt and use\n");
printf("-bin <-r/-w>load dict.dat and use\n");
printf(" -r read dict.dat and use\n");
printf(" -w read dict.txt and creat dict.dat\n");
}
//打印出错信息
void sys_err(char * str)
{
printf("%s \n",str);
exit(-1);
}
//获取单词的个数
int get_word_count(char * pathname)
{
int len = 0;
char buf[1024];
FILE * fp = fopen(pathname , "r");
if(!fp)
sys_err("open file error!");
while( fgets( buf , sizeof(buf) , fp) != NULL)
{
len++;
}
return len / 2;
}
//为每个单词的解释开辟存储空间
int trans_assign(pW w , char * str)
{
int n = 0 , i = 0;
char *tmp[50]; //临时指针数组,用来存储每个解释的指针【思想好】
w->ntrans = 0;
char *p = strtok( str , "@");
if(!p) return 0;
tmp[n++] = p;
while( (p = strtok(NULL , "@")) != NULL)
tmp[n++] = p;
w->ntrans = n;
w->trans = malloc( n * sizeof(char *));
for( i = 0 ; i < n ; ++i)
{
w->trans[i] = malloc( strlen(tmp[i]) +1 );
strcpy(w->trans[i] , tmp[i]);
}
return n;
}
//把文本txt的内容初始化到结构体数组里
void init_word_text(char * pathname , pW w , int n)
{
int i , len;
char buf[1024];
FILE * fp = fopen( pathname , "r");
if(!fp)
sys_err("open file error!");
for( i = 0 ; i < n ; ++i)
{
// word
fgets( buf , sizeof(buf) , fp);
len = strlen(buf);
buf[ len - 1] = '\0'; //把 \n 换成 \0
w[i].key = malloc( len - 1);
strcpy( w[i].key , buf + 1);
// trans
fgets( buf , sizeof(buf) , fp);
len = strlen(buf);
buf[ len - 1] = '\0';
trans_assign( &w[i] , buf + 6 );//+6表示把解释的Trans:去掉
}
fclose(fp);
}
//展示每一个单词和解释
void show_word(WORD w)
{
int i;
// printf("%s\n" , w.key);
// printf("%d\n" , w.ntrans);
printf("\n");
for( i = 0 ; i < w.ntrans ; ++i)
printf("%-3d:%s\n",i+1,w.trans[i]);
}
//展示所有的单词及解释
void show_word_arr(pW w , int n)
{
int i;
for( i = 0 ; i < n ; ++i)
show_word(w[i]);
}
//交换两个结构体
void swap(pW m , pW n)
{
WORD temp = *m;
*m = *n;
*n = temp;
}
//用来查找快速排序的分割元素
int partition(pW w , int l , int r)
{
int i,j;
for(i = l+1 , j = l ; i <= r ; ++i)
{
if(strcmp(w[i].key , w[l].key) < 0)
{
swap( &w[i] , &w[++j]);
}
}
swap( &w[l] , &w[j]);
return j;
}
//快速排序
void quick_sort(pW w , int l , int r)
{
if( l >= r) return;
int k = partition(w , l , r);
quick_sort(w , l , k-1);
quick_sort(w , k+1 , r);
}
//排序接口函数
void sort_word(pW w , int n)
{
quick_sort( w , 0 , n-1);
printf("初始化完成\n");
}
//判断用户是否退出
int is_exit(char * str)
{
if(strcmp(str,"exit") == 0)
return 1;
else
return 0;
}
//查找用户输入的单词,二分查找法
int search_word(pW w , int n , char * str)
{
int l = 0, r = n -1, mid;
while( l <= r)
{
mid = (l+r)/2;
if(strcmp(w[mid].key , str) < 0)
l = mid +1;
else if(strcmp(w[mid].key , str) > 0)
r = mid -1;
else
return mid;
}
return -1;
}
//释放每个单词申请的动态内存
void free_word(pW w , int n)
{
int i,j;
for(i = 0 ; i < n ; ++i)
{
free(w[i].key);
for(j = 0 ; j < n ; ++j)
{
free(w[i].trans[j]);
}
free(w[i].trans);
}
}
//把结构体数组写到二进制文件里
void write_word_bin(char * pathname , pW word , int n)
{
int i , j , len;
FILE * fp = fopen( pathname , "w");//打开dict.bin准备写入
fwrite( &n , sizeof(n) , 1 , fp);//先把总行数写进去
for( i = 0 ; i < n ; ++i)
{
len = strlen(word[i].key) + 1;// +1 这个坑啊
fwrite( &len ,sizeof( int ), 1,fp ); // 写进去单词的长度
fwrite( word[i].key , len , 1 , fp); //写进去单词的内容
fwrite( &word[i].ntrans , sizeof( int ) , 1 , fp);//写进去解释的个数
for( j = 0 ; j < word[i].ntrans ; ++j)
{
len = strlen( word[i].trans[j] ) + 1;//计算出每个解释的长度
fwrite( &len ,sizeof( int ), 1, fp );//写进去每个解释的长度
fwrite( word[i].trans[j] , len , 1 ,fp );//写进去每个解释的内容
}
}
fclose(fp);
}
//从二进制文件读到结构体数组内
void read_from_bin(char * pathname , pW word , int n)
{
int i , j , len;
FILE * fp = fopen( pathname , "r");//打开dict.bin
fseek( fp , 4 , SEEK_SET);//偏移4个字节,因为之前取出4个总行数了
for( i = 0 ; i < n ; ++i)
{
fread(&len ,sizeof( int ), 1, fp );//把单词的长度读取出来
word[i].key = malloc( len ); //为单词开辟存储空间
fread( word[i].key , len , 1 , fp); //把单词读取出来
fread( &word[i].ntrans , sizeof( int ) , 1 , fp);//把解释个数读取过来
word[i].trans = malloc( word[i].ntrans * sizeof(char * ));//开辟解释空间
for( j = 0 ; j < word[i].ntrans ; ++j)
{
fread( &len ,sizeof( int ), 1, fp );//读取每个解释的长度
word[i].trans[j] = malloc( len );//开辟每个解释的空间
fread( word[i].trans[j] , len , 1 ,fp );//把每个解释读取出来
}
}
fclose(fp);
}
int main(int argc , char * argv[])
{
if(argc < 2) //如果命令行参数小于2,退出
{
show_help();
return -1;
}
int n , res , m;
char buf[1024];
pW word = NULL;
if( strcmp(argv[1] , "-text") == 0) //但参数为-text时候,从文本读
{
n = get_word_count("dict.txt");
word = malloc( n * sizeof(*word) );
init_word_text("dict.txt", word , n);
sort_word( word , n);
// show_word_arr( word , n);
}
else if( strcmp(argv[1] , "-bin") == 0)
{
if(argv[2])
{
if( strcmp(argv[2] , "-r") == 0)
{
FILE * fp = fopen( "dict.bin" , "r");//打开dict.bin
if(!fp) sys_err("not bin file! now please\t-bin -w");
fread( &n , sizeof( int ) , 1 , fp); //读取有多少行
fclose( fp );
word = malloc( n * sizeof(*word));//开辟结构体数组内存空间
read_from_bin("dict.bin" , word , n);
}
else if( strcmp(argv[2] , "-w") == 0)
{
n = get_word_count("dict.txt");
word = malloc( n * sizeof(*word));
init_word_text("dict.txt",word,n);
sort_word( word , n);
write_word_bin("dict.bin" , word , n);
}
else
{
show_help();
return -1;
}
}
else
{
show_help();
return -1;
}
}
else
{
show_help();
return -1;
}
while(1)
{
printf("please input your word : \n");
fgets(buf,sizeof(buf),stdin);
m = strlen(buf);
buf[m-1] = '\0';
if(is_exit(buf))
break;
res = search_word( word , n , buf);
if(res != -1)
show_word(word[res]);
else
printf("\nnot find\n");
}
free_word(word , n);
free(word);
return 0;
}
附件列表