1/*
2 * dictionary.c
3 * ν΄μ ν
μ΄λΈμ νμ©ν μ€μ©μ μΈ μ¬μ (Dictionary) νλ‘κ·Έλ¨
4 *
5 * κΈ°λ₯:
6 * - λ¨μ΄ μΆκ°/κ²μ/μμ
7 * - μ 체 λͺ©λ‘ μΆλ ₯
8 * - νμΌ μ μ₯/λΆλ¬μ€κΈ°
9 * - λ¨μ΄ ν΅κ³ λ° κ²μ μ μ
10 * - λμλ¬Έμ κ΅¬λΆ μλ κ²μ
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <ctype.h>
17#include <stdbool.h>
18
19#define TABLE_SIZE 1000
20#define KEY_SIZE 100
21#define VALUE_SIZE 500
22#define FILENAME "dictionary.txt"
23
24// λ
Έλ ꡬ쑰체 (체μ΄λ λ°©μ)
25typedef struct Node {
26 char word[KEY_SIZE];
27 char meaning[VALUE_SIZE];
28 int search_count; // κ²μ νμ
29 struct Node *next;
30} Node;
31
32// μ¬μ ꡬ쑰체
33typedef struct {
34 Node *buckets[TABLE_SIZE];
35 int count;
36 int total_searches;
37} Dictionary;
38
39// ν΅κ³ ꡬ쑰체
40typedef struct {
41 char word[KEY_SIZE];
42 int count;
43} WordStat;
44
45// λμλ¬Έμ κ΅¬λΆ μλ djb2 ν΄μ ν¨μ
46unsigned int hash(const char *key) {
47 unsigned int hash = 5381;
48 while (*key) {
49 hash = ((hash << 5) + hash) + tolower((unsigned char)*key++);
50 }
51 return hash % TABLE_SIZE;
52}
53
54// μ¬μ μμ±
55Dictionary* dict_create(void) {
56 Dictionary *dict = calloc(1, sizeof(Dictionary));
57 if (!dict) {
58 fprintf(stderr, "λ©λͺ¨λ¦¬ ν λΉ μ€ν¨\n");
59 }
60 return dict;
61}
62
63// μ¬μ ν΄μ
64void dict_destroy(Dictionary *dict) {
65 if (!dict) return;
66
67 for (int i = 0; i < TABLE_SIZE; i++) {
68 Node *current = dict->buckets[i];
69 while (current) {
70 Node *next = current->next;
71 free(current);
72 current = next;
73 }
74 }
75 free(dict);
76}
77
78// λ¨μ΄ μΆκ° λλ μμ
79void dict_add(Dictionary *dict, const char *word, const char *meaning) {
80 if (!dict || !word || !meaning) return;
81
82 unsigned int index = hash(word);
83
84 // κΈ°μ‘΄ λ¨μ΄ νμΈ
85 Node *current = dict->buckets[index];
86 while (current) {
87 if (strcasecmp(current->word, word) == 0) {
88 // κΈ°μ‘΄ λ¨μ΄ μμ
89 strncpy(current->meaning, meaning, VALUE_SIZE - 1);
90 current->meaning[VALUE_SIZE - 1] = '\0';
91 printf("β '%s' μ
λ°μ΄νΈλ¨\n", word);
92 return;
93 }
94 current = current->next;
95 }
96
97 // μ λ¨μ΄ μΆκ°
98 Node *node = malloc(sizeof(Node));
99 if (!node) {
100 fprintf(stderr, "λ©λͺ¨λ¦¬ ν λΉ μ€ν¨\n");
101 return;
102 }
103
104 strncpy(node->word, word, KEY_SIZE - 1);
105 node->word[KEY_SIZE - 1] = '\0';
106 strncpy(node->meaning, meaning, VALUE_SIZE - 1);
107 node->meaning[VALUE_SIZE - 1] = '\0';
108 node->search_count = 0;
109
110 node->next = dict->buckets[index];
111 dict->buckets[index] = node;
112 dict->count++;
113
114 printf("β '%s' μΆκ°λ¨\n", word);
115}
116
117// λ¨μ΄ κ²μ
118char* dict_search(Dictionary *dict, const char *word) {
119 if (!dict || !word) return NULL;
120
121 unsigned int index = hash(word);
122
123 Node *current = dict->buckets[index];
124 while (current) {
125 if (strcasecmp(current->word, word) == 0) {
126 current->search_count++;
127 dict->total_searches++;
128 return current->meaning;
129 }
130 current = current->next;
131 }
132
133 return NULL;
134}
135
136// λ¨μ΄ μμ
137bool dict_delete(Dictionary *dict, const char *word) {
138 if (!dict || !word) return false;
139
140 unsigned int index = hash(word);
141
142 Node *current = dict->buckets[index];
143 Node *prev = NULL;
144
145 while (current) {
146 if (strcasecmp(current->word, word) == 0) {
147 if (prev) {
148 prev->next = current->next;
149 } else {
150 dict->buckets[index] = current->next;
151 }
152 free(current);
153 dict->count--;
154 printf("β '%s' μμ λ¨\n", word);
155 return true;
156 }
157 prev = current;
158 current = current->next;
159 }
160
161 printf("β '%s'μ(λ₯Ό) μ°Ύμ μ μμ΅λλ€\n", word);
162 return false;
163}
164
165// μ 체 λ¨μ΄ λͺ©λ‘ μΆλ ₯
166void dict_list(Dictionary *dict) {
167 if (!dict) return;
168
169 printf("\nββββββββββββββββββββββββββββββββββββββββββββββ\n");
170 printf("β μ¬μ λͺ©λ‘ (μ΄ %dκ°) β\n", dict->count);
171 printf("ββββββββββββββββββββββββββββββββββββββββββββββ\n\n");
172
173 if (dict->count == 0) {
174 printf(" (λΉμ΄μμ)\n");
175 return;
176 }
177
178 int num = 0;
179 for (int i = 0; i < TABLE_SIZE; i++) {
180 Node *current = dict->buckets[i];
181 while (current) {
182 printf(" %3d. %-20s : %s\n",
183 ++num, current->word, current->meaning);
184 current = current->next;
185 }
186 }
187}
188
189// νμΌμ μ μ₯
190bool dict_save(Dictionary *dict, const char *filename) {
191 if (!dict || !filename) return false;
192
193 FILE *fp = fopen(filename, "w");
194 if (!fp) {
195 fprintf(stderr, "νμΌ μ΄κΈ° μ€ν¨: %s\n", filename);
196 return false;
197 }
198
199 // ν€λ μμ±
200 fprintf(fp, "# Dictionary File\n");
201 fprintf(fp, "# Count: %d\n\n", dict->count);
202
203 // λͺ¨λ λ¨μ΄ μ μ₯
204 for (int i = 0; i < TABLE_SIZE; i++) {
205 Node *current = dict->buckets[i];
206 while (current) {
207 fprintf(fp, "%s|%s|%d\n",
208 current->word, current->meaning, current->search_count);
209 current = current->next;
210 }
211 }
212
213 fclose(fp);
214 printf("β %dκ° λ¨μ΄λ₯Ό '%s'μ μ μ₯νμ΅λλ€\n", dict->count, filename);
215 return true;
216}
217
218// νμΌμμ λΆλ¬μ€κΈ°
219bool dict_load(Dictionary *dict, const char *filename) {
220 if (!dict || !filename) return false;
221
222 FILE *fp = fopen(filename, "r");
223 if (!fp) {
224 fprintf(stderr, "νμΌ μ΄κΈ° μ€ν¨: %s\n", filename);
225 return false;
226 }
227
228 char line[KEY_SIZE + VALUE_SIZE + 50];
229 int loaded = 0;
230
231 while (fgets(line, sizeof(line), fp)) {
232 // μ£Όμ λ° λΉ μ€ κ±΄λλ°κΈ°
233 if (line[0] == '#' || line[0] == '\n') continue;
234
235 // μ€λ°κΏ μ κ±°
236 line[strcspn(line, "\n")] = '\0';
237
238 // νμ±: word|meaning|search_count
239 char word[KEY_SIZE], meaning[VALUE_SIZE];
240 int search_count = 0;
241
242 char *token = strtok(line, "|");
243 if (token) strncpy(word, token, KEY_SIZE - 1);
244
245 token = strtok(NULL, "|");
246 if (token) strncpy(meaning, token, VALUE_SIZE - 1);
247
248 token = strtok(NULL, "|");
249 if (token) search_count = atoi(token);
250
251 // μ¬μ μ μΆκ° (μΆλ ₯ μμ΄)
252 unsigned int index = hash(word);
253 Node *node = malloc(sizeof(Node));
254 if (!node) continue;
255
256 strncpy(node->word, word, KEY_SIZE - 1);
257 node->word[KEY_SIZE - 1] = '\0';
258 strncpy(node->meaning, meaning, VALUE_SIZE - 1);
259 node->meaning[VALUE_SIZE - 1] = '\0';
260 node->search_count = search_count;
261
262 node->next = dict->buckets[index];
263 dict->buckets[index] = node;
264 dict->count++;
265 loaded++;
266 }
267
268 fclose(fp);
269 printf("β %dκ° λ¨μ΄λ₯Ό '%s'μμ λΆλ¬μμ΅λλ€\n", loaded, filename);
270 return true;
271}
272
273// κ²μ μ μ (λΆλΆ μΌμΉ)
274void dict_suggest(Dictionary *dict, const char *prefix) {
275 if (!dict || !prefix) return;
276
277 printf("\n'%s'λ‘ μμνλ λ¨μ΄:\n", prefix);
278
279 int found = 0;
280 int len = strlen(prefix);
281
282 for (int i = 0; i < TABLE_SIZE; i++) {
283 Node *current = dict->buckets[i];
284 while (current) {
285 if (strncasecmp(current->word, prefix, len) == 0) {
286 printf(" - %s\n", current->word);
287 found++;
288 }
289 current = current->next;
290 }
291 }
292
293 if (found == 0) {
294 printf(" (μμ)\n");
295 } else {
296 printf("μ΄ %dκ° λ°κ²¬\n", found);
297 }
298}
299
300// μΈκΈ° λ¨μ΄ ν΅κ³
301void dict_statistics(Dictionary *dict) {
302 if (!dict) return;
303
304 printf("\nββββββββββββββββββββββββββββββββββββββββββββββ\n");
305 printf("β μ¬μ ν΅κ³ μ 보 β\n");
306 printf("ββββββββββββββββββββββββββββββββββββββββββββββ\n\n");
307
308 printf("μ΄ λ¨μ΄ κ°μ: %d\n", dict->count);
309 printf("μ΄ κ²μ νμ: %d\n", dict->total_searches);
310
311 // κ²μ νμ μμΌλ‘ μ λ ¬ (Top 10)
312 WordStat *stats = malloc(sizeof(WordStat) * dict->count);
313 if (!stats) return;
314
315 int idx = 0;
316 for (int i = 0; i < TABLE_SIZE; i++) {
317 Node *current = dict->buckets[i];
318 while (current) {
319 strncpy(stats[idx].word, current->word, KEY_SIZE - 1);
320 stats[idx].count = current->search_count;
321 idx++;
322 current = current->next;
323 }
324 }
325
326 // λ²λΈ μ λ ¬ (κ°λ¨νκ²)
327 for (int i = 0; i < dict->count - 1; i++) {
328 for (int j = 0; j < dict->count - i - 1; j++) {
329 if (stats[j].count < stats[j + 1].count) {
330 WordStat temp = stats[j];
331 stats[j] = stats[j + 1];
332 stats[j + 1] = temp;
333 }
334 }
335 }
336
337 // Top 10 μΆλ ₯
338 printf("\nμΈκΈ° λ¨μ΄ Top 10:\n");
339 int limit = dict->count < 10 ? dict->count : 10;
340 for (int i = 0; i < limit; i++) {
341 if (stats[i].count > 0) {
342 printf(" %2d. %-20s (%dν)\n",
343 i + 1, stats[i].word, stats[i].count);
344 }
345 }
346
347 free(stats);
348}
349
350// λ©λ΄ μΆλ ₯
351void print_menu(void) {
352 printf("\nββββββββββββββββββββββββββββββββββββββββββββββ\n");
353 printf("β π κ°λ¨ν μ¬μ νλ‘κ·Έλ¨ β\n");
354 printf("β βββββββββββββββββββββββββββββββββββββββββββββ£\n");
355 printf("β 1. λ¨μ΄ μΆκ° β\n");
356 printf("β 2. λ¨μ΄ κ²μ β\n");
357 printf("β 3. λ¨μ΄ μμ β\n");
358 printf("β 4. μ 체 λͺ©λ‘ β\n");
359 printf("β 5. κ²μ μ μ β\n");
360 printf("β 6. ν΅κ³ 보기 β\n");
361 printf("β 7. νμΌ μ μ₯ β\n");
362 printf("β 8. νμΌ λΆλ¬μ€κΈ° β\n");
363 printf("β 0. μ’
λ£ β\n");
364 printf("ββββββββββββββββββββββββββββββββββββββββββββββ\n");
365}
366
367// μ
λ ₯ λ²νΌ λΉμ°κΈ°
368void clear_input(void) {
369 int c;
370 while ((c = getchar()) != '\n' && c != EOF);
371}
372
373// μν λ°μ΄ν° λ‘λ
374void load_sample_data(Dictionary *dict) {
375 dict_add(dict, "apple", "μ¬κ³Ό; μ₯λ―Έκ³Όμ λμ½κ΅λͺ©");
376 dict_add(dict, "book", "μ±
; μΈμλ¬Όμ μ λ³Έν κ²");
377 dict_add(dict, "computer", "μ»΄ν¨ν°; μ μ κ³μ°κΈ°");
378 dict_add(dict, "dictionary", "μ¬μ ; λ¨μ΄λ₯Ό λͺ¨μ μΌμ ν μμλ‘ λ°°μ΄νμ¬ μ€λͺ
ν μ±
");
379 dict_add(dict, "education", "κ΅μ‘; μ§μκ³Ό κΈ°μ μ κ°λ₯΄μΉ¨");
380 dict_add(dict, "friend", "μΉκ΅¬; κ°κΉμ΄ μ¬κ·μ΄ μΉνκ² μ§λ΄λ μ¬λ");
381 dict_add(dict, "galaxy", "μν; μ°μ£Ό 곡κ°μ μλ μ²μ²΄ μ§λ¨");
382 dict_add(dict, "happiness", "ν볡; 볡λ μ’μ μ΄μ");
383 dict_add(dict, "internet", "μΈν°λ·; μ μΈκ³μ μ»΄ν¨ν°κ° μλ‘ μ°κ²°λ λ€νΈμν¬");
384 dict_add(dict, "javascript", "μλ°μ€ν¬λ¦½νΈ; μΉ νλ‘κ·Έλλ° μΈμ΄");
385}
386
387// λ©μΈ ν¨μ
388int main(void) {
389 Dictionary *dict = dict_create();
390 if (!dict) return 1;
391
392 // μν λ°μ΄ν° λ‘λ
393 printf("μν λ°μ΄ν°λ₯Ό λΆλ¬μ€λ μ€...\n");
394 load_sample_data(dict);
395
396 // κΈ°μ‘΄ νμΌμ΄ μμΌλ©΄ λΆλ¬μ€κΈ°
397 FILE *test = fopen(FILENAME, "r");
398 if (test) {
399 fclose(test);
400 printf("\nκΈ°μ‘΄ μ¬μ νμΌμ λ°κ²¬νμ΅λλ€.\n");
401 printf("λΆλ¬μ€μκ² μ΅λκΉ? (y/n): ");
402 char choice;
403 scanf(" %c", &choice);
404 clear_input();
405
406 if (choice == 'y' || choice == 'Y') {
407 // κΈ°μ‘΄ λ°μ΄ν° μμ ν λ‘λ
408 dict_destroy(dict);
409 dict = dict_create();
410 dict_load(dict, FILENAME);
411 }
412 }
413
414 int choice;
415 char word[KEY_SIZE];
416 char meaning[VALUE_SIZE];
417
418 while (1) {
419 print_menu();
420 printf("μ ν: ");
421
422 if (scanf("%d", &choice) != 1) {
423 clear_input();
424 printf("β μλͺ»λ μ
λ ₯μ
λλ€\n");
425 continue;
426 }
427 clear_input();
428
429 switch (choice) {
430 case 1: // μΆκ°
431 printf("\nλ¨μ΄: ");
432 fgets(word, KEY_SIZE, stdin);
433 word[strcspn(word, "\n")] = '\0';
434
435 if (strlen(word) == 0) {
436 printf("β λ¨μ΄λ₯Ό μ
λ ₯νμΈμ\n");
437 break;
438 }
439
440 printf("λ»: ");
441 fgets(meaning, VALUE_SIZE, stdin);
442 meaning[strcspn(meaning, "\n")] = '\0';
443
444 if (strlen(meaning) == 0) {
445 printf("β λ»μ μ
λ ₯νμΈμ\n");
446 break;
447 }
448
449 dict_add(dict, word, meaning);
450 break;
451
452 case 2: // κ²μ
453 printf("\nκ²μν λ¨μ΄: ");
454 fgets(word, KEY_SIZE, stdin);
455 word[strcspn(word, "\n")] = '\0';
456
457 char *result = dict_search(dict, word);
458 if (result) {
459 printf("\nββββββββββββββββββββββββββββββββββββββββββ\n");
460 printf("β %s\n", word);
461 printf("ββββββββββββββββββββββββββββββββββββββββββ€\n");
462 printf("β %s\n", result);
463 printf("ββββββββββββββββββββββββββββββββββββββββββ\n");
464 } else {
465 printf("\nβ '%s'μ(λ₯Ό) μ°Ύμ μ μμ΅λλ€\n", word);
466 dict_suggest(dict, word);
467 }
468 break;
469
470 case 3: // μμ
471 printf("\nμμ ν λ¨μ΄: ");
472 fgets(word, KEY_SIZE, stdin);
473 word[strcspn(word, "\n")] = '\0';
474
475 dict_delete(dict, word);
476 break;
477
478 case 4: // λͺ©λ‘
479 dict_list(dict);
480 break;
481
482 case 5: // μ μ
483 printf("\nκ²μν μ λμ¬: ");
484 fgets(word, KEY_SIZE, stdin);
485 word[strcspn(word, "\n")] = '\0';
486
487 dict_suggest(dict, word);
488 break;
489
490 case 6: // ν΅κ³
491 dict_statistics(dict);
492 break;
493
494 case 7: // μ μ₯
495 dict_save(dict, FILENAME);
496 break;
497
498 case 8: // λΆλ¬μ€κΈ°
499 printf("\nνμ¬ λ°μ΄ν°κ° μμ λ©λλ€. κ³μνμκ² μ΅λκΉ? (y/n): ");
500 char confirm;
501 scanf(" %c", &confirm);
502 clear_input();
503
504 if (confirm == 'y' || confirm == 'Y') {
505 dict_destroy(dict);
506 dict = dict_create();
507 dict_load(dict, FILENAME);
508 }
509 break;
510
511 case 0: // μ’
λ£
512 printf("\nμ μ₯νμκ² μ΅λκΉ? (y/n): ");
513 char save_choice;
514 scanf(" %c", &save_choice);
515 clear_input();
516
517 if (save_choice == 'y' || save_choice == 'Y') {
518 dict_save(dict, FILENAME);
519 }
520
521 printf("μ¬μ μ μ’
λ£ν©λλ€.\n");
522 dict_destroy(dict);
523 return 0;
524
525 default:
526 printf("β μλͺ»λ μ νμ
λλ€\n");
527 }
528 }
529
530 return 0;
531}