Записать в другой файл в столбик все слова, встречающиеся в тексте - C (СИ)
Формулировка задачи:
Задача (алфавитно-частотный словарь). В файле записан текст.
Нужно записать в другой файл в столбик все слова,
встречающиеся в тексте, в алфавитном порядке, и количество
повторений для каждого слова.
Проблемы:
1)количество слов заранее неизвестно (статический массив);
2)количество слов определяется только в конце работы (динамический массив).
Решение – список.
Алгоритм:
1)создать список;
2)если слова в файле закончились, то стоп.
3)прочитать слово и искать его в списке;
4)если слово найдено – увеличить счетчик повторений,
иначе добавить слово в список;
5)перейти к шагу 2.
Решение задачи: «Записать в другой файл в столбик все слова, встречающиеся в тексте»
textual
Листинг программы
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define INPUT_FILE_NAME "input.txt"
#define OUTPUT_FILE_NAME "output.txt"
typedef struct TREENODE {
char * word;
size_t count;
struct TREENODE * left;
struct TREENODE * right;
} treenode_t, *treeptr_t;
treenode_t * new_treenode(const char * word) {
treenode_t * node = malloc(sizeof(treenode_t));
if ( ! node )
return NULL;
node->word = malloc(strlen(word) + 1);
if ( ! node->word ) {
free(node);
return NULL;
}
strcpy(node->word, word);
node->count = 1;
node->left = NULL;
node->right = NULL;
return node;
}
void del_treenode(treenode_t * node) {
assert ( node && ! node->left && ! node->right );
free(node->word);
free(node);
}
int add_word(treeptr_t * tree, const char * word) {
if ( ! *tree ) {
if ( ! ( *tree = new_treenode(word) ) )
return -1;
}
else {
int cmp = strcmp((*tree)->word, word);
if ( cmp > 0 )
return add_word(&((*tree)->left), word);
else if ( cmp < 0 )
return add_word(&((*tree)->right), word);
else
(*tree)->count += 1;
}
return 0;
}
void del_tree(treeptr_t * tree) {
if ( *tree ) {
del_tree(&((*tree)->left));
del_tree(&((*tree)->right));
del_treenode(*tree);
*tree = NULL;
}
}
int dump_to_file(treeptr_t tree, FILE * f) {
if ( tree ) {
if ( dump_to_file(tree->left, f) || fprintf(f, "%s\t%u\n", tree->word, tree->count) < 1 || dump_to_file(tree->right, f) )
return -1;
}
return 0;
}
typedef char word_t[256];
#define getword(f, w) ( fscanf((f), "%255s", (w)) == 1 )
int main(void) {
FILE * fin, * fout;
treeptr_t tree;
word_t word;
if ( ! ( fin = fopen(INPUT_FILE_NAME, "r") ) ) {
perror(INPUT_FILE_NAME);
exit(1);
}
tree = NULL;
while ( getword(fin, word) ) {
if ( add_word(&tree, word) ) {
fprintf(stderr, "Memory error!\n");
if ( fclose(fin) )
perror(INPUT_FILE_NAME);
exit(1);
}
}
if ( ferror(fin) || fclose(fin) ) {
perror(INPUT_FILE_NAME);
del_tree(&tree);
exit(1);
}
assert ( tree );
if ( ! ( fout = fopen(OUTPUT_FILE_NAME, "w") ) ) {
perror(OUTPUT_FILE_NAME);
del_tree(&tree);
exit(1);
}
if ( dump_to_file(tree, fout) || fclose(fout) ) {
fprintf(stderr, "Error writing to %s!\n", OUTPUT_FILE_NAME);
del_tree(&tree);
exit(1);
}
del_tree(&tree);
fprintf(stderr, "Done!\n");
exit(0);
}
Объяснение кода листинга программы
В данном коде реализован алгоритм добавления слов в дерево и последующего их вывода в другой файл.
- Создаются структуры данных для представления дерева:
treenode_t- структура для представления узла дерева. Содержит указатель на слово, счетчик количества повторений слова и указатели на левое и правое поддерево.treeptr_t- указатель на узел дерева.
- Реализуются функции для работы с деревом:
new_treenode()- создает новый узел дерева с заданным словом.del_treenode()- удаляет узел дерева.add_word()- добавляет новое слово в дерево.del_tree()- удаляет все элементы дерева.
- Реализуется функция
dump_to_file(), которая выводит содержимое дерева в файл. - В функции
main()открывается входной файл для чтения и создается указательtreeptr_tдля представления дерева.- Используя цикл и функцию
getword(), из входного файла считываются слова, которые добавляются в дерево с помощью функцииadd_word(). - После чтения всего файла, дерево выводится в выходной файл с помощью функции
dump_to_file(). - После завершения работы программы выводится сообщение
Done!.
- Используя цикл и функцию