/*==============================================================================
  Лабораторна робота №1. Завдання 1. Варіант 19.
  Тема: типи даних, функції введення-виведення, обчислення виразів.

  Умова: за даними, введеними з клавіатури, обчислити значення виразу
         X = (A*cos^2(B) + 1)^(1/2) * ln(C) / D
         та вивести результат на екран.

  Метод: вираз обчислюється безпосередньо за допомогою стандартних
         математичних функцій cos(), sqrt(), log() з <math.h>.
         Перед обчисленням перевіряються обмеження області визначення:
             C > 0            (аргумент натурального логарифма);
             D != 0           (дільник);
             A*cos^2(B) + 1 >= 0  (підкореневий вираз).

  Введення-виведення: форматні функції scanf()/printf() з <stdio.h>
         (демонстрація потокового введення-виведення — у завданні 2).

  Виконав: Одарчук Олексій, КНУ імені Тараса Шевченка, ФІТ, група ІПЗ-11.

  Компілятор: gcc -std=c17
==============================================================================*/

#include <stdio.h>
#include <stdbool.h>
#include <math.h>

/*------------------------------------------------------------------------------
  readDouble — прочитати одне дійсне число з клавіатури з контролем коректності.

  Параметри:
      prompt [вхідний]  — текст запрошення, що виводиться користувачеві;
      value  [вихідний] — адреса змінної, куди буде записано введене число.

  Повертає: true  — число успішно прочитано;
            false — досягнуто кінця вхідного потоку (EOF).

  Локальні змінні:
      c — черговий символ, що зчитується під час очищення буфера клавіатури.
------------------------------------------------------------------------------*/
bool readDouble(const char *prompt, double *value)
{
    for (;;) {
        printf("%s", prompt);

        /* scanf повертає кількість успішно заповнених полів,
           або EOF, якщо вхідний потік вичерпано. */
        int scanned = scanf("%lf", value);

        if (scanned == EOF)
            return false;

        if (scanned == 1)
            return true;

        /* Введено не число: очищаємо буфер клавіатури до кінця рядка,
           інакше scanf нескінченно натикатиметься на ті самі символи. */
        int c;
        while ((c = getchar()) != '\n' && c != EOF) {
            /* пропускаємо залишок хибного рядка */
        }
        printf("Помилка: очікується дійсне число. Спробуйте ще раз.\n");
    }
}

/*------------------------------------------------------------------------------
  Головна функція. Організовує введення вихідних даних, перевірку області
  визначення виразу та виведення результату.

  Локальні змінні:
      a, b, c, d — вихідні дані, введені з клавіатури;
      cosB       — проміжне значення cos(B);
      radicand   — підкореневий вираз A*cos^2(B) + 1;
      x          — шукане значення виразу.
------------------------------------------------------------------------------*/
int main()
{
    double a = 0.0, b = 0.0, c = 0.0, d = 0.0;

    printf("Лабораторна робота №1, завдання 1 (варіант 19)\n");
    printf("Виконав: студент групи ІПЗ-11 Одарчук Олексій\n");
    printf("Обчислення виразу X = sqrt(A*cos^2(B) + 1) * ln(C) / D\n");
    printf("Кут B задається в радіанах, C > 0, D != 0.\n\n");

    if (!readDouble("Уведіть A = ", &a))
        return 1;
    if (!readDouble("Уведіть B (радіани) = ", &b))
        return 1;
    if (!readDouble("Уведіть C = ", &c))
        return 1;
    if (!readDouble("Уведіть D = ", &d))
        return 1;

    printf("\nВихідні дані: A = %.6f  B = %.6f  C = %.6f  D = %.6f\n", a, b, c, d);

    /* Перевірка області визначення виразу. */
    if (c <= 0.0) {
        printf("Вираз не визначено: ln(C) існує лише при C > 0.\n");
        return 2;
    }
    if (d == 0.0) {
        printf("Вираз не визначено: ділення на нуль (D = 0).\n");
        return 2;
    }

    const double cosB = cos(b);
    const double radicand = a * cosB * cosB + 1.0;

    if (radicand < 0.0) {
        printf("Вираз не визначено: підкореневий вираз A*cos^2(B)+1 = %.6f < 0.\n",
               radicand);
        return 2;
    }

    const double x = sqrt(radicand) * log(c) / d;

    /* Проміжні результати виводяться для перевірки достовірності обчислень. */
    printf("\nПроміжні результати:\n");
    printf("  cos(B)            = %.10f\n", cosB);
    printf("  cos^2(B)          = %.10f\n", cosB * cosB);
    printf("  A*cos^2(B) + 1    = %.10f\n", radicand);
    printf("  sqrt(...)         = %.10f\n", sqrt(radicand));
    printf("  ln(C)             = %.10f\n", log(c));

    printf("\nРезультат: X = %.10f\n", x);
    return 0;
}
