Литмир - Электронная Библиотека
A
A

6. Напишите программу, обнаруживающую даты в текстовом файле. Выведите на печать каждую строку, содержащую хотя бы одну дату в формате

linenumber:line
. Начните с регулярного выражения для простого формата, например 12/24/2000, и протестируйте ее на нем. Затем добавьте новые форматы.

7. Напишите программу (аналогичную предыдущей), которая находит номера кредитных карточек в файле. Разберитесь в том, какие форматы на самом деле используются для записи номеров кредитных карточек, и реализуйте их проверку в вашей программе.

8. Модифицируйте программу из раздела 23.8.7 так, чтобы на ее вход поступали шаблон и имя файла. Результатом работы программы должны быть пронумерованные строки (

line–number:line
), соответствующие шаблону. Если соответствия не выявлены, ничего выводить не надо.

9. Используя функцию

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

10. Модифицируйте программу для проверки таблицы из раздела 23.9 так, чтобы она выводила новую таблицу, в которой строки, имеющие одинаковые первые цифры (означающие год: первому классу соответствует число 1), были объединены.

11. Модифицируйте программу для проверки таблицы из раздела 23.9 так, чтобы проверить, возрастает или убывает количество учеников с годами.

12. Напишите программу, основываясь на программе, выявляющей строки, содержащие даты (упр. 6), найдите все даты и переведите их в формат ISO год/месяц/день. Эта программа должна считывать информацию из входного файла и выводить ее в выходной файл, идентичный входному, за одним исключением: даты в нем записаны в другом формате.

13. Соответствует ли точка (

.
) шаблону
'\n'
? Напишите программу, которая отвечает на этот вопрос.

14. Напишите программу, которую, подобно программе из раздела 23.8.7, можно использовать для экспериментирования с сопоставлением шаблонов с помощью их ввода извне. Однако теперь программа должна считывать данные из файла и записывать их в память (разделение на строки производится с помощью символа перехода на новую строку

'\n'
), чтобы можно было экспериментировать с шаблонами, содержащими разрывы строк. Протестируйте программу на нескольких десятках шаблонов.

15. Опишите шаблон, который нельзя представить с помощью регулярного выражения.

16. Только для экспертов: докажите, что шаблон из предыдущего упражнения действительно не является регулярным выражением.

Послесловие

Легко впасть в заблуждение, считая, что компьютеры и вычисления относятся только к числам, что вычисления являются частью математики. Очевидно, это не так. Просто посмотрите на экран компьютера; он заполнен текстом и пикселями. Может быть, ваш компьютер еще и воспроизводит музыку. Для каждого приложения важно выбрать правильный инструмент. В контексте языка С++ это значит правильно выбрать подходящую библиотеку. Для манипуляций текстом основным инструментом часто является библиотека регулярных выражений. Кроме того, не следует забывать об ассоциативных контейнерах map и стандартных алгоритмах.

Глава 24

Числа

“Любая сложная проблема имеет ясное, простое

и при этом неправильное решение”.

Г.Л. Менкен (H.L. Mencken)

Эта глава представляет собой обзор основных инструментов для численных расчетов, предоставляемых языком и его библиотекой. Мы рассмотрим фундаментальные проблемы, связанные с размером, точностью и округлением. В центре внимания этой главы — многомерные массивы в стиле языка С и библиотека N-мерных матриц. Мы также опишем генерирование случайных чисел, которые часто необходимы для тестирования и моделирования, а также для программирования игр. В заключение будут упомянуты стандартные математические функции и кратко изложены основные функциональные возможности библиотеки, предназначенные для работы с комплексными числами.

24.1. Введение

 

Программирование. Принципы и практика использования C++ Исправленное издание - _001.png
 Для некоторых людей, скажем, многих ученых, инженеров и статистиков, серьезные числовые расчеты являются основным занятием. В работе многих людей числовые расчеты играют значительную роль. К этой категории относятся специалисты по компьютерным наукам, иногда работающие с физиками. У большинства людей необходимость в числовых расчетах, выходящая за рамки простых арифметических действий над целыми числами и числами с десятичной точкой, возникает редко. Цель этой главы — описать языковые возможности, необходимые для решения простых вычислительных задач. Мы не пытаемся учить читателей численному анализу или тонкостям операций над числами с десятичной точкой; эти темы выходят за рамки рассмотрения нашей книги и тесно связаны с конкретными приложениями. Здесь мы собираемся рассмотреть следующие темы.

• Вопросы, связанные с встроенными типами, имеющими фиксированный размер, например точность и переполнение.

• Массивы, как в стиле языка С, так и класс из библиотека

Matrix
, который лучше подходит для числовых расчетов.

• Введение в случайные числа.

• Стандартные математические функции из библиотеки.

• Комплексные числа.

Основное внимание уделено многомерным массивам в стиле языка С и библиотеке N-мерных матриц

Matrix
, которая позволяет упростить работу с матрицами (многомерными массивами).

24.2. Размер, точность и переполнение

 

Программирование. Принципы и практика использования C++ Исправленное издание - _001.png
 Когда вы используете встроенные типы и обычные методы вычислений, числа хранятся в областях памяти фиксированного размера; иначе говоря, целочисленные типы (
int
,
long
и др.) представляют собой лишь приближение целых чисел, а числа с плавающей точкой (
float
,
double
и др.) являются лишь приближением действительных чисел. Отсюда следует, что с математической точки зрения некоторые вычисления являются неточными или неправильными. Рассмотрим пример.

float x = 1.0/333;

float sum = 0;

for (int i=0; i<333; ++i) sum+=x;

cout << setprecision(15) << sum << "\n";

Выполнив эту программы, мы получим не единицу, а

0.999999463558197

Мы ожидали чего-то подобного. Число с плавающей точкой состоит только из фиксированного количества битов, поэтому мы всегда можем “испортить” его, выполнив вычисление, результат которого состоит из большего количества битов, чем допускает аппаратное обеспечение. Например, рациональное число 1/3 невозможно представить точно как десятичное число (однако можно использовать много цифр его десятичного разложения). Точно так же невозможно точно представить число 1/333, поэтому, когда мы складываем 333 копии числа

x
(наилучшее машинное приближение числа 1/333 с помощью типа
float
), то получим число, немного отличающееся от единицы. При интенсивном использовании чисел с плавающей точкой возникает ошибка округления; остается лишь оценить, насколько сильно она влияет на результат.

330
{"b":"847443","o":1}