Подсчитать количество слов в файле - C (СИ) (71340)
Формулировка задачи:
Задачка вот такая, нужна помощь с ее решением)
Один из способов идентификации автора литературного произведения – подсчет частоты вхождения отдельных слов. В заданном текстовом файле найти 20 наиболее часто встречающихся слов с указанием частоты использования каждого из них.
Решение задачи: «Подсчитать количество слов в файле»
textual
Листинг программы
- #include <stdio.h>
- #include <malloc.h>
- #include <string.h>
- #include <ctype.h>
- #include <locale.h>
- #define MAX_SIZE 256
- typedef unsigned char uchar;
- typedef struct _word {
- struct _word* next;
- const uchar* ptr;
- unsigned cnt;
- } sword;
- typedef struct {
- sword* arr[MAX_SIZE];
- int cnt;
- } htab;
- static unsigned __calc_hash(const uchar* s);
- static int __scmp(const uchar* s1, const uchar* s2);
- static char* readfile(const char* fn);
- static void sword_fill(htab* ht, uchar* s);
- static void htab_init(htab* ht);
- static int htab_add(htab* ht, const uchar* w);
- static void htab_clear(htab* ht);
- static sword* htab_min(htab* ht);
- static void htab_print(FILE* _out, htab* ht, int num);
- int main(void){
- htab ht;
- char* buf = readfile("file.txt");
- if(buf == NULL)
- return 1;
- setlocale(LC_CTYPE, "Russian_Russia.1251");
- sword_fill(&ht, (uchar*)buf);
- htab_print(stdout, &ht, 20);
- htab_clear(&ht);
- free(buf);
- return 0;
- }
- //инициализация
- static void htab_init(htab* ht){
- int i;
- for(i = 0; i < MAX_SIZE; ++i)
- ht->arr[i] = NULL;
- ht->cnt = 0;
- }
- //добавление
- static int htab_add(htab* ht, const uchar* w){
- sword* p;
- unsigned key = __calc_hash(w);
- for(p = ht->arr[key]; p != NULL; p = p->next){
- if(__scmp(p->ptr, w)){
- ++(p->cnt);
- return 0;
- }
- }
- p = (sword*)malloc(sizeof(sword));
- if(p != NULL){
- p->cnt = 1;
- p->ptr = w;
- p->next = ht->arr[key];
- ht->arr[key] = p;
- ++(ht->cnt);
- }
- return (p != NULL);
- }
- //минимум
- static sword* htab_min(htab* ht){
- int i;
- sword* p;
- for(i = 0; i < MAX_SIZE; ++i){
- if((ht->arr[i] != NULL) && (ht->arr[i]->cnt > 0))
- break;
- }
- if(i == MAX_SIZE)
- return NULL;
- p = ht->arr[i];
- for(; i < MAX_SIZE; ++i){
- if((ht->arr[i] != NULL) && (ht->arr[i]->cnt > p->cnt))
- p = ht->arr[i];
- }
- return p;
- }
- //вывод результата
- static void htab_print(FILE* _out, htab* ht, int num){
- int i;
- sword* p;
- if(ht->cnt < num)
- num = ht->cnt;
- for(i = 0; i < num; ++i){
- if((p = htab_min(ht)) != NULL){
- fprintf(_out, "%s(%d)\n", p->ptr, p->cnt);
- p->cnt = 0;
- }
- }
- fflush(_out);
- }
- //удаление всех
- static void htab_clear(htab* ht){
- int i;
- sword* t;
- for(i = 0; i < MAX_SIZE; ++i){
- while(ht->arr[i] != NULL){
- t = ht->arr[i];
- ht->arr[i] = ht->arr[i]->next;
- free(t);
- }
- }
- ht->cnt = 0;
- }
- //...
- static void sword_fill(htab* ht, uchar* s){
- uchar* p;
- htab_init(ht);
- while(*s){
- while(*s && !isalnum(*s))
- ++s;
- for(p = s; isalnum(*p); ++p)
- ;
- if(s != p){
- if(*p)
- *p++ = '\0';
- htab_add(ht, s);
- }
- s = p;
- }
- }
- static unsigned __calc_hash(const uchar* s){
- unsigned n = 0;
- while(*s)
- n += (unsigned)toupper(*s++);
- return n % MAX_SIZE;
- }
- static int __scmp(const uchar* s1, const uchar* s2){
- while(*s1 && (toupper(*s1) == toupper(*s2))){
- ++s1;
- ++s2;
- }
- return (!*s1 && !*s2);
- }
- static char* readfile(const char* fn){
- char* s;
- long n;
- size_t i;
- FILE* fp = fopen(fn, "rb");
- if(fp == NULL)
- return NULL;
- fseek(fp, 0L, SEEK_END);
- n = ftell(fp);
- if(n <= 1L){
- fclose(fp);
- return NULL;
- }
- s = (char*)malloc((n + 1) * sizeof(char));
- if(s == NULL){
- fclose(fp);
- return NULL;
- }
- fseek(fp, 0L, SEEK_SET);
- i = fread(s, sizeof(char), (size_t)n, fp);
- fclose(fp);
- if(i == (size_t)n)
- s[i] = '\0';
- else {
- free(s);
- s = NULL;
- }
- return s;
- }
Объяснение кода листинга программы
- В данной программе используется язык программирования C.
- Программа подсчитывает количество слов в файле.
- Для решения задачи используется хэш-таблица (htab).
- Хэш-таблица содержит структуру данных sword, которая включает указатель на следующую структуру, указатель на строку и счетчик количества упоминаний слова.
- Программа считывает файл построчно и разбивает каждую строку на отдельные слова.
- Каждое слово проверяется на наличие в хэш-таблице. Если слово уже присутствует в хэш-таблице, увеличивается его счетчик. Если слова нет в хэш-таблице, оно добавляется в хэш-таблицу.
- В конце программы выводятся наиболее часто встречающиеся слова в порядке убывания их частоты.
- Для определения хэш-функции используется функция __calc_hash, которая преобразует слово в верхний регистр, суммирует значения символов и берет остаток от деления на размер массива MAX_SIZE.
- Для сравнения двух строк используется функция __scmp, которая сравнивает символы строк до тех пор, пока не найдет различие или не достигнет конца одной из строк.
- Для чтения файла используется функция readfile, которая открывает файл, считывает его содержимое в буфер и возвращает указатель на буфер. Если файл не может быть прочитан, функция возвращает NULL.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д