Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
0 / 0 / 0
Регистрация: 17.07.2017
Сообщений: 7
1

Определить количество букв, слов и строк

17.07.2017, 17:12. Показов 1329. Ответов 15
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте
Существует задача:
есть файл с произвольным текстом (заранее неизвестным). Необходимо открыть этот файл, считать с него текст и вывести информацию: сколько раз встречаются в этом тексте буквы, слова и строки.
По каждой букве вывести статистику в виде "Буква" - "Сколько раз встречается в тексте".
По каждому слову также вывести статистику в виде "Слово" - "Сколько раз встречается в тексте"
А также - общее количество строк, которое есть в тексте.
На текущий момент застопорился на выводе статистики по словам. Не могу сообразить какой создать цикл для вывода информации по каждому слову. Текст из файла читается в массив, а весь из массива как я понимаю, необходимо разбить на части через strtok (для разделения текста по словам). Но что делать дальше - не могу понять.

На текущий момент имеется код:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#define DELIMS " .,!?\t\n;:-'""
 
int main() {
    
    FILE *fp = fopen("C:\\file.txt","r");
    int count[26], num, letter,qtyStr=0;
    char str[512];
    char word1[256];
    char word2[256];    
    char *pstr;
    size_t size,i,j;
 
    if (fp == NULL) {
        printf("File not found!\n");
        return 0;
    }
    
    fgets(str,1024,fp);
    printf("%s\n", str);    
        
    // How many times any letters occured
    for (i=0; i < 26; i++)
    count[i]=0;
    for (i=0;i<strlen(str);i++){
    num=-1;
    if (str[i] >= 'a' && str[i] <='z')
    num = str[i] - 'a';
    if (str[i] >= 'A' && str[i] <='Z')
    num = str[i] - 'A';
    if (num >= 0) count[num]++;
    }
    
    for (i=0;i<26;i++){
        if (count[i] > 0)
        printf("%c - %d\n", 'A'+i, count[i]);
    }
 
    
    /*  while (pstr = strtok(str,DELIMS), pstr != NULL, pstr = strtok(NULL,DELIMS)){    
        }
    */
        getch();
    
    fclose(fp);
    system("pause");
    return 0;
}
Может, есть у кого какие идеи?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.07.2017, 17:12
Ответы с готовыми решениями:

Подсчитать количество букв, слов и строк ввода
Написать программу, подсчитывающую количество букв, слов и строк ввода. Пример программы...

Строка состоит из 3-ех слов.Определить какое из слов содержит наибольшее количество гласных букв
Строка состоит из 3-ех слов.Определить какое из слов содержит наибольшее количество гласных...

Подсчет количество: строк, слов, букв в open файле
Помогите пожалуйста сделать/доделать/переделать/ так чтобы считало количество строк, слов и букв в...

Определить, сколько букв, слов и строк в файле
Дан файл. Определите сколько в нем букв (латинского алфавита), слов, строк. Выведите три найденных...

15
1287 / 880 / 254
Регистрация: 30.06.2015
Сообщений: 4,592
Записей в блоге: 51
17.07.2017, 17:25 2
Заметил несколько моментов:

C
1
#define DELIMS " .,!?\t\n;:-'""
а надо поставить обратные слэши перед одинарной и двойной кавычками
далее обьявляешь :
C
1
char str[512];
а потом выход далеко за предел:
C
1
fgets(str,1024,fp);
здесь ты используешь паскалевский способ, который в паскале вычисляется на этапе компиляции, в отличии от си где strlen вызывается на каждом круге в ран-тайме:
C
1
for (i=0;i<strlen(str);i++){
да и так по строкам не лазят, а сравнивают с терминальным нулём, почитай учебник.
Это то что пока сразу бросается в глаза
0
0 / 0 / 0
Регистрация: 17.07.2017
Сообщений: 7
17.07.2017, 18:50  [ТС] 3
Спасибо! Первые 2 момента - обычная невнимательность.
Насчет 3-го - исправил
C
1
  i < strlen(str)
на
C
1
str[i] != '\0'
В целом, с выводом букв вроде все понятно. Но что делать с выводом количества слов? По крайней мере с повторяющимися словами?
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
12458 / 7482 / 1753
Регистрация: 25.07.2009
Сообщений: 13,762
17.07.2017, 18:52 4
Цитата Сообщение от CoderHuligan Посмотреть сообщение
паскалевский способ, который в паскале вычисляется на этапе компиляции,
Если можно, подробнее, как Паскаль вычисляет на этапе компиляции длину строки, которая ещё не введена даже? Другое дело - паскалевские короткие строки свою длину в нулевом байте держат. По этому они во-первых не могут быть длиннее 255 символов, а во-вторых их длина действительно не вычисляется...

michael2233, очевидное решение - нужен контейнер типа map, который ключами будет хранить слова, а значениями количество их вхождений. Можно самоделку сделать, можно из GLib готовый взять. Но судя по
Цитата Сообщение от michael2233 Посмотреть сообщение
#include <conio.h>
второй вариант - не ваш случай...
0
1287 / 880 / 254
Регистрация: 30.06.2015
Сообщений: 4,592
Записей в блоге: 51
18.07.2017, 11:41 5
Цитата Сообщение от easybudda Посмотреть сообщение
По этому они во-первых не могут быть длиннее 255 символов, а во-вторых их длина действительно не вычисляется...
Это я и имел в виду. В паскале код:
Pascal
1
for i:=1 to Length(s) do...
не имеет накладных расходов, так как если длина строки не задана явно, то подставится её наибольшее значение для данного компилятора. Во всяком случае её длина не будет вычисляться в ран-тайм, поэтому те, кто переходят с паскаля на си имеют в этом смысле затруднение.
0
0 / 0 / 0
Регистрация: 17.07.2017
Сообщений: 7
18.07.2017, 18:47  [ТС] 6
Спасибо огромное за идею!
Цитата Сообщение от easybudda Посмотреть сообщение
michael2233, очевидное решение - нужен контейнер типа map, который ключами будет хранить слова, а значениями количество их вхождений. Можно самоделку сделать, можно из GLib готовый взять
А Вы можете подсказать, где посмотреть примеры создания собственного контейнера и работы с ним на Си? Или хотя бы пример привести?
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
12458 / 7482 / 1753
Регистрация: 25.07.2009
Сообщений: 13,762
18.07.2017, 19:16 7
Цитата Сообщение от michael2233 Посмотреть сообщение
где посмотреть примеры создания собственного контейнера и работы с ним на Си?
Не поверите! Прямо в этом разделе на форуме. Пару штук сам делал. Давно, правда, но кнопка "поиск" в помощь. Самое простое решение - дерево. Можно даже забить на балансировку. Ну выродится в список в самом плохом случае. Ключи - char*, значения - любой целочисленный тип, какой больше нравится (главное, чтобы количество вхождений слов помещалось).
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
struct NODE {
    const char * key;
    int value;
    struct NODE * left;
    struct NODE * right;
};
 
struct NODE * node_new(const char * wrd) {
    struct NODE * ptr = malloc(sizeof(struct NODE));
 
    if ( ! ptr )
        return NULL;
 
    ptr->key = wrd; // только надо помнить, что нельзя освобождать память, выделенную под строку, пока вся эта затея с деревом не кончится
                              // ну или дублировать то, что по указателю, функцией strdup или подобной самоделкой, но потом не забывать память возвращать
    ptr->value = 1;
    ptr->left = NULL;
    ptr->right = NULL;
 
    return ptr;
}
 
int node_add(struct NODE ** ptr, const char * wrd) {
    if ( ! *ptr )
        if ( ( *ptr = node_new(wrd) ) == NULL )
            return -1;
    else {
        int cmp = strcmp((*ptr)->key, wrd);
        if ( cmp < 0 )
            return node_add(&((*ptr)->right), wrd);
        else if ( cmp > 0 )
            return node_add(&((*ptr)->left), wrd);
        else
            (*ptr)->value += 1;
    }
    return 0;
}
В общих чертах как-то так. А функцию удаления отдельно взятого узла из дерева можно и вообще не писать, для этой задачи не понадобится. Только обход дерева с выводом слов и счётчиков + деструктор, вроде
C
1
2
3
4
5
6
7
void kill_tree(struct NODE * root) {
    if ( root ) {
        kill_tree(root->left);
        kill_tree(root->right);
        free(root);
    }
}
0
838 / 641 / 940
Регистрация: 26.06.2015
Сообщений: 1,409
19.07.2017, 04:24 8
Цитата Сообщение от michael2233 Посмотреть сообщение
Или хотя бы пример привести?
Вот написал подсчёт слов используя Рандомизированное(случайное) бинарное дерево поиска.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
 
struct node {
    struct node* left;
    struct node* right;
    const char*  key;
    unsigned int cnt;
    int cost;
};
 
typedef struct {
    struct node* root;
} rtree;
 
static struct node* new_node(const char* key);
static struct node* r_insert_root(struct node* ptr, const char* key);
static struct node* r_rotate(struct node* p, int left);
static void r_fixsize(struct node* p);
static void r_print(FILE* _out, struct node* p);
static void r_clear(struct node* p);
static struct node* r_insert(struct node* p, const char* key);
void rtree_init(rtree* tr) { tr->root = NULL; }
void rtree_add(rtree* tr, const char* key);
void rtree_print(FILE* _out, rtree* tr);
void rtree_clear(rtree* tr);
char* readfile(const char* filename);
 
int main(void){
    rtree tr;
    char* buf, *p;
    const char delim[] = " \r\n\t,.!?-;:";
    
    if((buf = readfile("file.txt")) == NULL)
        return 1;
 
    rtree_init(&tr);
    p = strtok(buf, delim);
    while(p != NULL){
        rtree_add(&tr, p);
        p = strtok(NULL, delim);
    }
 
    rtree_print(stdout, &tr);
    rtree_clear(&tr);
    free(buf);
    getchar();
    return 0;
}
 
void rtree_add(rtree* tr, const char* key){
    tr->root = r_insert(tr->root, key);
}
 
void rtree_print(FILE* _out, rtree* tr){
    if(tr->root != NULL)
        r_print(_out, tr->root);
}
 
void rtree_clear(rtree* tr){
    if(tr->root != NULL)
        r_clear(tr->root);
    tr->root = NULL;
}
 
//печать
static void r_print(FILE* _out, struct node* p){
    if(p->left != NULL)
        r_print(_out, p->left);
    fprintf(_out, "%s(%u)\n", p->key, p->cnt);
    if(p->right != NULL)
        r_print(_out, p->right);
}
 
//удаление всех
static void r_clear(struct node* p){
    if(p->left != NULL)
        r_clear(p->left);
    if(p->right != NULL)
        r_clear(p->right);
    free(p);
}
 
//вставка
static struct node* r_insert(struct node* p, const char* key){
    int ret;
    if(p == NULL)
        return new_node(key);
 
    ret = strcmp(key, p->key);
    if(ret == 0){
        p->cnt += 1;
        return p;
    }
 
    if(!(rand() % (p->cost + 1)))
        return r_insert_root(p, key);
 
    if(ret < 0)
        p->left = r_insert(p->left, key);
    else
        p->right = r_insert(p->right, key);
    r_fixsize(p);
    return p;
}
 
// вставка узла в корень дерева
static struct node* r_insert_root(struct node* p, const char* key){
    int ret;
    if(p == NULL)
        return new_node(key);
 
    ret = strcmp(key, p->key);
    if(ret == 0){
        p->cnt += 1;
        return p;
    } else if(ret < 0)
        p->left  = r_insert_root(p->left, key);
    else
        p->right = r_insert_root(p->right, key);
    return r_rotate(p, ret < 0);
}
 
//вращение
static struct node* r_rotate(struct node* p, int left){
    struct node* t = (left) ? p->right : p->left;
    if(t == NULL)
        return p;
 
    if(left){ // левый поворот вокруг узла
        p->right = t->left;
        t->left  = p;
    } else {  // правый поворот вокруг узла
        p->left  = t->right;
        t->right = p;
    }
    t->cost = p->cost;
    r_fixsize(p);
    return t;
}
 
static void r_fixsize(struct node* p){
    if(p != NULL){
        p->cost  = (p->left  != NULL) ? p->left->cost  : 0;
        p->cost += (p->right != NULL) ? p->right->cost : 0;
        p->cost += 1;
    }
}
 
static struct node* new_node(const char* key){
    struct node* p = (struct node*)malloc(sizeof(struct node));
    if(p != NULL){
        p->key  = key;
        p->cost = 1;
        p->cnt  = 1;
        p->left = p->right = NULL;
    }   
    return p;
}
 
//загрузка файла
char* readfile(const char* filename){
    long   m;
    char*  s  = NULL;
    FILE*  fp = fopen(filename, "rb");
    if(fp == NULL)
        return NULL;
 
    fseek(fp, 0L, SEEK_END);
    if((m = ftell(fp)) <= 0L)
        goto err;
    if((s = (char*)malloc((m + 1) * sizeof(char))) == NULL)
        goto err;
 
    fseek(fp, 0L, SEEK_SET);
    if(fread(s, 1, (size_t)m, fp) != (size_t)m)
        goto err;
 
    fclose(fp);
    s[m] = '\0';
    return s;
err:
    fclose(fp);
    if(s != NULL)
        free(s);
    return NULL;
}
2
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
12458 / 7482 / 1753
Регистрация: 25.07.2009
Сообщений: 13,762
19.07.2017, 17:35 9
Ну и просто для расширения кругозора
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <glib.h>
#include <gio/gio.h>
 
#define DELIM " \t\n,.!?()\'\"-"
 
gboolean print_counter(gpointer key, gpointer val, gpointer width) {
    g_print("%-*s | %d\n", GPOINTER_TO_INT(width), (char*)key, GPOINTER_TO_INT(val));
    return FALSE;
}
 
const int DEFAULT_WIDTH = 20;
 
int main(int argc, char ** argv) {
    if ( argc < 2 ) {
        g_print("Usage: %s <input_file>\n", *argv);
        return 1;
    }
    
    GFile * fin = g_file_new_for_path(argv[1]);
    char * buf;
    gsize length;
    GError * err = NULL;
    
    if ( ! g_file_load_contents(fin, NULL, &buf, &length, NULL, &err) ) {
        g_print("%s: can't read input file: %s\n", *argv, ( err ) ? err->message : "unknown reason");
        return 1;
    }
    
    g_object_unref(fin);
    
    char ** tokens = g_strsplit_set(buf, DELIM, -1);
    GTree * counters = g_tree_new((GCompareFunc)g_strcmp0);
    
    for ( char ** tok = tokens; *tok; ++tok )
        if ( **tok )
            g_tree_insert(counters, *tok, GINT_TO_POINTER(GPOINTER_TO_INT(g_tree_lookup(counters, *tok)) + 1));
    
    g_print("%-*s | %s\n", DEFAULT_WIDTH, "WORD", "MEETS");
    g_tree_foreach(counters, print_counter, GINT_TO_POINTER(DEFAULT_WIDTH));
    
    g_tree_destroy(counters);
    g_strfreev(tokens);
    g_free(buf);
    
    return 0;
}
Определить количество букв, слов и строк
1
0 / 0 / 0
Регистрация: 17.07.2017
Сообщений: 7
19.07.2017, 21:33  [ТС] 10
Огромное спасибо за пример! Правда, при попытке выяснить как какая функция работает в данном коде, оказалось, что данные из файла все же на печать не выводятся. Но я думаю, что разберусь с этим. В любом случае спасибо Вам большое!

Добавлено через 7 минут
Цитата Сообщение от easybudda Посмотреть сообщение
Ну и просто для расширения кругозора
И Вам огромное спасибо за помощь и идеи!
Теперь буду думать, стоит ли мне устанавливать себе Linux или хотя бы виртуальную машину на нем.
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
12458 / 7482 / 1753
Регистрация: 25.07.2009
Сообщений: 13,762
19.07.2017, 23:27 11
Цитата Сообщение от michael2233 Посмотреть сообщение
Теперь буду думать, стоит ли мне устанавливать себе Linux или хотя бы виртуальную машину на нем.
Ставьте, не задумывайтесь! По крайней мере будет, с чем сравнивать...

Ну и вот Вам ещё решение, как слова посчитать (проще, но тупее): затолкать все слова в массив (с разделением текста на слова Вы, как я понял, справитесь), отсортировать и считать повторяющиеся (они в отсортированном массиве подряд идут)...
0
0 / 0 / 0
Регистрация: 17.07.2017
Сообщений: 7
23.07.2017, 00:02  [ТС] 12
Цитата Сообщение от easybudda Посмотреть сообщение
Ну и вот Вам ещё решение, как слова посчитать (проще, но тупее): затолкать все слова в массив (с разделением текста на слова Вы, как я понял, справитесь), отсортировать и считать повторяющиеся (они в отсортированном массиве подряд идут)...
Если не смогу сразу разобраться с деревьями, то попробую и с помощью массивов сделать. В любом случае для сравнения попробовать можно.

А еще вопрос: в бинарных деревьях можно ли сделать как-либо сортировку по возрастанию элементов (без участия массива). Как в Вашем примере сделать для поля MEETS сортировку от 1 до 11 в порядке возрастания количества повторяющихся слов?
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
12458 / 7482 / 1753
Регистрация: 25.07.2009
Сообщений: 13,762
23.07.2017, 02:16 13
Цитата Сообщение от michael2233 Посмотреть сообщение
в бинарных деревьях можно ли сделать как-либо сортировку по возрастанию элементов (без участия массива).
Нет, так не получится. В дереве данные сортируются по ключу (по строке в нашем случае). Если нужно вывести отсортированными по количеству вхождений, прийдётся создавать другое дерево, где ключами будут счётчики, а значениями списки слов, либо какую-то другую конструкцию для хранения пар (слово, счётчик). Тогда проще сразу по-другому сделать:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <glib.h>
#include <gio/gio.h>
 
#define DELIM " \t\n,.!?()'`-"
 
typedef struct WCNT {
    const char * wrd;
    int cnt;
} wcnt_t;
 
wcnt_t * wcnt_new(const char * w) {
    wcnt_t * p = g_new(wcnt_t, 1);
    
    p->wrd = w;
    p->cnt = 1;
    
    return p;
}
 
int wcnt_compare_words(const wcnt_t * a, const wcnt_t * b) {
    return g_strcmp0(a->wrd, b->wrd);
}
 
int wcnt_compare_counters(const wcnt_t * a, const wcnt_t * b) {
    return a->cnt - b->cnt;
}
 
void wcnt_dump(const wcnt_t * p, const void * w) {
    g_print("%-*s | %d\n", GPOINTER_TO_INT(w), p->wrd, p->cnt);
}
 
const int DEFAULT_WIDTH = 20;
 
int main(int argc, char ** argv) {
    if ( argc < 2 ) {
        g_print("Usage: %s <input_file>\n", *argv);
        return 1;
    }
    
    GFile * fin = g_file_new_for_path(argv[1]);
    char * buf;
    gsize length;
    GError * err = NULL;
    
    if ( ! g_file_load_contents(fin, NULL, &buf, &length, NULL, &err) ) {
        g_print("%s: can't read input file: %s\n", *argv, ( err ) ? err->message : "unknown reason");
        return 1;
    }
    
    g_object_unref(fin);
    
    char ** tokens = g_strsplit_set(buf, DELIM, -1);
    g_free(buf);
    
    GList * list = NULL;
    
    for ( char ** token = tokens; *token; ++token ) {
        if ( **token ) {
            wcnt_t * p = wcnt_new(*token);
            GList * iter = g_list_find_custom(list, p, (GCompareFunc)wcnt_compare_words);
            if ( iter ) {
                ((wcnt_t*)(iter->data))->cnt += 1;
                g_free(p);
            }
            else
                list = g_list_prepend(list, p);
        }
    }
    list = g_list_sort(list, (GCompareFunc)wcnt_compare_counters);
    
    g_print("%-*s | %s\n", DEFAULT_WIDTH, "WORD", "MEETS");
    g_list_foreach(list, (GFunc)wcnt_dump, GINT_TO_POINTER(DEFAULT_WIDTH));
    
    g_list_free_full(list, g_free);
    g_strfreev(tokens);
    
    return 0;
}
0
0 / 0 / 0
Регистрация: 17.07.2017
Сообщений: 7
29.07.2017, 18:36  [ТС] 14
В общем, вот что получилось на текущий момент:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
 
#define DELIMS " .,!?\t\n;:-\'"""
 
// word control
typedef struct word {
    struct word *next;              // linked list pointer
    char *str;                      // pointer to word string
    int count;                      // word frequency count
} word_t;
 
word_t wordlist;                    // list of words
 
// cleanword -- strip chaff and clean up word
void
cleanword(char *dst,const char *src)
{
    int chr;
 
    // NOTE: using _two_ buffers in much easier than trying to clean one buffer in-place
    for (chr = *src++;  chr != 0;  chr = *src++) {
        if (! isalpha(chr))
            continue;
        chr = tolower(chr);
        *dst++ = chr;
    }
 
    *dst = 0;
}
 
// addword -- add unique word to list and keep count of number of words
void
addword(const char *str)
{
    word_t *cur;
    word_t *prev;
    char word[1000];
 
    // get the cleaned up word
    cleanword(word,str);
 
    // find a match to a previous word [if it exists]
    prev = NULL;
    for (cur = wordlist.next;  cur != NULL;  cur = cur->next) {
        if (strcmp(cur->str,word) == 0)
            break;
        prev = cur;
    }
 
    // found a match -- just increment the count (i.e. do _not_ create a
    // duplicate that has to be removed later)
    if (cur != NULL) {
        cur->count += 1;
        return;
    }
 
    // new unique word
    cur = malloc(sizeof(word_t));
    if (cur == NULL)
        printf("Malloc failure!\n");
 
    cur->count = 1;
    cur->next = NULL;
 
    // save off the word string
    cur->str = strdup(word);
    if (cur->str == NULL)
        printf ("Strdup failure!\n");
 
    // add the new word to the end of the list
    if (prev != NULL)
        prev->next = cur;
 
    // add the first word
    else
        wordlist.next = cur;
}
 
main(int argc,char **argv)
{
    FILE *fp;
    char buf[1000];
    char *cp;
    char *bp;
    word_t *cur;
 
 
    fp = fopen("input.txt","r");
    if (fp == NULL)
       printf("Can not to open file!\n");
 
    while (1) {
        // get next line
        cp = fgets(buf,sizeof(buf),fp);
        if (cp == NULL)
            break;
 
        // loop through all words on a line
        bp = buf;
        while (1) {
            cp = strtok(bp,DELIMS);
            bp = NULL;
 
            if (cp == NULL)
                break;
 
            // add this word to the list [avoiding duplicates]
            addword(cp);
        }
    }
 
    fclose(fp);
 
    // print the words and their counts
    for (cur = wordlist.next;  cur != NULL;  cur = cur->next)
        printf("%s %d\n",cur->str,cur->count);
 
    return 0;
}
Подскажите как можно сделать сортировку по параметру count (по возрастанию)?
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
12458 / 7482 / 1753
Регистрация: 25.07.2009
Сообщений: 13,762
29.07.2017, 23:59 15
Лучший ответ Сообщение было отмечено michael2233 как решение

Решение

Как говорил один азербайджанский торговец на вещевом рынке, БЭС ПРЫБАМБАСАФ!
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
 
typedef struct WCNT {
    char * wrd;
    size_t cnt;
} wcnt_t;
 
wcnt_t * wcnt_new(const char * wrd) {
    wcnt_t * ptr = malloc(sizeof(wcnt_t));
    assert(ptr);
    ptr->wrd = malloc(strlen(wrd) + 1);
    assert(ptr->wrd);
    strcpy(ptr->wrd, wrd);
    ptr->cnt = 1;
 
    return ptr;
}
 
void wcnt_free(wcnt_t * ptr) {
    free(ptr->wrd);
    free(ptr);
}
 
typedef struct WCNT_LIST {
    wcnt_t * counter;
    struct WCNT_LIST * next;
} wcnt_list_t;
 
void wcnt_list_append(wcnt_list_t ** listPtr, const char * wrd) {
    if ( ! *listPtr ) {
        *listPtr = malloc(sizeof(wcnt_list_t));
        assert(*listPtr);
        (*listPtr)->counter = wcnt_new(wrd);
        (*listPtr)->next = NULL;
    }
    else if ( strcmp((*listPtr)->counter->wrd, wrd) == 0 )
        (*listPtr)->counter->cnt += 1;
    else
        wcnt_list_append(&((*listPtr)->next), wrd);
}
 
void wcnt_list_sort_by_cnt(wcnt_list_t * list) {
    wcnt_list_t * nextPtr, * minPtr = list;
 
    if ( ! minPtr )
        return;
 
    for ( nextPtr = list->next; nextPtr; nextPtr = nextPtr->next )
        if ( nextPtr->counter->cnt < minPtr->counter->cnt )
            minPtr = nextPtr;
 
    if ( minPtr != list ) {
        wcnt_t * tmp = minPtr->counter;
        minPtr->counter = list->counter;
        list->counter = tmp;
    }
 
    wcnt_list_sort_by_cnt(list->next);
}
 
void wcnt_list_free(wcnt_list_t * list) {
    while ( list ) {
        wcnt_list_t * next = list->next;
        wcnt_free(list->counter);
        free(list);
        list = next;
    }
}
 
/******************************************************************************/
/********************************* MAIN ***************************************/
/******************************************************************************/
 
#define DELIM " ,.!?\t\n"
#define WORD_FIELD 20
 
int main(int argc, char *argv[]) {
    FILE * f;
    char buf[BUFSIZ], * wptr;
    wcnt_list_t * lptr, * list = NULL;
 
    if ( argc != 2 ) {
        fprintf(stderr, "USAGE: %s <input_file_name>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
 
    if ( ( f = fopen(argv[1], "r") ) == NULL ) {
        fprintf(stderr, "%s: can't open input file!\n", argv[0]);
        exit(EXIT_FAILURE);
    }
 
    while ( fgets(buf, BUFSIZ, f) )
        for ( wptr = strtok(buf, DELIM); wptr; wptr = strtok(NULL, DELIM) )
            wcnt_list_append(&list, wptr);
 
    fclose(f);
 
    if ( ! list ) {
        fprintf(stderr, "%s: no words found!\n", argv[0]);
        exit(EXIT_FAILURE);
    }
 
    wcnt_list_sort_by_cnt(list);
 
    printf("%-*s | %s\n", WORD_FIELD, "WORD", "COUNT");
    for ( lptr = list; lptr; lptr = lptr->next )
        printf("%-*s | %u\n", WORD_FIELD, lptr->counter->wrd, (unsigned)lptr->counter->cnt);
 
    wcnt_list_free(list);
    exit(EXIT_SUCCESS);
}
Код
[andrew@andrew WordsCounter]$ gcc -Wall -ansi -pedantic -o words_counter main.c 
[andrew@andrew WordsCounter]$ ./words_counter jingle.txt 
WORD                 | COUNT
all                  | 2
the                  | 2
way                  | 2
what                 | 2
fun                  | 2
it                   | 2
is                   | 2
to                   | 2
ride                 | 2
In                   | 2
a                    | 2
one                  | 2
horse                | 2
open                 | 2
sleigh               | 2
Jingle               | 3
Oh                   | 3
jingle               | 3
bells                | 4
[andrew@andrew WordsCounter]$
Код
[andrew@andrew WordsCounter]$ cat jingle.txt 
Oh, jingle bells, jingle bells
Jingle all the way
Oh, what fun it is to ride
In a one horse open sleigh
Jingle bells, jingle bells
Jingle all the way
Oh, what fun it is to ride
In a one horse open sleigh
[andrew@andrew WordsCounter]$
0
0 / 0 / 0
Регистрация: 17.07.2017
Сообщений: 7
10.08.2017, 21:40  [ТС] 16
В общеми целом всем огромное спасибо за помощь! Задача решена, в том, в чем было необходимо, разобрался!
Цитата Сообщение от easybudda Посмотреть сообщение
Как говорил один азербайджанский торговец на вещевом рынке, БЭС ПРЫБАМБАСАФ!
Вам отдельное спасибо за помощь!
0
10.08.2017, 21:40
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.08.2017, 21:40
Помогаю со студенческими работами здесь

Определить количество слов в строке и вывести на экран все слова, количество букв у которых нечетное.
Помогите, пожалуйста решить задачу по на С++Builder6 Дана строка текста, в которой слова разделены...

Строка: Подсчитать и вывести на экран количество слов и количество всех букв в предложении,а также количество букв 'b'.
Считать предложение из файла .Слова разделены двумя пробелами. Подсчитать и вывести на экран...

Определить количество слов в тексте, состоящих из K букв
Даны числа K и текст из слов, разделенных пробелами, в конце – точка. Определить количество слов...

Определить количество слов, начинающихся с гласных букв
2. Дана строка символов. Определить количество слов, начинающихся с гласных букв. Вывести на экран...

Определить количество слов состоящих из менее 5 букв
Написать программу, которая считывает текст из файла и определяет, сколько в нем слов состоящих из...

Определить количество слов в тексте, состоящих из K букв. C#/C++
Даны числа K и текст из слов разделенными пробелами, в конце точка. Определить количество слов в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru