Завдання 9 Дедлайн 4 грудня (#ifndef’s з побітовими операціями)

Макроси мають кілька поширених застосувань:

  •  Замість констант, якщо потрібно мати можливість задавати їх значення на етапі компіляції не змінюючи код.
  •  Генерація однотипного коду, здебільшого у тестуванні.
  •  Відключення певних ділянок коду: при розділенні етапів розробки та релізу, або в мульти-платформних застосунках.

Останній варіант застосування зустрічається практично в кожному великому проєкті.
Для ознайомлення з ним, напишіть програму, яка зчитує два числа, і виводить їх частку.
Поведінку програми можна конфігурувати через макрос FLAGS — ціле число, окремі біти якого відповідають за певний аспект функціоналу:
 * Біт 0, FLAG_CHECK — чи перевіряти ділення на 0.
 * Біт 1, FLAG_DOUBLE — використовувати double чи int для обчислень.
 * Біт 2, FLAG_VERBOSE — чи виводити повідомлення для користувача.

Приклади роботи

  • FLAG_CHECK — якщо дільник 0, то програма виводить помилку і завершує роботу:

    4 0
    Divisor is 0.
Якщо FLAG_CHECK не встановлений, то програма має просто виконати ділення, поведінка не визначена. Наприклад для компілятора GCC (g++) на Linux:

4 0

    Floating point exception (core dumped)

  • FLAG_DOUBLE

Якщо встановлений, то використовувати double для обчислень:

3 2
1.5

Якщо ні — int:

3 2
1
  • FLAG_VERBOSE — якщо встановлений, то виводити повідомлення для користувача перед зчитуванням операндів і повний вираз при виведенні результату:

    Enter the operands for division: 6 2

6 / 2 = 3

Поведінку без нього можна бачити в попередніх прикладах.

Підказки

  • Біт n варто визначити як макрос з відповідним ім’ям наступним чином:
#define FLAG_X (1 << n)

Наприклад:

#define FLAG_VERBOSE (1 << 2)
  • Для перевірки, чи біт встановлений, використовуйте оператор & та директиву if:
#if FLAGS & FLAG_DOUBLE
// Код, якщо біт встановлено.
#else
// Код, якщо біт не встановлено.
#endif
  • З метою тестування, змінну FLAGS можна визначити в коді. Наприклад, у першому ж рядку. Наступне визначення ввімкне всі три аспекти функціоналу одночасно:
#define FLAGS 7

Еквівалентне і більш правильне:

#define FLAGS (FLAG_CHECK | FLAG_DOUBLE | FLAG_VERBOSE)

Зауважте, що це можна робити навіть до оголошення макросів FLAG_X, бо макроси не розгортаються на моменті оголошення.

Відповідь

#include <iostream>
// Якщо FLAGS не визначений через опції компілятора, то задаємо йому значення
// за замовчуванням 0 - вимкнути все.
#ifndef FLAGS
#define FLAGS 0
#endif
// Для покращення якості коду, створюємо окремий макрос для кожного біта.
#define FLAG_CHECK   (1 << 0) // Біт 0 - Перевірка ділення на 0.
#define FLAG_DOUBLE  (1 << 1) // Біт 1 - Використовувати double.
#define FLAG_VERBOSE (1 << 2) // Біт 2 - Виводити повідомлення.
// Визначаємо макрос "calc_t" в залежності від FLAG_DOUBLE.
// На відміну від інших макросів, "calc_t" записаний малими літерами, щоб
// візуально бути схожим на стандартні імена типів.
#if FLAGS & FLAG_DOUBLE
#define calc_t double
#else
#define calc_t int
#endif

int main() {
   // Оголошуємо змінні для операндів і результату.
   calc_t a;
   calc_t b;
   calc_t result;
   // Зчитуємо операнди. Виводимо запит, якщо встановлено біт FLAG_VERBOSE.
#if FLAGS & FLAG_VERBOSE
   std::cout << "Enter the operands for division: ";
#endif
   std::cin >> a >> b;
   // Виконуємо ділення. Перевіряємо на 0, якщо встановлено біт FLAG_CHECK.
#if FLAGS & FLAG_CHECK
   if (!b) {
       std::cout << "Divisor is 0." << std::endl;
       return 0;
   }
#endif
   result = a / b;
   // Виводимо результат. Виводимо вираз, якщо встановлено біт FLAG_VERBOSE.
#if FLAGS & FLAG_VERBOSE
   std::cout << a << " / " << b << " = ";
#endif
   std::cout << result << std::endl;
   return 0;
}

Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Максимальный размер загружаемого файла: 1 ГБ. Вы можете загрузить: изображение, аудио, видео, документ, таблица, интерактив, текст, архив, код, другое. Ссылки на YouTube, Facebook, Twitter и другие сервисы, вставленные в текст комментария, будут автоматически встроены. Перетащите файл сюда