一.这一部曲是紧接第二部没有介绍完的内容,主要是函数接口实体的实现,代码比较多,如果没有看前两部曲的先去看看,再来看这里,不然不好理解,话不说多上代码,
1 #define _CRT_SECURE_NO_WARNINGS
2 #include "dict.h"
3
4
5
6
7
8 /**************函数实现************************/
9 /*统计文件中单词数量,返回单词数量*/
10 int statWordCount(char *filaename)
11 {
12 FILE *F = fopen(filaename, "r");
13 if (F == NULL)
14 {
15 printf("文件打开失败");
16 return -1;
17 }
18 else
19 {
20 int num = 0;
21 while (!feof(F))
22 {
23 char buf[275];
24 fgets(buf, 275, F);
25 num++;
26 }
27 fclose(F);
28 return num / 2;//两行对应一个单词
29
30 }
31 }
32 /*加载文本词库文件*/
33 void loadTextFile(char *filename)
34 {
35 LEN = statWordCount(filename);//计算单词数量
36 mallocForSArra(LEN);//为单词结构体数组分配内存
37 FILE *F = fopen(filename, "r");
38 if (F == NULL)
39 {
40 printf("加载文件失败");
41 return;
42 }
43 createInitArray(F);//创建并初始化结构体数组
44 printf("OK\n");
45
46
47
48 }
49 /*加载二进制词库文件*/
50 void loadBinFile(char *filename)
51 {
52 FILE *F = fopen(filename, "rb");
53 if (F == NULL)
54 {
55 printf("打开文件失败");
56 return;
57 }
58
59 createInitBinArr(F);
60
61
62
63
64 }
65 /*为长度为len的结构体数组分配内存*/
66 void mallocForSArra(int len)
67 {
68 DICT = (SWORD *)malloc(sizeof(SWORD)*len);
69 }
70 /*对结构体dict数组进行排序,使用插入排序*/
71 void sortStructArr(SWORD * dict)
72 {
73 SWORD SW;
74 int j;
75 int i;
76 for (i = 1; i < LEN; i++)
77 {
78 SW = dict[i];
79 for (j = i; j>0 && wordcmp(dict[j-1],SW) > 0; j--)
80 {
81 dict[j] = dict[j - 1];
82 }
83 dict[j] = SW;
84 }
85 printf("ok");
86
87 }
88 /*输入模块,返回输入字符串*/
89 char *getInput(char *p)
90 {
91
92 scanf("%s",p);
93 //printf("%s", p);
94 return p;
95 }
96 /*输出模块,输出一个结构体*/
97 void setOutput(SWORD *word)
98 {
99 if (word == NULL)
100 {
101 printf("没有找到您输入的单词\n");
102 return;
103 }
104 printf("\n%s", word->key);
105 int len = word->count_trans;
106 printf("\n解释:\n");
107 for (int i = 0; i < len; i++)
108 {
109 printf("\n\t%s", word->trans[i]);
110 }
111
112 }
113 /*查询模块,使用二分法,据关键词key在词库里查询,找到返回这个结构体位置,否则返回NULL*/
114 SWORD *searchWord(char *key)
115 {
116 //printf("%s\n",key);
117 //int low = 0;
118 //int high = LEN;
119 //while (low < high)
120 //{
121 // int mid = (low + high) / 2;
122
123 // if (strcmp(key,DICT[mid].key) == 0)
124 // {
125 // printf("%s", DICT[mid].key);
126 // return DICT + mid;
127
128 // }
129 // else if (strcmp(key, DICT[mid].key) > 0)
130 // {
131 // low = mid + 1;
132 // }
133 // else
134 // {
135 // high = mid - 1;
136 // printf("%s*********", DICT[mid].key);
137 //
138 // }
139 //}
140 //int len = strlen(key);
141 //int dictlen = strlen(DICT[0].key);
142 //printf("%d\t%d", len, dictlen);
143 //printf("%s*********", DICT[0].key);
144 for (int i = 0; i < LEN; i++)
145 {
146 if (strcmp(key, DICT[i].key) == 0)
147 {
148 return DICT + i;
149 }
150
151
152
153 }
154
155 return NULL;
156
157 }
158 /*从输入获取要添加的单词*/
159 void getWord(SWORD *word)
160 {
161
162
163
164 printf("请输入要添加的单词(输入#over结束添加):");
165 scanf("%s", word->key);
166
167 printf("%s", word->key);
168
169 printf("请输入解释数量:");
170 scanf("%d", &(word->count_trans));
171 for (int i = 0; i < word->count_trans; i++)
172 {
173 printf("请输入第%d条解释:",i+1);
174 scanf("%s", (word->trans)[i]);
175 }
176 printf("hello");
177
178
179 }
180
181 /*添加单词word到结构体数组,弃用*/
182 void addWordToArr(SWORD *word)
183 {
184 //给词库添加单词
185 //int len = (*word).count_trans;
186
187 //puts((*word).key);
188 //for (int i = 0; i < len; i++)
189 //{
190 // puts((*word).trans[i]);
191 //}
192
193
194 //printf("%d\n", LEN);
195 //printf("%s\n", DICT[LEN - 1].key);
196 //printf("%d\n", DICT[LEN - 1].count_trans);
197 //for (size_t i = 0; i < DICT[LEN - 1].count_trans; i++)
198 //{
199 // printf("%s\n", DICT[LEN - 1].trans[i]);
200 //}
201 LEN = LEN + 1;
202 DICT = (SWORD *)realloc(DICT, LEN);
203 DICT[10000 - 1] = *word;
204
205
206 //puts((*word).key);
207 //for (int i = 0; i < len; i++)
208 //{
209 // puts((*word).trans[i]);
210 //}
211 //printf("%d\n", (*word).count_trans);
212
213 //int keylen = strlen((*word).key)+1;
214 //分配单词空间并填充
215 //DICT[LEN - 1].key = (char *)malloc(sizeof(char) * keylen);
216 //strcpy(DICT[LEN - 1].key, word->key);
217 //DICT[LEN - 1].key[keylen - 1] = '\0';
218 ////解释长度
219 //int transnum = word->count_trans;
220 //DICT[LEN - 1].count_trans = transnum;
221
222 //DICT[LEN - 1].trans = (char **)malloc(sizeof(char *)*transnum);
223 ////解释空间分配与填充
224 //for (int i = 0; i < transnum; i++)
225 //{
226 // int trlen = strlen(word->trans[i])+1;
227 // DICT[LEN - 1].trans[i] = (char *)malloc(sizeof(char)* trlen);
228 // strcpy(DICT[LEN - 1].trans[i], word->trans[i]);
229 // DICT[LEN - 1].trans[i][trlen - 1] = '\0';
230 //}
231
232 }
233 /*保存一个单词到文件*/
234 void saveWord(char *filename,SWORD *sw)
235 {
236 FILE *F = NULL;
237 if (!_access(filename, 0))//如果文件存在
238 {
239 F = fopen(filename, "a");
240 if (F == NULL)
241 {
242 printf("保存词库到文件失败");
243 return;
244 }
245
246 char str[50];
247 sprintf(str, "#%s", sw->key);
248 fputs(str, F);
249
250 char trans[200] = "";
251 for (int i = 0; i < sw->count_trans; i++)
252 {
253 char strs[50];
254 if (i == 0)
255 {
256 sprintf(strs, "Trans:%s", sw->trans[i]);
257 }
258 else
259 {
260 sprintf(strs, "@%s", sw->trans[i]);
261 }
262 strcat(trans, str);
263
264 }
265 fputs(trans, F);//将解释写入文件
266
267
268 fclose(F);
269
270 }
271 else
272 {
273 F = fopen(filename, "w");
274 if (F == NULL)
275 {
276 printf("保存词库到文件失败");
277 return;
278 }
279
280 char str[50];
281 sprintf(str, "#%s", sw->key);
282 fputs(str, F);
283
284 char trans[200] = "";
285 for (int i = 0; i < sw->count_trans; i++)
286 {
287 char strs[50];
288 if (i == 0)
289 {
290 sprintf(strs, "Trans:%s", sw->trans[i]);
291 }
292 else
293 {
294 sprintf(strs, "@%s", sw->trans[i]);
295 }
296 strcat(trans, str);
297
298 }
299 fputs(trans, F);//将解释写入文件
300
301
302 fclose(F);
303 }
304
305
306 }
307 /*生成二进制的词库文件,30位字符块大小*/
308 void createBinFile(SWORD *word)
309 {
310 FILE *F = fopen(dictbitname, "wb");
311 if (F == NULL)
312 {
313 printf("打开文件失败");
314 return;
315 }
316 printf("打开文件成功");
317 fwrite(&LEN, sizeof(int), 1, F);//前四个字节存储单词个数
318 printf("写入长度成功");
319 for (; word <= DICT+LEN-1; word += 1)
320 {
321 fwrite(word->key, sizeof(char),50, F);
322 //printf("写入单词成功");
323 fwrite(&(word->count_trans), sizeof(int),1, F);
324
325 //printf("写入解释数量%d成功", word->count_trans);
326 for (int i = 0; i < word->count_trans; i++)
327 {
328
329
330 fwrite(word->trans+i, sizeof(char), 50, F);
331 //printf("\n写入解释成功");
332
333
334
335 }
336 }
337 fclose(F);
338
339 }
340
341 /*计算一个字符串里某个ch字符的个数*/
342 int calcNumber(char *str,char ch)
343 {
344 int num = 0;
345 for (char *p =str; *p != '\0'; p++)
346 {
347 if (*p == ch)
348 {
349 num++;
350 }
351 }
352 return num;
353 }
354 /*从字符串str中取出字符ch后面的字符串*/
355 char *rearstr(char *str, char ch,int *pos)
356 {
357 char *p = strrchr(str, ch);
358 *pos = p - str;
359 p = p + 1;
360 return p;
361 }
362
363 /*创建并初始化词库结构体数组*/
364 void createInitArray(FILE *F)
365 {
366 for (int i = 0; i < LEN; i++)
367 {
368 char str[500] = { 0 };
369 fgets(str, 500, F);
370 char *temp = str + 1;
371 int length = strlen(temp);//分配空间长度排除#号
372 DICT[i].key = (char *)malloc(sizeof(char)*length);//一条关键字分配内存
373 strcpy(DICT[i].key, temp);
374 DICT[i].key[length - 1] = '\0';//关键词
375
376 char strtrans[500] = { 0 };
377 fgets(strtrans, 500, F);
378
379 int len = strlen(strtrans) + 1;//加1是考虑到'\0'
380 char *ch = (char *)malloc(sizeof(char)*len);//给每一个指针所指的字符串分配内存
381 strcpy(ch, strtrans);//将数组里的字符串拷贝到ch中但不带'\0'
382 ch[len - 1] = '\0';//添加字符串结束标记
383
384 int number = calcNumber(strtrans, '@') + 1;
385 DICT[i].count_trans = number;//解释的数量
386
387 DICT[i].trans = (char **)malloc(sizeof(char *)*number);
388
389 char *transtemp = strtrans + 6;
390 char *tok = strtok(transtemp, "@");
391 int j = 0;
392 while (tok != NULL)
393 {
394 int translen = strlen(tok)+1;
395 DICT[i].trans[j] = (char *)malloc(sizeof(char)*translen);//给每一条解释分配存储空间
396 strcpy(DICT[i].trans[j], tok);
397 DICT[i].trans[j][translen - 1] = '\0';
398
399 tok = strtok(NULL, "@");
400 j++;
401 }
402
403
404 }
405 }
406
407 /*比较两个SWORD单词的大小,前一个大于后一个返回1,前一个小于后一个返回-1,前一个等于后一个返回0*/
408 int wordcmp(SWORD wordf, SWORD wordr)
409 {
410 if (strcmp(wordf.key, wordr.key) == 0)
411 {
412 return 0;
413 }
414 else if (strcmp(wordf.key, wordr.key) > 0)
415 {
416 return 1;
417 }
418 else
419 {
420 return -1;
421 }
422 }
423
424 /*创建并初始化二进制加载文件对应的的数组,30为写入块大小*/
425 void createInitBinArr(FILE *F)
426 {
427 fread(&LEN, sizeof(int), 1, F);//先读取四个字节初始化词库长度
428 mallocForSArra(LEN);//为词库数组分配内存
429 SWORD *TEMP = DICT;
430 while (!feof(F))//不在文件末尾
431 {
432
433
434 TEMP->key = (char *)malloc(sizeof(char)* 50);//一条关键字分配内存
435 fread(TEMP->key, sizeof(char), 50, F);
436
437 fread(&(TEMP->count_trans), sizeof(int), 1, F);//读取解释数量
438 TEMP->trans = (char **)malloc(sizeof(char *)*(TEMP->count_trans));
439
440 for (int i = 0; i < TEMP->count_trans; i++)
441 {
442 TEMP->trans[i] = (char *)malloc(sizeof(char)*50);//给每一条解释分配存储空间
443 fread(TEMP->trans[i], sizeof(char), 50, F);
444 }
445
446
447
448 }
449 }
450 /*查询模块函数*/
451 void searchModel()
452 {
453
454 //开始查询
455 char p[100] = { 0 };
456 printf("请输入要查找的单词:");
457 char *instr = getInput(p);
458 while (strcmp(instr, "#exit") != 0)//不等于#exit就一直查找
459 {
460 /* printf("%s", instr);*/
461
462 SWORD *wd = searchWord(instr);
463
464 setOutput(wd);
465 printf("请输入要查找的单词(输入#exit退出查询):");
466 instr = getInput(p);
467 }
468
469 }
470 /*添加单词模块函数*/
471 void addWordModel()
472 {
473
474
475 SWORD word;
476 word.key = (char *)malloc(sizeof(char)* 50);//开辟单词输入缓冲区
477
478 word.trans = (char **)malloc(sizeof(char *)* 10);//开辟解释输入缓冲区
479
480 for (int i = 0; i < 10; i++)
481 {
482 word.trans[i] = (char *)malloc(sizeof(char)* 50);
483 }
484 //char key[100] = {0};
485 //char trans[10][50] = {0};
486 //word.key = key;
487 //word.trans = trans;
488 // getWord(&word);
489
490 //int len = word.count_trans;
491 //puts(word.key);
492 //for (int i = 0; i < len; i++)
493 //{
494 // puts(word.trans[i]);
495 //}
496
497
498
499 do
500 {
501
502 getWord(&word);//获取单词
503
504 printf("是否保存词库数组到文件(输入0退出程序,1保存,2不保存):0/1/2?\n");
505
506 int yesorno;
507 scanf("%d", &yesorno);
508 if (yesorno == 1)
509 {
510 saveWord(dicttxtname, &word);/*保存词库结构数组到文件*/
511 }
512 else if (yesorno == 0)
513 {
514 exit(0);
515 }
516 else
517 {
518
519 }
520
521
522 } while (strcmp(word.key, "#over") != 0);
523
524
525
526
527 }
二.至此整个电子词典项目介绍完了,在加载二进制文件和读取时有些小bug,运行结果在第二部曲中有描述,本人目前换有一个计划,那就是监听键盘输入以及获取聊天信息,有意的朋友们欢迎一起交流,再次感谢大家。