Форматирование данных
Каждая функция в таблице разбирает пакет своего типа, проверяет результат и инициирует дальнейшую обработку этого пакета. Благодаря этой таблице работа приемника получается более прямолинейной:
Итак, теперь код для обработки каждого пакета стал компактен; основная часть всей обработки происходит в одной функции и потому поддерживать такой код нетрудно. Код приемника теперь мало зависит от самого протокола; код его также прост и однозначен.
Этот пример основан на некоем реальном коде настоящего коммерческого сетевого протокола. Как только автор осознал, что этот, в общем, не хитрый подход работоспособен, в небытие ушли несколько тысяч строк повторяющегося кода, напичканного ошибками (скорее даже, описками), и вместо него появились несколько сот строк, поддерживать которые можно без всякого напряжения. Итак, хороший способ написания существенным образом улучшил как сам процесс работы, так и ее результат.
Упражнение 9.1
Измените pack и unpack так, чтобы можно было передавать и значения со знаком, причем даже между машинами, имеющими разные размеры short и long. Как вы измените форматную строку для обозначения элемента данных со знаком? Как можно протестировать код, чтобы убедиться, что он корректно передает, например, число -1 с компьютера с 32-битовым long на компьютер с 64-битовым long?
Упражнение 9.2
Добавьте в pack и unpack возможности обработки строк. (Есть вариант включать длину строки в форматную строку.) Добавьте возможность обработки повторяющихся значений с помощью счетчика. Как это соотносится с кодировкой строк?
Упражнение 9.3
Вспомните таблицу указателей на функции, которую мы применили олько что в программе на С. Такой же принцип лежит в основе механизма виртуальных функций C++. Перепишите pack, unpack и receive на C++, чтобы прочувствовать все удобство этого способа.
Упражнение 9.4
Напишите версию printf для командной строки: пусть эта функция печатает свой второй и последующие аргументы в формате, заданном первом аргументе. Надо отметить, что во многих оболочках имеется строенный аналог такой функции.
Упражнение 9.5
Напишите функцию, реализующую спецификации формата, используемого в какой-нибудь программе работы с электронными таблицами или в Java-классе Decimal Format, где числа отображаются в соответствии некоторым заданным шаблоном, указывающим количество обязательных и возможных символов, положение десятичной точки и тысячных, десятых и т. п. Для иллюстрации рассмотрим строку:
##,##0.00
Эта строка задает число с двумя знаками после десятичной точки, э крайней мере одним знаком перед десятичной точкой, запятой в качестве разделителя тысяч и заполняющими пробелами до позиции 10 000. Таким образом, число 12345.67 будет представлено как 12, 345. 67, а.4 – ж **,**0.40 (для наглядности вместо пробелов мы вставили звездочки). Для получения полной спецификации можете обратиться к описанию DecimalFormat или программам работы с электронными таблицами.