Д. Стефенс - C++. Сборник рецептов
- Название:C++. Сборник рецептов
- Автор:
- Жанр:
- Издательство:КУДИЦ-ПРЕСС
- Год:2007
- Город:Москва
- ISBN:5-91136-030-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Д. Стефенс - C++. Сборник рецептов краткое содержание
Данная книга написана экспертами по C++ и содержит готовые рецепты решения каждодневных задач для программистов на С++. Один из авторов является создателем библиотеки Boost Iostreams и нескольких других библиотек C++ с открытым исходным кодом. В книге затрагивается множество тем, вот лишь некоторые из них: работа с датой и временем; потоковый ввод/вывод; обработка исключений; работа с классами и объектами; сборка приложений; синтаксический анализ XML-документов; программирование математических задач. Читатель сможет использовать готовые решения, а сэкономленное время и усилия направить на решение конкретных задач.
C++. Сборник рецептов - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Табл. 4.3. Функции для проверки символов из и
Функция | Описание |
---|---|
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>>
, определенный в , а для сохранения каждого слова и его частоты в файле используйте map
, определенный в . Пример 4.27 демонстрирует, как это делается.
Пример 4.27. Подсчет частоты слов
1 #include
2 #include
3 #include
4 #include
5
6 typedef std::map 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 StrIntMap;
Таким образом, StrIntMap
— это map
, который хранит пары string/int. Каждая string
— это уникальное слово именно по этой причине я использую ее как ключ, — которое было прочитано из входного потока, а связанное с ней int
— это число раз, которое это слово встретилось. Все, что осталось, — это прочитать все слова по одному, добавить их в map, если их там еще нет, и увеличить значение счетчика, если они там уже есть.
Это делает countWords
. Основная логика кратка.
while (in >> s) {
++words[s];
}
operator>>
читает из левого операнда ( istream
) непрерывные отрезки, не содержащие пробелов, и помещает их в правый операнд ( string
). После прочтения слова все, что требуется сделать, — это обновить статистику в map
, и это делается в следующей строке.
++words[s];
map
определяет operator[]
, позволяющий получить значение данного ключа (на самом деле он возвращает ссылку на само значение), так что для его инкремента просто инкрементируется значение, индексируемое с помощью заданного ключа. Но здесь могут возникнуть небольшие осложнения. Что, если ключа в map еще нет? Разве мы не попытаемся увеличить несуществующий элемент, и не обрушится ли программа, как в случае с обычным массивом? Нет, map
определяет operator[]
не так, как другие контейнеры STL или обычные массивы.
В map operator[]
делает две вещи: если ключ еще не существует, он создает значение, используя конструктор типа значения по умолчанию, и добавляет в map
эту новую пару ключ/значение, а если ключ уже существует, то никаких изменений не вносится. В обоих случаях возвращается ссылка на значение, определяемое ключом, даже если это значение было только что создано конструктором по умолчанию. Это удобная возможность (если вы знаете о ее существовании), так как он устраняет необходимость проверки в клиентском коде существования ключа перед его добавлением.
Теперь посмотрите на строки 32 и 33. Итератор указывает на члены, которые называются first
и second
— что это такое? map
обманывает вас, используя для хранения пар имя/значение другой шаблон класса: шаблон класса pair
, определенный в (уже включенный в ). При переборе элементов, хранящихся в
map
, вы получите ссылки на объекты pair
. Работа с pair
проста. Первый элемент пары хранится в элементе first
, а второй хранится, естественно, в second
.
В примере 4.27 я для чтения из входного потока непрерывных фрагментов текста использую operator>>
, что отличается от некоторых других примеров. Я делаю это для демонстрации того, как это делается, но вам почти наверняка потребуется изменить его поведение в зависимости от определения «слова» текстового файла. Например, рассмотрим фрагмент вывода, генерируемого примером 4.27.
with присутствует 5 раз.
work присутствует 3 раз.
workers присутствует 3 раз.
workers, присутствует 1 раз.
Интервал:
Закладка: