一.這一部曲是緊接第二部沒有介紹完的內容,主要是函數接口實體的實現,代碼比較多,如果沒有看前兩部曲的先去看看,再來看這里,不然不好理解,話不說多上代碼,
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,運行結果在第二部曲中有描述,本人目前換有一個計划,那就是監聽鍵盤輸入以及獲取聊天信息,有意的朋友們歡迎一起交流,再次感謝大家。
