功能
实现输入英语单词输出对应的中文意思
算法
1、导入整理好的英汉小词典文件到哈希表中
2、建立以单词首字母为key的索引表
3、获取输入单词的key,查找索引表,找到中文释义输出
关键点
1、文件的读入操作:fopen()、fgets()
2、对字符串的处理及存储
3、哈希表的建立、查询
两个函数
#include <stdio.h>
FILE *fopen(const char *path, const char *mode);
//示例
FILE *f = fopen("./xxx.txt","r");//文件的相对路径或绝对路径
if(f==NULL)printf("文件打开失败!\n");
FILE :数据对象类型(控制块),记录一个流的状态
流:逻辑数据流,数据流入或流出缓冲区,是一块堆区的内存空间
文本流:文本行的有序字符序列,每一行有换行符
二进制流:字符的有序序列
函数fopen打开名为path(路径加文件名.扩展名)的文件,并把这个文件和一个流相关联。参数mode指向以下列出的字符开头的字符串:
“r”:以只读权限打开path的文件
“rb”:以只读权限打开path的二进制文件
函数fopen返回指向控制流的对象的指针。如果打开文件失败,返回NULL
#include <stdio.h>
char *fgets(char *s,int n,FILE *stream);
//示例
char s1[10],s2[20];
FILE *f = fopen("./xxx.txt","r");
fgets(s1,10,f);//从文件f中读取一行字符串并存入s1数组中
if(fgets(s2,20,stdin)!=NULL){//从标准输入流(键盘)读取字符并存入s2数组中
语句块;
}
函数fgets从stream指向的流中读取字符,读取字符的数目最多为n-1,然后将字符写入到s指向的数组中。读入换行符('\n')(保留)或者文件结束不再读取字符。最后一个字符写入数组后立即写入一个'\0'。
△linux文件一行末尾以\n结尾、windows以\r结尾、unix以\r\n结尾
如果执行成功,返回s;如果遇到文件结束并没有向数组中写入字符,则数组的内容不变且返回一个空指针;如果操作发生读错误,则数组内容不确定且返回一个空指针。
stream指针有以下几个:
stderr:指向标准错误流对象
stdin:指向标准输入流对象
stdout:指向标准输出流对象
<code>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100 //文本一行字符串读取长度限制
#define INDEX 26 //索引表容量
#define EN 30 //英文字符串长度限制
#define CN 70 //中文字符串长度限制
typedef struct vocabulary{
char key;
char en_word[EN];//存储英文
char ch_word[CN];//存储中文
struct vocabulary *next;
}Word,*WORD;
//创建Hash表
WORD *create()
{
int i;
WORD *hash = (WORD*)malloc(INDEX);
for(i=0;i<INDEX;i++)
{
hash[i] = (WORD)malloc(sizeof(Word));
hash[i]->key = 'a'+i;
memset(hash[i]->en_word,0,sizeof(char)*EN);
memset(hash[i]->ch_word,0,sizeof(char)*CN);
hash[i]->next = NULL;
}
return hash;
}
//插入单词到Hash表
void insert(WORD* hash,char *word)
{
//拆分中英文
char en[EN]="",ch[CN]="";
int en_len=0,ch_len=0;
char *p=word;
while(*p!=' ')
{
p++;
en_len++;
}
strncpy(en,word,en_len);//得到英文
while(*p==' ')p++;
char *c=p;
while(*p!='\0')
{
p++;
ch_len++;
}
strncpy(ch,c,ch_len);//得到释义中文
//获取key
char key[2]="";
strncpy(key,word,1);
//创建单词结点
WORD node = (WORD)malloc(sizeof(Word));
node->key = key[0];
strcpy(node->en_word,en);
strcpy(node->ch_word,ch);
//strcpy(node->en_word,word);//test
//strcpy(node->ch_word,word);//test
//头插法
WORD head = hash[node->key-'a'];
node->next = head->next;
head->next = node;
}
//打印Hash表
void printHash(WORD* hash)
{
int i;
WORD h;
for(i=0;i<INDEX;i++)
{
h = hash[i];
while(h->next!=NULL)
{
h = h->next;
printf("%s\n",h->en_word);
//printf("%d\n",strlen(h->en_word));//test
printf("%s\n",h->ch_word);
}
}
}
//查询英文的释义
void find(WORD* hash,char *vocabulary)
{
char key[2]="";
strncpy(key,vocabulary,1);
WORD p=hash[key[0]-'a']->next;
//printf("%c %d\n",key[0],key[0]-'a');//test
while(p!=NULL)
{
if(!strcmp(p->en_word,vocabulary))
{
printf("%s",p->ch_word);
return;
}
p=p->next;
}
printf("词典中没有这个单词\n");
}
int main(int argc, const char *argv[])
{
FILE *f = fopen("./牛津英汉小词典.txt","r");
if(f==NULL){
printf("读取失败\n");
return 0;
}
char word[SIZE] = "";
WORD *hash = create();
while(fgets(word,SIZE,f)!=NULL)
{
insert(hash,word);
//printf("%s",word);//test
}
fclose(f);//读取完毕释放空间
printHash(hash);//test
char vocabulary[EN]="";
printf("请输入你要查询的英文单词-->");
if(fgets(vocabulary,EN,stdin)!=NULL){//会多读一个'\n'
vocabulary[strlen(vocabulary)-1] = '\0';
//printf("%d\n",strlen(vocabulary));//test
find(hash,vocabulary);
}
return 0;
}
调试
调试过程中出现过段错误
定位
这里出现段错误就2种可能:①哈希表中指针的错误访问;②字符串指针的越界
先将字符串处理的函数全部注释掉,再将英文中文整串字符串word都存入数组en_word和ch_word中,调用打印哈希表全部内容测试,发现没有问题,能全部打印
定位到
void insert(WORD* hash,char *word)
函数中的拆分中英文部分语句块
检查
①字符串的定义、及容量设置是否小了;②字符串处理函数strncpy()的用法是否无误
发现字符串的定义出错了,指针变量指向的空间里存储的内容成了一个字符串常量
错误定义如下:
char *en = "",*ch = ""; char *key = "";
修改正确如下:
char en[EN] = "",ch[CN] = ""; char key[2] = "";
测试
结果
请输入你要查询的英文单词-->cod
词典中没有这个单词
请输入你要查询的英文单词-->code
n.法规,代码,密码
本文链接:https://shengto.top/data_structure/hash_dictionary.html
转载时须注明出处及本声明