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

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

Жанры

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];

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

Лолита

Набоков Владимир Владимирович
Проза:
классическая проза
современная проза
8.05
рейтинг книги
Лолита

Я подарю тебе ребёнка

Малиновская Маша
Любовные романы:
современные любовные романы
6.25
рейтинг книги
Я подарю тебе ребёнка

Убивать чтобы жить 3

Бор Жорж
3. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 3

Небо для Беса

Рам Янка
3. Самбисты
Любовные романы:
современные любовные романы
5.25
рейтинг книги
Небо для Беса

Сердце Дракона. Том 11

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

Печать мастера

Лисина Александра
6. Гибрид
Фантастика:
попаданцы
технофэнтези
аниме
фэнтези
6.00
рейтинг книги
Печать мастера

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

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

Калибр Личности 1

Голд Джон
1. Калибр Личности
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Калибр Личности 1

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

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

Волчья воля, или Выбор наследника короны

Шёпот Светлана
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Волчья воля, или Выбор наследника короны

Вечный. Книга I

Рокотов Алексей
1. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга I

Спасение 6-го

Уолш Хлоя
3. Парни из школы Томмен
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Спасение 6-го

Ротмистр Гордеев

Дашко Дмитрий Николаевич
1. Ротмистр Гордеев
Фантастика:
фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Ротмистр Гордеев

Нечто чудесное

Макнот Джудит
2. Романтическая серия
Любовные романы:
исторические любовные романы
9.43
рейтинг книги
Нечто чудесное