Advertisement
blazinghorizon

Untitled

Nov 12th, 2019
392
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.42 KB | None | 0 0
  1. /**
  2.  * dict2.c -- программа чтения словаря и печати словарной статьи по шаблону
  3.  *
  4.  * Copyright (c) 2019, Arseniy Fomin <student@cs.karelia.ru>
  5.  *
  6.  * This code is licensed under a MIT-style license.
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13.  
  14. #define MAXLINE 1023
  15. #define SEARCH_MODE_B 110
  16. #define SEARCH_MODE_E 101
  17. #define SEARCH_MODE_BE 211
  18. #define SIZE_OF_BUFFER 10 * 1024 * 1024
  19.  
  20. char* load_dictionary(char *dictionary, FILE *stream);
  21. char* filter_dictionary(char *pattern, char *dictionary, char *entries);
  22.  
  23. int main(int argc, char*argv[])
  24. {
  25.     /* Файл словаря */
  26.     FILE* dict = NULL;
  27.  
  28.     /* Диагностика ошибки неправильного числа аргументов */
  29.     if (argc != 2) {
  30.         fprintf(stderr, "Incorrect number of arguments.\n",
  31.                         "The correct input is: <dictionary_name>\n");
  32.         exit(EXIT_FAILURE);
  33.     }
  34.    
  35.     /* Открываем файл словаря */
  36.     dict = fopen(argv[1], "r");
  37.  
  38.     /* Диагностика ошибок ввода-вывода */
  39.     if (dict == NULL) {
  40.         fprintf(stderr, "The program has closed due to I/O error.\n");
  41.         exit(EXIT_FAILURE);
  42.     }
  43.  
  44.     /* Создание буфера для загрузки файла и вывода результатов*/
  45.     char *dict_buffer = NULL;
  46.     char *entries_buffer = NULL;
  47.     dict_buffer = (char *) malloc(sizeof(char) * SIZE_OF_BUFFER);
  48.     entries_buffer = (char *) malloc(sizeof(char) * SIZE_OF_BUFFER);
  49.     if ((dict_buffer == NULL) || (entries_buffer == NULL)) {
  50.         fprintf(stderr, "Not enough memory for creating a buffer.\n",
  51.                         "The size required: 10MB\n");
  52.         exit(EXIT_FAILURE);
  53.     }
  54.  
  55.     /* Загрузка словаря и диагностика */
  56.     char *qp_buffer = load_dictionary(dict_buffer, dict);
  57.     if (qp_buffer == NULL) {
  58.         fprintf(stderr, "The dictionary file is too large.\n",
  59.                         "The size limit: 10MB\n");
  60.         exit(EXIT_FAILURE);
  61.     }
  62.  
  63.     /* Завершаем работу с файлом словаря */
  64.     fclose(dict);
  65.  
  66.     /* Шаблон для поиска */
  67.     char query[MAXLINE + 1] = "";
  68.  
  69.     /* Получаем шаблон для поиска */
  70.     printf("Enter the searching pattern:\n");
  71.     scanf("%s", query);
  72.     char *entries;
  73.     memset(entries_buffer, '\0', SIZE_OF_BUFFER);
  74.  
  75.     /* Цикл ввода шаблонов */
  76.     while (*query != '\0') {
  77.         entries = filter_dictionary(query, qp_buffer, entries_buffer);
  78.         if (entries == NULL)
  79.             printf("No enties found.\n");
  80.         else
  81.             printf("%s\n", entries);
  82.         memset(entries_buffer, '\0', SIZE_OF_BUFFER);
  83.         memset(query, '\0', MAXLINE + 1);
  84.         printf("Enter the searching pattern:\n");
  85.         scanf("%s", query);
  86.     }
  87.  
  88.     free(entries);
  89.     free(dict_buffer);
  90.  
  91.     return 0;
  92. }
  93.  
  94. char* filter_dictionary(char *pattern, char *dictionary, char *entries) {
  95.  
  96.     /* Текущая строка */
  97.     char current_line[MAXLINE + 1] = "";
  98.  
  99.     /* Флаг для выбора режима поиска */
  100.     int search_mode = 0;
  101.  
  102.     /* Определяем режим поиска */
  103.     int pattern_len = strlen(pattern);
  104.     if (pattern[0] == '^') {
  105.         search_mode += SEARCH_MODE_B;
  106.         memmove(pattern, pattern + 1, pattern_len - 1);
  107.         pattern[pattern_len - 1] = '\0';
  108.         pattern_len--;
  109.     }
  110.     if (pattern[pattern_len - 1] == '$') {
  111.         search_mode += SEARCH_MODE_E;
  112.         pattern[pattern_len - 1] = '\0';
  113.     }
  114.  
  115.     /* Флаг соответствия текущей статьи условию отбора */
  116.     int matched_entry = 0;
  117.  
  118.     char *line = dictionary;
  119.     int sym_per_line = strcspn(line, "\n") + 1;
  120.     strncpy(current_line, line, sym_per_line);
  121.     line += sym_per_line;
  122.  
  123.     /* Просматриваем словарь */
  124.     while (*line) {
  125.         /* Если первый символ строки не является пробельным разделителем,
  126.             найдено начало новой словарной статьи */
  127.         if (!isspace(current_line[0])) {
  128.             char *pointer = strstr(current_line, pattern);
  129.             int cur_line_len = strlen(current_line) - 1;
  130.             /* Определяем, выполнено ли условие отбора для данной статьи */
  131.             switch (search_mode) {
  132.             case SEARCH_MODE_B:
  133.                 if (pointer == current_line)
  134.                     matched_entry = 1;
  135.                 else
  136.                     matched_entry = 0;
  137.                 break;
  138.             case SEARCH_MODE_E:
  139.                 if (pointer == current_line + cur_line_len - pattern_len)
  140.                     matched_entry = 1;
  141.                 else
  142.                     matched_entry = 0;
  143.                 break;
  144.             case SEARCH_MODE_BE:
  145.                 if ((pointer == current_line) && (pattern_len == cur_line_len))
  146.                     matched_entry = 1;
  147.                 else
  148.                     matched_entry = 0;
  149.                 break;
  150.             case 0:
  151.                 if (pointer != NULL)
  152.                     matched_entry = 1;
  153.                 else
  154.                     matched_entry = 0;
  155.                 break;
  156.             }
  157.         }
  158.  
  159.         /* Печатаем строку, если она относится к запрошенной статье */
  160.         if (matched_entry) {
  161.             strcat(entries, current_line);
  162.         }
  163.  
  164.         sym_per_line = strcspn(line, "\n") + 1;
  165.         strncpy(current_line, line, sym_per_line);
  166.         line += sym_per_line;
  167.  
  168.     }
  169.  
  170.     if (strlen(entries) == 0)
  171.         return NULL;
  172.     else
  173.         return entries;
  174. }
  175.  
  176. char* load_dictionary(char *dictionary, FILE *stream) {
  177.  
  178.     /* Определение размера файла */
  179.     fseek(stream, 0, SEEK_END);
  180.     long dict_size = ftell(stream);
  181.     rewind(stream);
  182.  
  183.     /* Копирование файла в буфер */
  184.     fread(dictionary, 1, dict_size, stream);
  185.     long buffer_size = strlen(dictionary);
  186.  
  187.     /* Проверка на целостность копирования */
  188.     if (dict_size != buffer_size)
  189.         return NULL;
  190.     else
  191.         return dictionary;
  192. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement