Завдання 1  Дедлайн 6 листопада


Програмування на C++ часто пов’язане з C, а відповідно — з поняттями швидкодії і малими одиницями часу. На практиці найменшою одиницею часу є наносекунда — максимально можлива точність виміру в звичайних системах. При низькорівневій розробці також оперують мілісекундами (швидкодія алгоритмів) чи мікросекундами (мітки часу в медіа).

Для ознайомлення з цими величинами і їх типовими позначеннями, необхідно розробити алгоритм, який розбиває мітку часу в наносекундах (timestamp) на:

  • Дні (d — days)
  • Години (h — hours)
  • Хвилини (m — minutes)
  • Секунди (s — seconds)
  • Мілісекунди (ms — milliseconds)
  • Мікросекунди (us — microseconds). Латинська u тут заміняє грецьку μ.
  • Наносекунди (ns — nanoseconds)

Всі величини мають бути виведені на екран зі своїм суфіксом.

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

Enter the timestamp (ns): 88702401174195007
1026d 15h 33m 21s 174ms 195us 7ns

Вхідні дані на скріншоті.

#include <iostream>

// Для зручності - окремі змінні для дільників кожної величини.
// Це щоб не повторювати один і той самий вираз в коді кілька разів.
// Щоб отримати лише мікросекунди (ms) з часу в наносекундах timestamp),
// потрібно відкинути все до мікросекунд (остача від ділення на дільник мікросекунд - d_us),
// а потім відкинути наносекунди (цілочисельне ділення на дільник наносекунд - d_ns):
// us = timestamp % d_us / d_ns; Цей
// підхід зберігається для всіх значень, окрім днів і наносекунд, вони простіші.
unsigned long long d_ns = 1000;         // Дільник наносекунд.
unsigned long long d_us = d_ns * 1000;  // Дільник мікросекунд.
unsigned long long d_ms = d_us * 1000;  // Дільник мілісекунд.
unsigned long long d_s = d_ms * 60;     // Дільник секунд.
unsigned long long d_m = d_s * 60;      // Дільник хвилин.
unsigned long long d_h = d_m * 24;      // Дільник годин.

int main()
{
    unsigned long long int timestamp;
    std::cout << "Enter the timestamp (ns): ";
    std::cin >> timestamp;
    std::cout << timestamp / d_h         << "d "
              << timestamp % d_h / d_m   << "h "
              << timestamp % d_m / d_s   << "m "
              << timestamp % d_s / d_ms  << "s "
              << timestamp % d_ms / d_us << "ms "
              << timestamp % d_us / d_ns << "us "
              << timestamp % d_ns        << "ns"
              << std::endl;
    return 0;
}

Отже, давайте розглянемо разом ваші роботи і обговоримо, що можна покращити. Зараз загальні моменти, які присутні майже в кожній роботі, потім буде огляд кожної роботи окремо.

  1. Пропоную потроху вивчати Google Style для уніфікації коду, який використовується на переважній більшості проектів https://google.github.io/styleguide/cppguide.html
  2. Використовуючи using namespace std; ви одразу затягуєте в свій код всі імена з даного неймспейсу. З часом у великому проекті такий підхід може призвести до конфліку імен. Уникнути цього можна, підключаючи лише ті імена, які ви використовуєте:

using namespace std::cout;
using namespace std::cin;
using namespace std::endl;
3. Глобальні змінні то є зло і їх потрібно уникати, якщо це можливо. Але константи можна і варто оголосити глобально. Назва константи повинна починатись з літери k, за якою назва продовжується верблюдом (з великої букви), наприклад:  kTimes.
4. Якщо значення змінної не змінюється, вона повинна бути оголошена константою. Константність краще позначати через constexpr, і лише там, де це неможливо, використовувати const. При використанні constexpr константа буде проініціалізована під час компіляції, const дозволяє зробити це в run-time.
5. С++ дозволяє оголошувати кілька змінних одного типу в одному рядку. Але варто уникати цього і кожну змінну оголошувати в окремому рядку.
6. Змінна повинна бути проініціалізована при оголошенні. Завжди задавайте початкове значення змінної для уникнення випадкового використання «сміттєвого значення».
7. Найкращий і найбезпечніший спосіб ініціалізувати змінну це uniform-initialization (фігурні дужки і без знаку присвоєння). В цьому випадку компілятор не буде приводити типи, а видасть помилку, якщо дане значення не співпадає з оголошеним типом. Приклад такої ініціалізації:
int a{-5};
unsigned int b{-5}; // компілятор видасть помилку
unsigned int c = -5; //  компілятор видасть попередження
8. Використовуйте типи з плаваючою точкою лише для чисел з плаваючою точкою. В даній задачі у вас задається кількість наносекунд, яка апріорі не можу бути дробом, як і інші величини у вас лише цілочисленні.
9. Позначати тип як беззнаковий (unsigned), якщо діапазон значень даної змінної лише додатні числа і нуль:
unsigned int days{0};
10. Приведення типу зі звуженням (з втратою частини розрядів) свідчить про архітектурну помилку і в С++ не вітається, а за стандартами безпеки взагалі заборонено.
11. Ніколи не використовуйте в С++ конструкції мови С, якщо є С++ аналог. Для приведення типів в 90% підійте static_cast.
12. Використання С макросів в С++ заборонене через порушення безпекових принципів.
13. Використання #define в С++ дозволене лише для підключення платформозалежних бібліотек.
14. Слідкуйте за повідомленнями компілятора. Ви повинні усунути не лише усі повідомлення про помилки (без чого ваша програма і не скомпілюється), але й усі попередження (warning).


Комментарии

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

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

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