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

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

Жанры

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.50
рейтинг книги
Хозяйка старой пасеки

Измена. Не прощу

Леманн Анастасия
1. Измены
Любовные романы:
современные любовные романы
4.00
рейтинг книги
Измена. Не прощу

Черный маг императора 2

Герда Александр
2. Черный маг императора
Фантастика:
юмористическая фантастика
попаданцы
аниме
6.00
рейтинг книги
Черный маг императора 2

Разбуди меня

Рам Янка
7. Серьёзные мальчики в форме
Любовные романы:
современные любовные романы
остросюжетные любовные романы
5.00
рейтинг книги
Разбуди меня

Не грози Дубровскому! Том III

Панарин Антон
3. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том III

Семья. Измена. Развод

Высоцкая Мария Николаевна
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Семья. Измена. Развод

Хозяин Теней 4

Петров Максим Николаевич
4. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Хозяин Теней 4

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

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

Потомок бога

Решетов Евгений Валерьевич
1. Локки
Фантастика:
попаданцы
альтернативная история
аниме
сказочная фантастика
5.00
рейтинг книги
Потомок бога

Отмороженный 11.0

Гарцевич Евгений Александрович
11. Отмороженный
Фантастика:
боевая фантастика
рпг
попаданцы
фантастика: прочее
фэнтези
5.00
рейтинг книги
Отмороженный 11.0

Надуй щеки! Том 7

Вишневский Сергей Викторович
7. Чеболь за партой
Фантастика:
попаданцы
дорама
5.00
рейтинг книги
Надуй щеки! Том 7

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

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

Антимаг его величества. Том III

Петров Максим Николаевич
3. Модификант
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Антимаг его величества. Том III

Истребители. Трилогия

Поселягин Владимир Геннадьевич
Фантастика:
альтернативная история
7.30
рейтинг книги
Истребители. Трилогия