Вывести из файла все русские слова по алфавиту, начинающихся с гласной - 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; }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д