Форум программистов, компьютерный форум CyberForum.ru

Количество вхождений слова в файл - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 24, средняя оценка - 4.71
lesorub_
2 / 2 / 0
Регистрация: 20.02.2011
Сообщений: 51
21.02.2011, 19:07     Количество вхождений слова в файл #1
Здравствуйте, уважаемые программисты! Нужна Ваша помощь, какая именно, речь пойдет далее

Для начала я скажу, что программа делает, и приложу свой код, который состряпал:

Программа, которая определяет, сколько раз в текстовом файле, не содержащем переносов слов, встречается заданное слово, вводимое с клавиатуры.

Вот код:
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
#include "stdafx.h"
 
using namespace std;
 
int main()
{
    const int len = 255;
    char word[len], line[len];
    int branch;
    setlocale(LC_ALL, "Russian");
    
    do {
        cout << "Введите слово для поиска: ";
        cin >> word;
        int l_word = strlen(word);
        ifstream fin ("text.txt");
        if (!fin) 
            {
                cout << "Ошибка открытия файла." << endl;
                return 1;
            }
 
    int count = 0;
    
    while (fin.getline(line, len))
    {
        char *p = line;
        
        while(p=strstr(p, word))
        {
            cout << "Cовпадение в подстроке: " << p << endl;
            char *c=p;
            p+=l_word;
            
            if(c!=line)
                if (!ispunct(*(c-1)) && !isspace(*(c-1)))
            continue;
            if (ispunct(*p) || isspace(*p) || (*p == '\0'))
                count++;
        }
    }
    cout << endl << "Слово " << word << " встретилось в файле " << count << " раз(а)." << endl; 
    cout << "\nЧтобы продолжить поиск, нажмите '1'. Чтобы выйти из программы, нажмите '2'.\n";  
    cin >> branch;
        }   
    while (branch!=2);
    return 0;
А вот сами вопросы:

1) как сделать, чтобы поиск производился без учета регистра? (например, пишу в файле слово Cat и cat, слова одинаковые, но разный регистр, соответственно у меня определяет кол-во вхождений cat 1 раз;

2) почему требуется контрольный вывод в строке /*cout << "Cовпадение в подстроке: " << p << endl;*/
Без него программа не определяет символ, стоящий после введенного слова. К примеру, пишу cat и catw, программа без этой строки находит 2 совпадения, считая что cat и catw одинаковые слова.

3) Как в C++ сделать выход из цикла по нажатии клавиш Ctrl+Z?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.02.2011, 19:07     Количество вхождений слова в файл
Посмотрите здесь:

C++ Распечатать количество вхождений заданного слова в каждую строку и заменить его на другое заданное слово
C++ Подсчёт вхождений каждого слова в текстовом файле[C++]
C++ Подсчитать количество вхождений введенного с клавиатуры слова в строку
C++ Вывести в выходной файл все слова, начинающиеся на заданную букву, и их количество
Дан файл f, компоненты которого являются целыми числами. Получить файл g, образованный из файла f исключением повторных вхождений одного и того же чис C++
Строки. Определить количество вхождений заданного слова в текст C++
Определить количество вхождений каждого слова в заданную строку C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
lesorub_
2 / 2 / 0
Регистрация: 20.02.2011
Сообщений: 51
23.02.2011, 13:47  [ТС]     Количество вхождений слова в файл #2
поднимаю тему, т.к. она опустилась аж на 3-ю страницу О_о
Mr.X
Эксперт С++
 Аватар для Mr.X
3011 / 1667 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
23.02.2011, 17:43     Количество вхождений слова в файл #3
Вот так считает не только без учета регистра, но и при наличии знаков препинания:
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
///////////////////////////////////////////////////////////////////////////////////////// 
//Программа, которая определяет, сколько раз в текстовом файле, не содержащем 
//переносов слов, встречается заданное слово, вводимое с клавиатуры.
///////////////////////////////////////////////////////////////////////////////////////// 
#include <algorithm> 
#include <fstream> 
#include <iostream> 
#include <iterator> 
#include <locale> 
#include <string> 
#include <windows.h> 
///////////////////////////////////////////////////////////////////////////////////////// 
typedef std::string  T_str;
/////////////////////////////////////////////////////////////////////////////////////////
T_str  from_DOS(T_str  DOS_string)
{    
    char buf[1000000];   
    OemToCharA(DOS_string.c_str(), buf);
    return buf;
}
/////////////////////////////////////////////////////////////////////////////////////////
int main()
{
    std::locale::global(std::locale(""));
 
    for(;;)
    {
        T_str  filename("text.txt");
        std::ifstream  fin(filename.c_str());
        if(!fin) 
        {
            std::cout << "Ошибка открытия файла "
                      << filename
                      << "." 
                      << std::endl;
            exit(0);
        }
 
        std::cout << std::endl
                  << std::endl
                  << std::endl
                  << "Введите слово для поиска: ";
        T_str  DOS_word_for_count;
        getline(std::cin, DOS_word_for_count); 
        if(DOS_word_for_count.empty())  break;
        T_str  word_for_count(from_DOS(DOS_word_for_count));
 
        struct  T_word_eq_without_match_case_and_puncts
        {            
            T_str  word_for_count_;
            //---------------------------------------------------------------------------
            T_word_eq_without_match_case_and_puncts(const T_str&  word_for_count) 
                : word_for_count_(word_for_count)
            {}
            //---------------------------------------------------------------------------
            struct  T_rus_symb_comp_without_match_case
            {
                bool  operator() (char L, char R)
                {
                    return tolower(L, std::locale("")) == tolower(R, std::locale(""));
                }        
            };
            //---------------------------------------------------------------------------
            bool  operator() (T_str  word_cur)
            { 
                while(std::ispunct(word_cur[0], std::locale("")))
                {
                    word_cur.erase(0, 1);
                }
                          
                while(std::ispunct(word_cur[word_cur.size() - 1], std::locale(""))) 
                {
                    word_cur.erase(word_cur.size() - 1);
                }
 
                return    word_cur.size() == word_for_count_.size()
                       && std::equal(word_cur.begin(), word_cur.end(), word_for_count_.begin(), 
                                     T_rus_symb_comp_without_match_case());
            }
        };//struct  T_word_eq_without_match_case_and_puncts
        
        std::istream_iterator<T_str>  fit_beg(fin);
        std::istream_iterator<T_str>  fit_end;
 
        int  word_count = std::count_if(fit_beg, fit_end, 
                                        T_word_eq_without_match_case_and_puncts(word_for_count));
 
        std::cout << "В файле "
                  << filename
                  << " слово \""
                  << word_for_count
                  << "\" встречается "
                  << word_count
                  << " раз."
                  << std::endl;      
    }//for
}
lesorub_
2 / 2 / 0
Регистрация: 20.02.2011
Сообщений: 51
26.02.2011, 15:46  [ТС]     Количество вхождений слова в файл #4
Большое спасибо, всё работает как надо Сейчас буду разбираться в изменениях. Даже поиск с участием кириллицы организовал, класс

Добавлено через 2 часа 41 минуту
По ходу разбора кода программы возникли такие вопросы(извините, если нубские, я не ас в программировании, но хочу разобраться)

1. в строках с 15-20 описывается функция для перевода в ASCII кодировку?

2. в строке 43 DOS_word_for_count это переменная? А T_str определение строки?

3. в строке 52 пишется функция, а что означают её параметры?

4. не могу понять, что написано в строках 82-83.

Сразу скажу, с алгоритмами и контейнерами дело не имел, возможно большинство непоняток именно отсюда
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7933 / 4715 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
26.02.2011, 16:49     Количество вхождений слова в файл #5
lesorub_, Позволю себе ответить на ваши вопросы.

1) Вроде да.
2) T_str - синоним типа std::string определенный через typedef.
3) 52 строка - конструтор структуры. Передаем строку в структуру.
4) Определяются итераторы ввода для строк. Первый инициализируется файловым потоком, второй - прекращение ввода, поэтому конструктор пуст (по сути ловит сигнал EOF).
lesorub_
2 / 2 / 0
Регистрация: 20.02.2011
Сообщений: 51
26.02.2011, 16:56  [ТС]     Количество вхождений слова в файл #6
Благодарю за ответы, Видимо, у меня всё это ещё впереди

А не могли бы Вы мне подсказать функцию, которая сравнивает к примеру две подстроки без учета регистра? Знаю функцию strcmp, но она считает слова к примеру robot и RoBoT разными, т.е. учитывает их регистр.
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4247 / 2779 / 219
Регистрация: 12.12.2009
Сообщений: 7,109
Записей в блоге: 1
Завершенные тесты: 1
26.02.2011, 17:08     Количество вхождений слова в файл #7
1. в строках с 15-20 описывается функция для перевода в ASCII кодировку?
Не вдаваясь в подробности это перевод из DOS кодировки в ANSI. А нужно это, чтоб использовать кирилицу в программе.

Добавлено через 2 минуты
Набор символов OEM
Цитата Сообщение от перевод MSDN.COM
Набор символов OEM обычно используется в полноэкранном сеансе MS-DOS для показа на экране. Символы с кодом от 32 до 127 в OEM обычно те же самые, что в американском ASCII, и наборах символов Windows. Другие знаки в наборе символов OEM (0 до 31 и 128 до 255) соответствуют символам, которые могут быть отображены в полноэкранном сеансе MS-DOS. Эти символы обычно отличаются от символов Windows
asics
Freelance
Эксперт C++
 Аватар для asics
2841 / 1778 / 144
Регистрация: 09.09.2010
Сообщений: 3,842
26.02.2011, 17:15     Количество вхождений слова в файл #8
Цитата Сообщение от lesorub_ Посмотреть сообщение
А не могли бы Вы мне подсказать функцию, которая сравнивает к примеру две подстроки без учета регистра? Знаю функцию strcmp, но она считает слова к примеру robot и RoBoT разными, т.е. учитывает их регистр.
http://www.cyberforum.ru/cpp-beginne...ead233262.html
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7933 / 4715 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
26.02.2011, 17:18     Количество вхождений слова в файл #9
lesorub_, stricmp если Си.
В С++ встроенной нету - например

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <string>
#include <iostream>
#include <cctype>
 
std::string strtolower(const std::string& str)
{
   std::string res=str;
   for(std::string::iterator iter=res.begin(); iter != res.end(); ++iter)
      *iter=tolower(*iter);
   return res;
}
 
int main()
{
    std::string str1="RoBoT";
    std::string str2="rObOt";
    if(strtolower(str1) == strtolower(str2))
       std::cout<<"Real\n";
    else
       std::cout<<"Impossible\n";
    return 0;
}
lesorub_
2 / 2 / 0
Регистрация: 20.02.2011
Сообщений: 51
26.02.2011, 19:08  [ТС]     Количество вхождений слова в файл #10
Всем большое спасибо за помощь!

Все вопросы решил кроме одного: сделать выход из цикла по нажатии сочетания клавиш Ctrl+Z.
Например у меня реализован простенький цикл do{код} while(i!=1); То есть при каждом выводе кол-ва вхождений слова в файл пользователю предлагается нажать на выбор клавишу отличную от '1' для продолжения поиска.(такой вариант плохой)
Гораздо удобнее осуществлять поиск до тех пор, пока не будет нажата какая-нибудь клавиша. т.е. вводишь слово - находишь, потом выполняется автоматический переход в начало цикла для ввода следующего слова. Если пользователю захотелось выйти из программы, то он к примеру нажимает ctrl+z, происходит выход из цикла и завершение программы.

Вот по сути и вопрос, как такой цикл организовать?
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4247 / 2779 / 219
Регистрация: 12.12.2009
Сообщений: 7,109
Записей в блоге: 1
Завершенные тесты: 1
26.02.2011, 21:56     Количество вхождений слова в файл #11
Цитата Сообщение от lesorub_ Посмотреть сообщение
то он к примеру нажимает ctrl+z
Если подразумеваеться, что пользователь может нажать ctrl+z в любой момент выполнения программы, то простыми средствами С/С++ тут не обойтись (не знаю, может есть какая-нибудь сторонняя библиотека, позволяющая это делать). Если речь идет о программе под Windows, то можно использовать Win API.

Цитата Сообщение от lesorub_ Посмотреть сообщение
происходит выход из цикла и завершение программы.
Можно нажать ctrl+C, Виндовз любезно предоставляет такой сервис, для завершения и выхода из консольного приложения.
Digit@ll
Brainsbreaker
 Аватар для Digit@ll
832 / 343 / 27
Регистрация: 01.02.2011
Сообщений: 1,485
26.02.2011, 22:11     Количество вхождений слова в файл #12
Цитата Сообщение от Kastaneda Посмотреть сообщение
может есть какая-нибудь сторонняя библиотека
Нет никаких сторонних, все местные... API рулит. )
Kastaneda
26.02.2011, 22:14
  #13

Не по теме:

Я имел ввиду какую-нибудь библиотеку, написанную специально под С/С++.

lesorub_
2 / 2 / 0
Регистрация: 20.02.2011
Сообщений: 51
26.02.2011, 23:23  [ТС]     Количество вхождений слова в файл #14
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
while (fin.getline(line, len)) // читаем строку
        {
                char *p = line; // указатель для хранения позиции на найденной подстрокой
                
                while(strstr(p, word)) //можно ли strstr заменить на stricmp? (Просто функции разного типа)
                {
                        
                        char *c=p; // хранение адреса начала вхождения подстроки
                        p+=l_word; наращиваем позицию на длину подстроки
                        
                        if(c!=line)
                                if (!ispunct(*(c-1)) && !isspace(*(c-1)))
                        continue;
                        if (ispunct(*p) || isspace(*p) || (*p == '\0'))
                                count++; // счетчик количества вхождений
                }
        }
говорят, что можно намного проще производить поиск без учета регистра, не используя написания собственным функций. Ведь функции из С и C++ можно совмещать. На форуме я узнал, что функция для сравнения двух подстрок без учета регистра stricmp, вот только как её правильно применить, особо не раздувая код?
(Вверху привел участок кода, отвечающего на поиск подстроки в файле) Хочется это опробывать на своём уровне - уровне новичка. Код во втором посте конечно крут, но он пока не для моего уровня, придет время, изучу алгоритмы и контейнеры, благо в учебнике они есть. А вот по строкам там мало что рассказывается)
Mr.X
Эксперт С++
 Аватар для Mr.X
3011 / 1667 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
27.02.2011, 00:24     Количество вхождений слова в файл #15
Цитата Сообщение от lesorub_ Посмотреть сообщение
На форуме я узнал, что функция для сравнения двух подстрок без учета регистра stricmp
Она нестандартная.
lesorub_
2 / 2 / 0
Регистрация: 20.02.2011
Сообщений: 51
27.02.2011, 12:46  [ТС]     Количество вхождений слова в файл #16
Цитата Сообщение от Mr.X Посмотреть сообщение
Она нестандартная.
Это значит, что функция не имеет прототипа в заголовочном файле? Но ведь использовать её можно?
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4247 / 2779 / 219
Регистрация: 12.12.2009
Сообщений: 7,109
Записей в блоге: 1
Завершенные тесты: 1
27.02.2011, 12:54     Количество вхождений слова в файл #17
Это значит, что не каждый компилятор ее поддреживает.
lesorub_
2 / 2 / 0
Регистрация: 20.02.2011
Сообщений: 51
27.02.2011, 17:25  [ТС]     Количество вхождений слова в файл #18
А можно переделать эту функцию, чтобы она сравнивала не строки, а массивы символов, т.е. с типом char? Допустим, если строка фиксированной длинны, слово тоже, то как сделать аналогию ниже приведенной функции, сравнивающей без учета регистра ?

C++
1
2
3
4
5
6
7
std::string strtolower(const std::string& str)
{
   std::string res=str;
   for(std::string::iterator iter=res.begin(); iter != res.end(); ++iter)
      *iter=tolower(*iter);
   return res;
}
Добавлено через 3 часа 1 минуту
нашел в C возможность реализации выхода по нажатии Ctrl+Z, правда пришлось расставлять метки с goto, что, я слышал, не очень хорошо для современного стандарта.
C
1
scanf("%d",&branch)!=EOF
Это я запихнул в цикл, поставил 2 метки, одну на сам цикл, другую на начало тела цикла, чтобы при первом запуске программы игнорировалась проверка его условия.

А вот написать функцию для сравнения массивов строк что-то не получается
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7933 / 4715 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
27.02.2011, 18:01     Количество вхождений слова в файл #19
C++
1
2
3
4
5
6
7
8
char* strtolower(const char* str)
{
   char* res=new char(strlen(str)+1);
   strcpy(res, str);
   for(size_t i=0; i<strlen(res); ++i)
      res[i]=tolower(res[i]);
   return res;
}
Функция тупо переводит строку в нижний регистр. Далее можно сравнивать обычным strcmp

Добавлено через 3 минуты
Пример

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <cstring>
 
char* strtolower(const char* str)
{
    char* res=new char(strlen(str)+1);
    strcpy(res, str);
    for(size_t i=0; i<strlen(res); ++i)
        res[i]=tolower(res[i]);
    return res;
}
 
int main()
{
    if(!strcmp(strtolower("HeLLo"), strtolower("hEllO")))
        std::cout<<"Real\n";
    else
        std::cout<<"Impossible\n";
    return 0;
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.02.2011, 18:36     Количество вхождений слова в файл
Еще ссылки по теме:

C++ Посчитать количество всех букв и количество вхождений каждой буквы
Определить количество вхождений каждого слова C++
C++ Дана строка, вывести различные слова и число их вхождений
Записать в файл заданное количество строк из слова и его номера по порядку C++
Найти в тексте количество вхождений определенного слова C++

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

Или воспользуйтесь поиском по форуму:
lesorub_
2 / 2 / 0
Регистрация: 20.02.2011
Сообщений: 51
27.02.2011, 18:36  [ТС]     Количество вхождений слова в файл #20
А вот так почему-то не хочет переводить в нижний регистр строку
В файле ввел слово с заглавной буквы, по идее функция должна была преобразовать все заглавные буквы в строчные(если я правильно понял саму функцию) и вывести на экран слово, в котором заглавные буквы не встречаются, но почему-то этого не произошло, может я где накосячил?

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
#include <iostream>
#include <cstring>
#include <fstream>
 
using namespace std;
 
char* strtolower(const char* str)
{
        char* res=new char(strlen(str)+1);
        strcpy(res, str);
        for(size_t i=0; i<strlen(res); ++i)
                res[i]=tolower(res[i]);
        return res;
}
 
int main()
{   
    const int len = 80;
    char word[len];
    char line[len];
    
    ifstream fin ("text.txt");
    fin.getline(line, len);
    strtolower(line);
    cout << line;
    return 0;
}
Yandex
Объявления
27.02.2011, 18:36     Количество вхождений слова в файл
Ответ Создать тему
Опции темы

Текущее время: 18:45. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru