Загадочные числа
Загадочные числа — это константы, размеры массивов, позиции символов и другие
числовые значения, появляющиеся в программе непосредственно, как "буквальные
константы".
Давайте имена загадочным числам. В принципе нужно считать, что любое
встречающееся в программе число, отличное от 0 и 1, является загадочным и
должно получить собственное имя. Просто "сырые" числа в тексте программы не
дают
представления об их происхождении и назначении, затрудняя понимание и
изменение программы. Вот отрывок из программы, которая печатает гистограмму
частот букв на терминале с разрешением 24 X 80. Этот отрывок неоправданно
запутан из-за целого сонма непонятных чисел:
fac = lim / 20; /* установка масштаба */
if (fac < 1)
fac = 1;
/* генерация гистограммы */ for (i = 0, col = 0; i < 27; i++, j++)
{
col += 3;
k = 21 - (let[i] / fac);
star = (let[i] == 0) ? ' ' : '*';
for (j = k; j < 22; j++)
draw(j, col, star); } draw(23, 2, ' '); /* разметка оси х */
Наряду с другими в
коде присутствуют числа 20, 21, 22, 23 и 27. Они как-то тесно
связаны... или нет? На самом деле есть только три критических числа, существенных
для программы: 24 — число строк экрана; 80 — число столбцов экрана и, наконец, 26
— количество букв в английском алфавите. Однако, как мы видим, ни одно из этих
чиеел в коде не встречается, отчего числа,
используемые в коде, становятся еще
более загадочными.
Присвоив имена числам, имеющим принципиальное значение, мы облегчим
понимание кода. Например, станет понятно, что число 3 берется из
арифметического выражения (80-1)/26, а массив let должен иметь 26 элементов, а не
27 (иначе возможна ошибка его переполнения на единицу — из-за того, что
экранные координаты индексируются, начиная с 1). Сделав
еще пару
усовершенствований, мы придем к следующему результату:
enum {
MINROW =1, /* верхняя граница */
MINCOL =1, /* левая граница */
MAXROW = 24, /* нижняя граница (<=) */
MAXCOL = 80, /* правая граница (<=) */
LABELROW =1, /* позиция подписей оси */
NLET = 26, f /* количество букв алфавита */
HEIGHT = MAXROW - 4, /* высота столбиков */•
WIDTH = (MAXCOL-1)/NLET /* ширина столбиков */
};
fac = (lim + HEIGHT-1) / HEIGHT; /* установка масштаба */
if (fac <
1)
fac = 1; for (i = 0; i < NLET; i++) { /* генерация гистограммы */
if (let[i] == 0) continue;