Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 24, средняя оценка - 4.71
lesorub_
2 / 2 / 0
Регистрация: 20.02.2011
Сообщений: 51
#1

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

21.02.2011, 19:07. Просмотров 4263. Ответов 23
Метки нет (Все метки)

Здравствуйте, уважаемые программисты! Нужна Ваша помощь, какая именно, речь пойдет далее

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

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

Вот код:
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?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.02.2011, 19:07
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Количество вхождений слова в файл (C++):

Подсчитать количество вхождений слова «мама» в строку и вывести номера первых позиций этих вхождений - C++
Помогите исправить ошибку. Как вывести номера первых позиций вхождений слова мама? Подсчитать количество вхождений слова «мама» в строку...

Определить количество вхождений каждого слова - C++
Проанализировать текстовый файл и посчитать, сколько раз в него входит каждое слово. Большие и маленькие буквы рассматриваем как одну и ту...

Найти в тексте количество вхождений определенного слова - C++
Ребята, приветствую! Мне необходимо загрузить из файла текст (перемешанный, т.е. и буквы, и цифры, и знаки препинания, и табуляции есть)....

Подсчитать количество вхождений введенного с клавиатуры слова в строку - C++
собственно, сабж...помогите с задачкой, пожалуйста

Строки. Определить количество вхождений заданного слова в текст - C++
Дано текст и некоторое слово А. Определить количество вхождений заданного слова в текст.

Определить количество вхождений каждого слова в заданную строку - C++
заданная строка. определить количество вхождения каждого слова в заданую строку. помогите,а то не могу понять почему не правельно...

23
lesorub_
2 / 2 / 0
Регистрация: 20.02.2011
Сообщений: 51
27.02.2011, 12:46  [ТС] #16
Цитата Сообщение от Mr.X Посмотреть сообщение
Она нестандартная.
Это значит, что функция не имеет прототипа в заголовочном файле? Но ведь использовать её можно?
0
Kastaneda
Jesus loves me
Эксперт С++
4697 / 2901 / 238
Регистрация: 12.12.2009
Сообщений: 7,385
Записей в блоге: 2
Завершенные тесты: 1
27.02.2011, 12:54 #17
Это значит, что не каждый компилятор ее поддреживает.
0
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 метки, одну на сам цикл, другую на начало тела цикла, чтобы при первом запуске программы игнорировалась проверка его условия.

А вот написать функцию для сравнения массивов строк что-то не получается
0
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 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;
}
1
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;
}
0
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
27.02.2011, 18:47 #21
lesorub_, Файл точно верно открылся?
А. Нужно создать новую строку. Указатель передается константный, посему сама строка не меняется.
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
#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;
        char line[len];
    
        ifstream fin ("text.txt");
        fin.getline(line, len);
        word=strtolower(line);
    cout << word;
    delete word;
        return 0;
}
Кстати мой косяк с функцией. Скобочки как-то перепутал оО
1
lesorub_
2 / 2 / 0
Регистрация: 20.02.2011
Сообщений: 51
27.02.2011, 19:31  [ТС] #22
Отлично, там всё переводит как надо Спасибо Вам большое, что помогаете, я недавно купил книжку Джесс Либерти и Бредли Джонс "Освой язык C++ самостоятельно за 21 день". Но к сожалению подробно о строках там говорится очень мало, а до написания собственных функций пока ещё не дошел.

Позвольте уделить мне ещё немного времени(знаю, что надоел). Вот финальная прога, где я хочу реализовать нормальный поиск в файле. Всё ищет, но чувствительна к регистру. Поэтому я спрашивал, как решить эту проблему. Но в итоге при модифицировании программы функцией преобразования строки в нижний регистр, программа вообще не хочет ничего искать. Посмотрите, пожалуйста, что здесь не так, а то 2-й день сижу, мучаюсь, никак не получить желаемый результат.

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
#include "stdafx.h"
 
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];
        char *modline;
        
        setlocale(LC_ALL, "Russian");
        
 
        while(1)
        {  
        cout << "Введите слово для поиска: ";
        if(gets(word)==NULL) goto q;
        
        int l_word = strlen(word);
        ifstream fin ("text.txt");
        if (!fin) 
           {
              cout << "Ошибка открытия файла." << endl;
              return 1;
           }
 
        int count = 0;
        
            while (fin.getline(line, len)) // заносим строку длинной len в переменную line
            {    
                modline=strtolower(line); //превращаем все прописные буквы в строчные
                char *p = modline; // р - для хранения позиции за найденной подстрокой
            while(p=strstr(p, word)) // многократно ищем вхождение подстроки в строку
            {                
                  char *c=p; //c - для хранения адреса начала вхождения подстроки
                  p+=l_word; // перемещаем указатель на длину заданного слова
                        
                   if(c!=modline) // слово не в начале строки?
                      if (!ispunct(*(c-1)) && !isspace(*(c-1))) // символ перед словом не разделитель?
                         continue;
                      if (ispunct(*p) || isspace(*p) || (*p == '\0')) // символ после слова разделитель?
                         count++;
                }
             }
        cout << endl << "Слово " << word << " встретилось в файле " << count << " раз(а). Выход <Ctrl+Z>" << endl << endl; 
     
        }
        q:;
    return 0;
}
В эту версию я добавил переменную modline для хранения модифицированной строки, т.е. строки нижнего регистра.

Такое чувство, что пять наврал с указателями...
0
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
27.02.2011, 19:48 #23
Проверил - работает.

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
#include <cstring>
#include <iostream>
#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 = 255;
        char word[len]; 
        char line[len];
        char *modline;
        char* modword;
                setlocale(LC_ALL, "Russian");
                
 
                while(1)
            {  
            cout << "Введите слово для поиска: ";
                if(gets(word)==NULL) goto q;
                
                int l_word = strlen(word);
                modword=strtolower(word);
        ifstream fin ("text.txt");
        if (!fin) 
           {
              cout << "Ошибка открытия файла." << endl;
              return 1;
           }
 
        int count = 0;
        
                        while (!fin.eof()) // заносим строку длинной len в переменную line
                        {    
                            fin.getline(line, len);
                            if(!strcmp(line, ""))
                                break;
                            modline=strtolower(line); //превращаем все прописные буквы в строчные
                                char *p = modline; // р - для хранения позиции за найденной подстрокой
            while(p=strstr(p, modword)) // многократно ищем вхождение подстроки в строку
                        {                
                  char *c=p; //c - для хранения адреса начала вхождения подстроки
                  p+=l_word; // перемещаем указатель на длину заданного слова
                        
                   if(c!=modline) // слово не в начале строки?
                      if (!ispunct(*(c-1)) && !isspace(*(c-1))) // символ перед словом не разделитель?
                         continue;
                      if (ispunct(*p) || isspace(*p) || (*p == '\0')) // символ после слова разделитель?
                         count++;
                }
                         }
        cout << endl << "Слово " << word << " встретилось в файле " << count << " раз(а). Выход <Ctrl+Z>" << endl << endl; 
     
                }
                q:;
        return 0;
}
1
lesorub_
2 / 2 / 0
Регистрация: 20.02.2011
Сообщений: 51
27.02.2011, 20:03  [ТС] #24
Всё замечательно, только одна проблема - когда в текстовом файле слово вводится с новой строки, то программа его не видит О_о

Всё, проблема решена, просто удалил строчки.
C++
1
2
if(!strcmp(line, ""))
                    break;
Ещё раз ОГРОМНОЕ спасибо FoReVeRy за помощь! Удачи и успехов Вам!
0
27.02.2011, 20:03
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.02.2011, 20:03
Привет! Вот еще темы с ответами:

Распечатать количество вхождений заданного слова в каждую строку и заменить его на другое заданное слово - C++
Даны две строки, содержащие не более 100 символов. Строки состоят из слов, разделенных пробелами. Распечатать количество вхождений...

Считать текст из файла, добавить в конце каждого предложения, количество вхождений в него заданного слова - C++
Вот задание: Написать программу, которая считывает текст из файла и выводит его на экран, добавляя после каждого предложения, сколько раз...

Посчитать количество всех букв и количество вхождений каждой буквы - C++
Есть файл из нескольких строк. нужно: 1 посчитать количество всех букв 2 посчитать количество каждой из букв (abcd) Проблема:...

Записать в файл заданное количество строк из слова и его номера по порядку - C++
Здравствуйте.Помогите написать программу.Вот принцип работы программы: 1)Вводиться слово к примеру star 2)Вводиться число к примеру 4 ...


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

Или воспользуйтесь поиском по форуму:
24
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.