Kill mega-sena.sh
[lcapit-junk-code.git] / games / hangman / dict.c
blob4b565ff128a8c6bb23caa90592c36af684b2af9b
1 /*
2 * This file is licensed under the GPLv2 license
3 *
4 * Luiz Fernando N. Capitulino
5 * <lcapitulino@gmail.com>
6 */
7 #include <stdio.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <errno.h>
11 #include <time.h>
13 #include "dict.h"
14 #include "misc.h"
16 enum dictionary_menu_opt {
17 DICT_PRINT = 1,
18 DICT_SEARCH,
19 DICT_INSERT,
20 DICT_REMOVE,
21 DICT_EXIT
24 static const char dict_file_path[] = "dict.txt";
27 * Helpers
30 /* skip_char(): skip a sequence of characters 'c' in 'file' */
31 static void skip_char(FILE *file, int c)
33 int rc;
35 while ((rc = getc(file)) == c)
36 /* NOTHING */ ;
37 ungetc(rc, file);
40 /* skip_space(): skip spaces in 'file' */
41 static void skip_space(FILE *file)
43 skip_char(file, ' ');
46 /* seek_line_end(): go to the end of a dict line */
47 static void seek_line_end(FILE *file)
49 int c;
51 for (;;) {
52 c = getc(file);
53 if (c == EOF || c == ':' || c == '\n')
54 break;
58 /* str_kill_nl(): kill a new-line character at end of line */
59 static void str_kill_nl(char *line)
61 line[strlen(line) - 1] = '\0';
65 * List functions
68 /* list_empty(): Return 1 if 'list' is empty, 0 otherwise */
69 static int list_empty(const struct dict_list *list)
71 return list->first == list->last;
74 /* word_compare(): comparison function used by insertion_sort() */
75 static int word_compare(const void *key1, const void *key2)
77 const char *str1 = ((const struct dict_line *) key1)->word;
78 const char *str2 = ((const struct dict_line *) key2)->word;
80 return memcmp(str1, str2, DICT_WORD_MAX);
83 /* insertion_sort(): sort data by using insertion sort algorithm */
84 static int insertion_sort(void *data, int size, int esize,
85 int (*compare) (const void *key1, const void *key2))
87 char *a = data;
88 void *key;
89 int i, j;
91 key = (char *) malloc(esize);
92 if (!key)
93 return -1;
95 for (j = 1; j < size; j++) {
96 memcpy(key, &a[j * esize], esize);
97 i = j - 1;
99 while (i >= 0 && compare(&a[i * esize], key) > 0) {
100 memcpy(&a[(i + 1) * esize], &a[i * esize], esize);
101 i--;
104 memcpy(&a[(i + 1) * esize], key, esize);
107 free(key);
108 return 0;
111 /* list_sort(): sort list */
112 static int list_sort(struct dict_list *list)
114 return insertion_sort(list->dict_line, list->last,
115 sizeof(struct dict_line), word_compare);
118 /* list_init(): Initialize 'list' */
119 static void list_init(struct dict_list *list)
121 list->first = list->last = 0;
124 /* list_insert(): Insert element 'line' into 'list' */
125 static int list_insert(struct dict_list *list, struct dict_line *line)
127 if (list->last == DICT_LIST_MAX) {
128 errno = ENOMEM;
129 return -1;
132 list->dict_line[list->last] = *line;
133 list->last++;
135 return 0;
138 /* list_remove(): Removes element at position 'pos' from 'list', the
139 * elements' address is returned in 'ret' */
140 static int list_remove(int pos,
141 struct dict_list *list, struct dict_line *ret)
143 int i;
145 if (list_empty(list) || pos >= list->last)
146 return -1;
148 if (ret)
149 *ret = list->dict_line[pos];
151 list->last--;
153 for (i = pos; i < list->last; i++)
154 list->dict_line[i] = list->dict_line[i + 1];
156 return 0;
159 /* list_write(): Write 'list' to the dict file */
160 static int list_write(struct dict_list *list)
162 int i;
163 FILE *dict;
165 dict = fopen(dict_file_path, "w");
166 if (!dict)
167 return -1;
169 for (i = 0; i < list->last; i++) {
170 fprintf(dict, "%s: %s\n",
171 list->dict_line[i].word, list->dict_line[i].tip);
174 fclose(dict);
175 return 0;
178 /* show_entry(): print 'entry' in a standard way */
179 static void show_entry(int nr, const struct dict_line *entry)
181 printf("%d. word: %s\n", nr, entry->word);
182 printf(" tip: %s\n", entry->tip);
183 printf("\n");
186 /* list_print(): Print 'list' to the standard output */
187 static void list_print(const struct dict_list *list)
189 int i;
191 if (list_empty(list))
192 return;
194 printf("\n");
196 for (i = 0; i < list->last; i++)
197 show_entry(i, &list->dict_line[i]);
200 static void handle_pattern(char *pattern,
201 const struct dict_list *list)
203 int i, showed;
205 if (pattern[0] == '\n') {
206 list_print(list);
207 return;
210 showed = 0;
211 pattern[strlen(pattern) - 1] = '\0';
213 for (i = 0; i < list->last; i++) {
214 if (strstr(list->dict_line[i].word, pattern)) {
215 show_entry(i, &list->dict_line[i]);
216 showed = 1;
220 if (!showed)
221 printf("\n-> Nao encontrado\n");
224 static void show_prompt(void)
226 clear_screen();
228 printf("Aperte <enter> para fazer a pesquisa e "
229 "Ctrl-D para sair\n\n");
230 printf(">>> ");
233 static void list_search(const struct dict_list *list)
235 char *ret;
236 char pattern[DICT_WORD_MAX];
238 for (;;) {
239 show_prompt();
241 ret = fgets(pattern, sizeof(pattern), stdin);
242 if (!ret)
243 return;
245 handle_pattern(pattern, list);
246 mprint("");
251 * Dict high level functions
254 /* dict_read_line(): read a line from dict file 'file' and return it
255 * in 'line' of size 'size' */
256 static int dict_read_line(FILE *file, char *line, size_t size)
258 size_t i;
259 int end, c;
261 end = 0;
262 memset(line, 0, size);
264 skip_space(file);
266 for (i = 0; i < size; i++) {
267 c = getc(file);
268 if (c == EOF || c == ':' || c == '\n') {
269 end = 1;
270 break;
272 line[i] = c;
275 if (!end) {
276 seek_line_end(file);
277 --i;
280 line[i] = '\0';
281 return c;
284 /* dict_read_file(): read the entire dict file in the 'dict_line'
285 * array, of elements 'size'. Return the number of read elements
286 * in 'read' */
287 static int dict_read_file(struct dict_line *dict_line, size_t size, int *read)
289 int ret;
290 size_t i;
291 FILE *dict;
293 *read = 0;
295 dict = fopen(dict_file_path, "r");
296 if (!dict)
297 return -1;
299 for (i = 0; i < size; i++) {
300 ret = dict_read_line(dict, dict_line[i].word, DICT_WORD_MAX);
301 if (ret == EOF)
302 break;
304 ret = dict_read_line(dict, dict_line[i].tip, DICT_TIP_MAX);
305 if (ret == EOF)
306 break;
309 *read = i;
311 fclose(dict);
312 return 0;
315 /* dict_read_user(): Read a dict line from the user */
316 static void dict_read_user(struct dict_line *line)
319 line->word[0] = line->tip[0] = '\0';
321 fflush(stdin);
322 printf("Entre com a palavra chave: ");
323 fgets(line->word, DICT_WORD_MAX, stdin);
324 str_kill_nl(line->word);
326 fflush(stdin);
327 printf("Entre com a dica: ");
328 fgets(line->tip, DICT_TIP_MAX, stdin);
329 str_kill_nl(line->tip);
333 * Main functions
336 void dict_pick_up_word(struct dict_line *line)
338 int err;
339 struct dict_list list;
341 list_init(&list);
343 err = dict_read_file(list.dict_line, DICT_LIST_MAX, &list.last);
344 if (err && errno != ENOENT) {
345 eprint("dict_read_file() failed");
346 return;
349 srand(time(NULL));
351 *line = list.dict_line[rand() % list.last];
354 void dictionary_menu(void)
356 int op, pos, err;
357 struct dict_line line;
358 struct dict_list list;
360 list_init(&list);
362 err = dict_read_file(list.dict_line, DICT_LIST_MAX, &list.last);
363 if (err && errno != ENOENT) {
364 eprint("dict_read_file() failed");
365 return;
368 for (;;) {
369 err = list_sort(&list);
370 if (err) {
371 eprint("insertion_sort() failed");
372 return;
375 clear_screen();
376 printf("\nManipular dicionario\n\n");
377 printf("1. Imprimir conteudo\n"
378 "2. Pesquisa\n"
379 "3. Inserir\n"
380 "4. Remover\n"
381 "5. Sair\n"
382 "\n-> opcao: ");
383 scanf("%d", (int *) &op);
384 flush_all();
386 switch (op) {
387 case DICT_PRINT:
388 list_print(&list);
389 mprint("");
390 break;
391 case DICT_SEARCH:
392 list_search(&list);
393 break;
394 case DICT_INSERT:
395 dict_read_user(&line);
396 err = list_insert(&list, &line);
397 if (err)
398 eprint("Failed\n");
399 else
400 mprint("Success\n");
401 break;
402 case DICT_REMOVE:
403 list_print(&list);
404 printf("Digite o numero para remover: ");
405 scanf("%d", &pos);
406 flush_all();
407 err = list_remove(pos, &list, NULL);
408 if (err)
409 eprint("Failed\n");
410 else
411 mprint("Success\n");
412 break;
413 case DICT_EXIT:
414 goto out;
415 default:
416 errno = EINVAL;
417 eprint("Function not implemented");
421 out:
422 list_write(&list);