Чтение онлайн

на главную - закладки

Жанры

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

Для примера 4.26 я предположил, что слово это неразрывная последовательность буквенно-цифровых символов. В процессе просмотра каждого символа входного потока при обнаружении неалфавитно-цифрового символа я проверяю предыдущий символ — был ли он буквенно-цифровым или нет. Если был то это конец слова, и я увеличиваю счетчик слов. Определить, является ли символ буквенно-цифровым, можно с помощью функции

isalnum
из
<cctype>
. Но это еще не все — с помощью аналогичных функций можно проверять символы на целый ряд других качеств. Функции, которые предназначены для проверки характеристик символов, приведены в табл. 4.3. Для широких символов используйте функции с такими же именами, но с буквой «w» после «is», например
iswSpace
.
Версии для широких символов объявлены в заголовочном файле
<cwctype>
.

Табл. 4.3. Функции для проверки символов из <cctype> и <cwctype>

Функция Описание
isalpha iswalpha
Буквенные символы: a-z, A-Z (верхний или нижний регистр)
isupper iswupper
Буквенные символы верхнего регистра: A-Z
islower iswlower
Буквенные символы нижнего регистра: a-z
isdigit iswdigit
Числовые символы: 0-9
isxdigit iswxdigit
Шестнадцатеричные числовые символы: 0-9, a-f, A-F
isspace iswspace
Пробельные символы. ' ', \n, \t, \v, \r, \l
iscntrl iswcntrl
Управляющие символы: ASCII 0-31 и 127
ispunct iswpunct
Символы пунктуации, не принадлежащие предыдущим группам
isalnum iswalnum
isalpha
или
isdigit
равны true
isprint iswprint
Печатаемые символы ASCII
isgraph iswgraph
isalpha
,
isdigit
или
ispunct
равны true

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

Методика использования потоков в примере 4.26 почти идентична той, которая описана в рецептах 4.14 и 4.15, но несколько проще, так как он только исследует файл, не внося никаких изменений.

Смотри также

Рецепты 4.14 и 4.15.

4.18. Подсчет вхождений каждого слова в текстовом файле

Проблема

Требуется подсчитать количество вхождений в текстовом файле каждого слова.

Решение

Для чтения из текстового файла непрерывных фрагментов текста используйте

operator>>
, определенный в
<string>
, а для сохранения каждого слова и его частоты в файле используйте
map
,
определенный в
<map>
. Пример 4.27 демонстрирует, как это делается.

Пример 4.27. Подсчет частоты слов

1 #include <iostream>

2 #include <fstream>

3 #include <map>

4 #include <string>

5

6 typedef std::map<std::string, int> StrIntMap;

7

8 void countWords(std::istream& in, StrIntMap& words) {

9

10 std::string s;

11

12 while (in >> s) {

13 ++words[s];

14 }

15 }

16

17 int main(int argc, char** argv) {

18

19 if (argc < 2)

20 return(EXIT_FAILURE);

21

22 std::ifstream in(argv[1]);

23

24 if (!in)

25 exit(EXIT_FAILURE);

26

27 StrIntMap w;

28 countWords(in, w);

29

30 for (StrIntMap::iterator p = w.begin;

31 p != w.end; ++p) {

32 std::cout << p->first << " присутствует "

33 << p->second << " раз.\n";

34 }

35 }

Обсуждение

Пример 4.27 кажется вполне простым, но в нем делается больше, чем кажется. Большая часть тонкостей связана с

map
, так что вначале давайте обсудим его.

Если вы не знакомы с

map
, то вам стоит узнать про него,
map
 — это шаблон класса контейнера, который является частью STL. Он хранит пары ключ-значение в порядке, определяемом
std::less
или вашей собственной функцией сравнения. Типы ключей и значений, которые можно хранить в нем, зависят только от вашего воображения. В этом примере мы просто сохраняем
string
и
int
.

В строке 6 я для упрощения читаемости кода использовал

typedef
.

typedef map<string, int> StrIntMap;

Таким образом,

StrIntMap
— это
map
, который хранит пары string/int. Каждая
string
— это уникальное слово именно по этой причине я использую ее как ключ, — которое было прочитано из входного потока, а связанное с ней
int
— это число раз, которое это слово встретилось. Все, что осталось, — это прочитать все слова по одному, добавить их в map, если их там еще нет, и увеличить значение счетчика, если они там уже есть.

Это делает

countWords
. Основная логика кратка.

while (in >> s) {

 ++words[s];

}

operator>>
читает из левого операнда (
istream
) непрерывные отрезки, не содержащие пробелов, и помещает их в правый операнд (
string
). После прочтения слова все, что требуется сделать, — это обновить статистику в
map
, и это делается в следующей строке.

++words[s];

Поделиться:
Популярные книги

Неучтенный. Дилогия

Муравьёв Константин Николаевич
Неучтенный
Фантастика:
боевая фантастика
попаданцы
7.98
рейтинг книги
Неучтенный. Дилогия

Попаданка

Ахминеева Нина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Попаданка

Я еще не барон

Дрейк Сириус
1. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я еще не барон

Жена проклятого некроманта

Рахманова Диана
Фантастика:
фэнтези
6.60
рейтинг книги
Жена проклятого некроманта

Камень. Книга шестая

Минин Станислав
6. Камень
Фантастика:
боевая фантастика
7.64
рейтинг книги
Камень. Книга шестая

Барон нарушает правила

Ренгач Евгений
3. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон нарушает правила

Комбинация

Ланцов Михаил Алексеевич
2. Сын Петра
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Комбинация

Испытание Огня

Гаврилова Анна Сергеевна
3. Академия Стихий
Фантастика:
фэнтези
9.43
рейтинг книги
Испытание Огня

Идеальный мир для Лекаря 25

Сапфир Олег
25. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 25

Ведьмак. Перекресток воронов

Сапковский Анджей
Фантастика:
фэнтези
5.00
рейтинг книги
Ведьмак. Перекресток воронов

Сердце Дракона. Том 20. Часть 1

Клеванский Кирилл Сергеевич
20. Сердце дракона
Фантастика:
фэнтези
боевая фантастика
городское фэнтези
5.00
рейтинг книги
Сердце Дракона. Том 20. Часть 1

Вечная Война. Книга II

Винокуров Юрий
2. Вечная война.
Фантастика:
юмористическая фантастика
космическая фантастика
8.37
рейтинг книги
Вечная Война. Книга II

Клан

Русич Антон
2. Долгий путь домой
Фантастика:
боевая фантастика
космическая фантастика
5.60
рейтинг книги
Клан

Герцог и я

Куин Джулия
1. Бриджертоны
Любовные романы:
исторические любовные романы
8.92
рейтинг книги
Герцог и я