Табличный метод
Табличный метод — это схема, позволяющая искать информацию в таблице, а не использовать для этого логические выражения, такие как if
и case
. Практически все, что вы можете выбирать посредством логических операторов, можно выбирать, применяя таблицы. В простых случаях логические выражения проще и понятней. Но при усложнении логических построений таблицы становятся все привлекательнее.
Рассмотрим пример определения количества дней в месяце. Допустим, вы хотите получить число дней в месяце (для простоты забудем о високосных годах). Разумеется, создание большого условия if
— неуклюжий способ решения этой проблемы:
if (month == 1) days = 31; else if (month == 2) days = 28; else if (month == 3) days = 31; else if (month == 4) days = 30; else if (month == 5) days = 31; else if (month == 6) days = 30; else if (month == 7) days = 31; else if (month == 8) days = 31; else if (month == 9) days = 30; else if (month == 10) days = 31; else if (month == 11) days = 30; else if (month == 12) days = 31;
Более простой и удобный для модификации способ выполнения тех же самых действий — разместить данные в таблице (в данном случае одномерном массиве):
int daysPerMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; days = daysPerMonth[month-1];
Определение количества дней в месяце — удобный пример, так как переменную
month можно использовать для поиска записи в таблице.
Рассмотрим другой пример со ставками медицинского страхования, которые варьируются в зависимости от возраста, пола, семейного положения и от того, курит ли страхователь. Если бы вы писали для этих ставок логическую управляющую структуру, то получилось бы нечто вроде этого:
if ( gender == Gender.Female ) { if ( maritalStatus == MaritalStatus.Single ) { if ( smokingStatus == SmokingStatus.NonSmoking ) { if ( age < 18 ) { rate = 200.00; } else if ( age == 18 ) { rate = 250.00; } else if ( age == 19 ) { rate = 300.00; } ... else if ( 65 < age ) { rate = 450.00; } else { if ( age < 18 ) { rate = 250.00; } else if ( age == 18 ) { rate = 300.00; } else if ( age == 19 ) { rate = 350.00; } ... else if ( 65 < age ) { rate = 575.00; } } else if ( maritalStatus == MaritalStatus.Married ) ... }
Эта сокращенная версия логической структуры — хорошая иллюстрация того, насколько сложной может получиться программа. Она не учитывает замужних женщин, всех мужчин и большинства возрастов между 18 и 65 годами. Вы можете вообразить, насколько сложной станет эта структура, если запрограммировать всю таблицу ставок.
Вы можете сказать: «Да, но почему вы проверяете каждый возраст? Почему бы не поместить ставку для каждого возраста в массив?» Хороший вопрос, и одним из очевидных усовершенствований будет размещение ставок для каждого возраста в отдельных массивах.
Однако лучшее решение — создать массив ставок не только для каждого возраста, но вообще для всех факторов.
enum SmokingStatus{ Smoking, NonSmoking }; enum Gender{ Male, Female }; enum MaritalStatus{ Single, Married }; const int max_age = 100; int main() { double rateTable[2][2][2][max_age]; // заполнение массива rateTeable double rate = rateTable[Smoking][Male][Married][43]; }
Сложная логическая структура, показанная ранее, заменяется простым выражением. Основное преимущество этого подхода — в замене сложной логики табличным поиском. Такой код удобней читать и проще изменять.
При применении табличных методов перед вами стоят два основных вопроса. Во-первых, вам надо решить, как будет выполняться поиск записей в таблице. Вы можете использовать какие-либо данные для прямого доступа к таблице. Так, если вам нужно систематизировать данные по месяцам, то выбор ключа для таблицы месяцев очевиден. Вы можете использовать массив с индексом от 1 до 12.
Другие данные затруднительно использовать для прямого поиска табличной записи. Так, для классификации информации по серии и номеру паспорта вы не сможете использовать этот номер в качестве ключа непосредственно, если, конечно, вы не собираетесь хранить в таблице огромное количество записей. Вам понадобится более сложный подход. Вот какие способы, применяются для поиска записи в таблице:
- прямой доступ;
- индексированный доступ;
- ступенчатый доступ.
Второй вопрос, который нужно решить при использовании табличных
методов: что хранить в таблице. Иногда результатом поиска в таблице
являются данные — тогда можно хранить в таблице сами данные. Если
же результатом поиска является действие, можно хранить ссылку на метод, выполняющий это действие. В каждом из этих случаев таблицы усложняются.