Вывести из файла все русские слова по алфавиту, начинающихся с гласной - C (СИ)
Формулировка задачи:
Здраствуйте.
Дано текстовый файл.за один просмотр файла вывести его содержание в следующем порядке:
сначала все русские слова по алфавиту, начинающихся с гласной, и количество их вхождений в файл, а затем аналогичные данные о словах, начинающихся с гласной.
Решение задачи: «Вывести из файла все русские слова по алфавиту, начинающихся с гласной»
textual
Листинг программы
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- typedef struct node_t
- {
- char* pstr; // Указатель на слово
- size_t length; // Длина слова
- size_t count; // Количество слов
- struct node_t* next; // Следующий узел
- } TNode;
- //-----------------------------------------------------------------------------
- // Функция меняет верхний регистр русских букв на ничжний
- char ToLower(char c)
- {
- if (('А' <= c) && (c <= 'П'))
- {
- c += 32;
- }
- else if (('Р' <= c) && (c <= 'Я'))
- {
- c += 80;
- }
- else if ('Ё' == c)
- {
- c = 'ё';
- }
- return c;
- }
- //-----------------------------------------------------------------------------
- // Функция определяет является ли символ буквой русского алфавита
- int IsAlpha(char c)
- {
- return ((('А' <= c) && (c <= 'п') )||
- (('р' <= c) && (c <= 'ё')));
- }
- //-----------------------------------------------------------------------------
- // Функция сравнивает 2 строки заданной длины.
- // Ориентирована на русский алфавит. Сравнение регистронезависимое.
- int StrNCmp(const char* a, size_t lenA, const char* b, size_t lenB)
- {
- // Берём минимальную из длин
- size_t len = (lenA < lenB) ? lenA : lenB;
- int result = 0;
- int i;
- // Выполняем пока не достигнем минимальной длины
- // или пока не найдём различия
- for (i = 0; (i < len) && (result == 0); ++i)
- {
- result = ToLower(a[i]) - ToLower(b[i]);
- }
- // Если различий небыло, тогда пытаеся наёти
- // различия в длине
- if (result == 0)
- {
- result = lenA - lenB;
- }
- return result;
- }
- //-----------------------------------------------------------------------------
- // Находит в заданной строке слово на русском языке.
- // В begin передаётся указатель на начало слова, а end - конец
- int GetWord(char* text, char** begin, char** end)
- {
- // Перебирваем символы в строке пока не встретим
- // русскую букву (ну или пока текст не закончится)
- for (; *text && !IsAlpha(*text); ++text) { ; }
- *begin = text;
- // Перебирваем символы в строке пока встречаются
- // русские буквы
- for (; *text && IsAlpha(*text); ++text) { ; }
- *end = text;
- // Возвращаем длину найденного слова
- return *end - *begin;
- }
- //-----------------------------------------------------------------------------
- // Функция добавляет в список новое слово не нарушая порядок сортировки списка.
- // Если такое слово уже встречается, то значение count узла просто инкрементируется.
- TNode* PushWithSortAndCount(TNode** list, char* pstr, size_t length)
- {
- // Временно создаём самый верхний узел.
- // Создаётся для упрощения дальнейшего алгоритма
- TNode* head = (TNode*) malloc(sizeof(TNode));
- TNode* cur = head;
- TNode* node;
- int cmp = 1;
- head->next = *list;
- // Ищем мето, куда можно пристроить новое слово.
- // Если cmp будет равно 0, то это означает, что такое
- // слово уже есть
- for (; cur->next &&
- ((cmp = StrNCmp(cur->next->pstr, cur->next->length, pstr, length)) < 0)
- ; cur = cur->next) { ; }
- // Если слово не повторяется, то создаём и вставляем новый узел
- if (cmp)
- {
- node = (TNode*) malloc(sizeof(TNode));
- node->pstr = pstr;
- node->length = length;
- node->count = 1;
- node->next = cur->next;
- cur->next = node;
- // В случае если слово попало на вершину списка
- if (cur == head)
- {
- *list = node;
- }
- }
- // Слово уже есть
- else
- {
- cur->next->count++;
- }
- free(head);
- return *list;
- }
- //-----------------------------------------------------------------------------
- // Очищаем всеь список
- void Clear(TNode** list)
- {
- TNode* node;
- // Перебираем все эелементы и удаляем каждый узел
- while (*list)
- {
- node = *list;
- *list = node->next;
- free(node);
- }
- }
- //-----------------------------------------------------------------------------
- // Печать списка
- void Print(const TNode* list, FILE* stream)
- {
- for (; list; list = list->next)
- {
- fprintf(stream, "\t%4d : %.*s\n", list->count, list->length, list->pstr);
- }
- }
- //-----------------------------------------------------------------------------
- // Вормируем из текста 2 списка. В одном храняться информация о словах
- // начинающихся на гласные буквы, в другом - на согласные. Оба списка не
- // дублируют слова из text, а хранять лишь указатели.
- void GetLists(char* text, TNode** a, TNode** b)
- {
- const char CChars[] = "аеёиоуыэюя";
- char* begin;
- char* end;
- while (GetWord(text, &begin, &end) > 0)
- {
- if (strchr(CChars, ToLower(*begin)))
- {
- PushWithSortAndCount(a, begin, end - begin);
- }
- else
- {
- PushWithSortAndCount(b, begin, end - begin);
- }
- text = end;
- }
- }
- //-----------------------------------------------------------------------------
- // Загружаем содержимое файла в память
- char* GetTextFromFile(const char* fname)
- {
- FILE* f = fopen(fname, "rb");
- if (f == NULL)
- {
- perror(fname);
- system("pause");
- exit (EXIT_FAILURE);
- }
- // Определяем размер файла
- fseek(f, 0, SEEK_END);
- size_t size = ftell(f);
- fseek(f, 0, SEEK_SET);
- char* text = (char*) malloc(size + 1);
- text[size] = '\0';
- // Загружаем
- fread(text, size, 1, f);
- fclose(f);
- return text;
- }
- //-----------------------------------------------------------------------------
- int main(int argc, char* argv[])
- {
- if (argc != 2)
- {
- fprintf(stdout, "Использование: program <ТЕКСТОВЫЙ ФАЙЛ>\n"
- "Примечание: текстовый фал должен быть в кодировке CP866\n");
- system("pause");
- return EXIT_FAILURE;
- }
- char* text = GetTextFromFile(argv[1]);
- TNode* a = NULL;
- TNode* b = NULL;
- GetLists(text, &a, &b);
- fprintf(stdout, "Сам текст\n"
- "-----------------------\n"
- "%s\n\n", text);
- fprintf(stdout, "Начинающиеся на гласные\n"
- "-----------------------\n");
- Print(a, stdout);
- fprintf(stdout, "Начинающиеся на согласные\n"
- "-----------------------\n");
- Print(b, stdout);
- Clear(&a);
- Clear(&b);
- free(text);
- system("pause");
- return EXIT_SUCCESS;
- }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д