Лабораторна робота 3

Твердження мови C++

1 Завдання на лабораторну роботу

Для виконання всіх завдань слід використовувати операції та твердження. Усі твердження слід помістити в тіло функції main().

1.1 Програмна реалізація алгоритму з розгалуженням

Розробити програму розв'язання квадратного рівняння. Програма повинна включати перевірку всіх можливих варіантів вихідних даних. Зокрема, слід перевіряти дискримінант, а також передбачити перевірку, чи рівняння є квадратним. Якщо рівняння виродилося в лінійне, слід передбачити знаходження кореня цього лінійного рівняння, або встановити наявність безлічі розв'язків (відсутності розв'язків).

1.2 Програмна реалізація циклічного алгоритму

Розробити програму, в якій користувач уводить значення x, n і k. Програма реалізує алгоритм обчислення виразу:

y = 1/(x + 2) + 2/(x + 4) + ... + (k – 1)/(x + 2(k – 1)) + (k + 1)/(x + 2(k + 1)) + ... + n/(x + 2n)

У наведеній сумі спільний член можна записати як i/(x + 2i), але в ньому пропущено один елемент, коли i = k.

Забезпечити перевірку можливих помилок.

1.3 Обчислення добутку

Розробити програму, яка забезпечує читання x і n і обчислює y:

y = (x + 1)(x – 2)(x + 3)(x – 4) ... (x – 2n)

1.4 Обчислення суми

Розробити програму, яка читає значення eps (невеличке число – точність обчислень) і обчислює y:

y = 1/2 + 1/4 + 1/8 + 1/16 + ...

Цикл завершується, якщо новий доданок менше, ніж eps.

1.5 Індивідуальне завдання

Розробити програму, яка обчислює значення функції в заданому діапазоні. Програма повинна реалізувати алгоритм, розроблений у завданні 1.3 першої лабораторної роботи. Не використовувати власних функцій.

2 Методичні вказівки

2.1 Порожнє твердження

Раніше була наведена класифікація тверджень, а також було розглянуто синтаксис та способи роботи з твердженнями-описами та твердженнями-виразами.

Порожнє твердження (null statement) – це просто крапка з комою. Порожнє твердження вживають, коли твердження необхідне синтаксично, але не треба виконувати ніяких дій.

2.2 Складене твердження

Складене твердження – це послідовність тверджень, укладена у фігурні дужки {}. Складене твердження часто іменують блоком. Після фігурної дужки, яка закриває блок, крапка з комою не ставиться. Синтаксично блок може розглядатися як окреме твердження. Наприклад:

{
    temp = a;
    a = b;
    b = temp;
}

Складені твердження зазвичай розташовують у тих місцях програми, де за синтаксисом повинно бути одне твердження, а алгоритм вимагає виконання декількох дій.

Використання програмних блоків пов'язане з певними правилами форматування сирцевого коду. Фігурна дужка розкривається на новому рядку, після неї в цьому рядку не розташовують ніякого коду. Подальші твердження розташовують на наступному рядку з відступом. Для відступів можна застосовувати:

  • два пропуски;
  • чотири пропуски;
  • символ табуляції.

У прикладах цих лабораторних робіт для відступів використано чотири пропуски.

Після останнього твердження блоку (перед фігурною дужкою, що закривається) здійснюється перехід на новий рядок, а останній доданий відступ скасовується. Фігурна дужка, що закривається, розташована на окремому рядку.

Блоки можна вкладати один в інший. Наприклад:

{
    a = x;
    b = y;
    {
        temp = a;
        a = b;
        b = temp;
    }
}

Блок також має значення у визначенні видимості й часу життя ідентифікаторів. Ідентифікатор, оголошений усередині блока, має область видимості від точки визначення до фігурної дужки, що закривається. Наприклад,

{
    int i = 1;
    {
        int k = i;
    }
    k = 2; // Помилка! Змінна k недоступна в зовнішньому блоці 
}

Не варто створювати однойменні локальні змінні, тим більше, що в деяких мовах (наприклад Java, C#) це заборонено.

Сучасні стандарти кодування вимагають розташування блоків у гілках умовного твердження і в тілі циклу навіть, якщо синтаксично цей блок не потрібен.

2.3 Твердження вибору

2.3.1 Умовне твердження

Твердження вибору дозволяють виконувати різні дії залежно від умов, які виникають під час виконання програми.

Умовне твердження (твердження if) забезпечує розгалуження відповідно до умови. Умовне твердження застосовується в двох видах:

Перша форма:

if (умова)
    твердження

Друга форма:

if (вираз-умова)
    твердження1
else
    твердження2

Під час виконання твердження if у першій формі обчислюється вираз-умова і якщо це істина (true, значення, відмінне від 0), то виконується твердження. Якщо вираз-умова повертає 0 (false), ніякі дії не виконуються.

У другій формі виконується твердження1, якщо вираз-умова повертає значення, відмінне від 0 (true), твердження2 виконується, якщо результат виразу-умови інтерпретується як 0 (false).

Вираз-умова може бути будь-якого типу, що приводиться до цілого.

В обох випадках управління далі передається від твердження if до наступного твердження.

Якщо необхідно виконати декілька дій в одній з гілок, використовують складене твердження (блок). Наприклад:

if (i > 0)
    y = x * i;
else
{
    x = i;
    y = x + i;
} 

У цьому прикладі твердження y = x * i виконується, якщо i більше ніж 0. Якщо i менше або дорівнює 0, значення i присвоюється змінній x, а сума x + i записується в y.

Примітка: належна практика кодування рекомендує завжди використовувати складене твердження у конструкції if, навіть, якщо виконується одне твердження.

Наведений у першій лабораторній роботі алгоритм обчислення зворотної величини можна програмно реалізувати за допомогою умовного твердження:

#include <iostream>

using namespace std;

int main()
{
    double x;
    cin >> x;
    if (x == 0)
    {
        cout << "Error" << endl;
    }
    else
    {
        double y = 1 / x;
        cout << y << endl;
    }
    return 0;
}

Як видно з наведеного прикладу, в обох гілках твердження if розташовано складені твердження відповідно до належної практики кодування. Крім того, змінна y визначена всередині блоку лише в одній з гілок. Такий стиль вважається більш коректним, ніж визначення всіх змінних заздалегідь.

Дуже часто початківці роблять помилку, використовуючи if (x = 0) замість if (x == 0):

int x = 3;
if (x = 0)
{
    cout << "zero";
}
else
{
    cout << "non-zero";
}

Використання такої умови не спричинить помилок компілятора, ймовірний лише "натяк" (hint), але призведе до неприємних наслідків. Блок, який повинен виконуватись, якщо умова дорівнює true, ніколи не буде виконана й управління передаватиметься на else. Крім того, буде зіпсоване значення x. Після "перевірки" воно завжди дорівнюватиме 0.

Наведена нижче програма обчислює результат ділення:

#include <iostream>

using namespace std;

int main()
{
    double a, b;
    cout << "Enter a and b: ";
    cin >> a >> b;
    if (b)
    {
        double c = a / b;
        cout << "Quotient is " << c << endl;
    }
    else
    {
        cout << "Error" << endl;
    }
    return 0;
}

Як видно з прикладу, замість перевірки if (b != 0) достатньо записати if (b). Така форма типова для C і C++, але заборонена в деяких інших мовах, таких як Java або C#.

Умовні твердження можна вкладати одне в інше. Наприклад, Необхідно ввести x і вивести такі повідомлення: "ліворуч", якщо x < 0, "всередині", якщо 0 ≤ x ≤ 1 і "праворуч", якщо x > 1. Код введення і перевірки може бути таким:

setlocale(LC_ALL, "UKRAINIAN");
double x;
cin >> x;
if (x < 0)
    cout << "ліворуч";
else if (x <= 1)
    cout << "всередині";
else
    cout << "праворуч";  

Для уникнення плутанини в цьому випадку також доцільно використовувати фігурні дужки:

setlocale(LC_ALL, "UKRAINIAN");
double x;
cin >> x;
if (x < 0)
{
    cout << "ліворуч";
}
else
{
    if (x <= 1)
    {
        cout << "всередині";
    }
    else
    {
        cout << "праворуч";
    }
}

Типовими помилками початківців є розташування умови після else (синтаксична помилка), а також зайва перевірка умови, яка вже перевірялась:

if (x < 0)
{
    cout << "ліворуч";
}
else
{
    if (x >= 0 && x <= 1)
    {
        cout << "всередині";
    }
    else {
        if (x > 1)
        {
            cout << "праворуч";
        }
    }
}

Слід уникати зайвих дій в програмі.

Під час роботи з умовним твердженням можуть виникати помилки, пов'язані з використанням зайвої крапки з комою. Навіть, якщо змінні x та y були коректно створені та ініціалізовані, наведений нижче код не буде скомпільований:

if (x > 0);
{
    y = 1;
}
else
{
    y = 2;
}

Помилка пов'язана з тим, що після твердження перевірки було розташовано крапку з комою. Фактично після if (...) розташовано порожнє твердження (;). Воно виконується, якщо твердження дорівнює true (1). Складене твердження виконується в усіх випадках. Ключове слово else в цьому випадку вже не відноситься до if, що і спричиняє помилку компіляції. Тому не слід зловживати крапками з комами в сирцевому коді.

2.3.2 Перемикач

Для розгалуження на декілька гілок використовують конструкцію switch (перемикач).

switch (вираз_керування)
{
    /* тіло */
}

Тіло твердження switch складається з послідовності case-міток та необов'язкової мітки default. Мітка складається з ключового слова case після якого розташований константний вираз. Не повинно бути двох константних виразів з однаковими значеннями. Мітка default може з'явитися лише один раз.

Виконання перемикача складається з обчислення виразу керування і переходу до групи тверджень, позначених case-міткою, значення якої дорівнює виразу керування. Якщо такої мітки немає, виконуються твердження після мітки default. Під час виконання перемикача відбувається перехід на твердження з обраною міткою, і далі твердження виконуються у нормальному порядку. Для того щоб не виконувати твердження, які залишилися у тілі перемикача, необхідно використовувати твердження break. Наприклад:

switch (i)
{
    case 1:
        cout << "дорівнює 1"; 
        break;
    case 2:
        cout << "дорівнює 2, ";
    default: 
        cout << "не дорівнює 1";
}

Результати виконання попереднього коду будуть такими:

i Виведення
1 дорівнює 1
2 дорівнює 2, не дорівнює 1
інші значення не дорівнює 1

Особливістю перемикача є вимога до виразу керування: він повинен бути цілим.

За допомогою перемикача можна створити простіше меню. Залежно від уведення відповіді користувачем програма виконує різні дії. Наприклад:

double x;
cout << "Введiть x\n";
cin >> x;
cout << "1 - Обчислення зворотної величини\n";
cout << "2 - Обчислення другого степеня\n";
cout << "3 - Обчислення третього степеня\n";
int k;
cout << "Введiть вiдповiдь\n";
cin >> k;
switch (k)
{
    case 1:
        cout << 1 / x << endl;
        break;
    case 2:
        cout << x * x << endl;
        break;
    case 3:
        cout << x * x * x << endl;
        break;
    default:
        cout << "Хибний вибiр!" << endl;
        break;
}

Виведення позицій меню і введення користувачем відповіді можна розташувати в циклі. Цикли будуть розглянуті нижче.

Мітки можна групувати, якщо декілька значень обумовлюють однакові дії. Наприклад, користувач уводить номер місяця (від одного до 12 включно) і програма виводить йому назву сезону:

int month;
cout << "Enter month: (1..12): ";
cin >> month;
switch (month)
{
    case 12: case 1: case 2:
        cout << "Winter\n";
        break;
    case 3: case 4: case 5:
        cout << "Spring\n";
        break;
    case 6: case 7: case 8:
        cout << "Summer\n";
        break;
    case 9: case 10: case 11:
        cout << "Autumn\n";
        break;
    default:
        cout << "Wrong season!\n";
}

Відсутність твердження break є однією з дуже розповсюджених помилок у використанні switch. Тому в деяких мовах (наприклад, C#) використання break є обов'язковим і його відсутність призводить до помилки компіляції.

2.4 Циклічні твердження

2.4.1 Загальні відомості

Циклічні конструкції дуже часто використовують у програмах. Дуже важко знайти реальну програму, яка була створена без застосування явних циклів. Але навіть у реалізації алгоритмів без явних циклів циклічні конструкції присутні неявно, оскільки реалізувати введення та виведення даних на стандартному рівні без циклів не можливо.

Цикли застосовують для обчислення сум і добутків, проходження всіх елементів масивів або інших наборів даних, реалізації ітеративних алгоритмів обчислень, забезпечення отримання подій від різних пристроїв з обробкою цих подій, читання даних з файлу (до кінця файлу), роботи з рядками тощо.

Цикли у мовах програмування зазвичай будуються з заголовка (перевірка умови, визначення діапазону, підготовка або модифікація параметра тощо) і тіла (твердження, які можуть виконуватися багато разів, залежно від умов).

Твердження циклу представлені в чотирьох варіантах:

  • цикл з передумовою: перед кожним кроком циклу перевіряється певна умова, якщо результат істинний, виконуються дії, визначені в тілі циклу;
  • цикл з постумовою: спочатку виконуються дії, визначені в тілі циклу, потім здійснюється перевірка умови і залежно від результату перевірки здійснюється повторення дій або здійснюється вихід з циклу;
  • цикл з параметром: ініціалізується спеціальна змінна – параметр циклу, здійснюється перевірка умови виконання дій в тілі циклу і модифікація значення параметра;
  • цикл, побудований на діапазоні: визначається діапазон і здійснюється робота з елементами масивів або інших структур даних.

Цикл, побудований на діапазоні, пов'язаний з масивами та іншими колекціями елементів, буде розглянуто пізніше.

Синтаксично в усіх формах циклу тіло – це одне твердження. Якщо в тілі необхідно виконати декілька тверджень, застосовують складене твердження (блок). Належна практика кодування вимагає використання блоку в усіх випадках.

2.4.2 Цикл з передумовою

Цикл з передумовою будується за схемою

while (вираз-умова)
    твердження

Під час кожного повторення циклу (ітерації) обчислюється вираз-умова і якщо значення цього виразу не дорівнює нулю, виконується твердження – тіло циклу.

Роботу циклу можна показати на прикладі обчислення суми:

y = 12 + 22 + 32 + ... + n2

Код буде таким:

int y = 0;
int i = 1;
while (i <= n)
{
    y += i * i;
    i++;
}

Дуже важливо змінювати значення i в тілі циклу, інакше можна отримати нескінчений цикл. Також помилкою буде розташувати крапку з комою після заголовку циклу: отримаємо нескінчений цикл, на кожному кроці якого виконується порожнє твердження:

int y = 0;
int i = 1;
while (i <= n); // нескінчений цикл
{ // Це вже не тіло циклу
    y += i * i; 
    i++;
}

2.4.3 Цикл з постумовою

Цикл з постумовою будується за схемою

do
    твердження
while (вираз-умова); 

У цьому варіанті вираз-умова обчислюється і перевіряється після кожного повторення твердження – тіла циклу, цикл повторюється, поки умова виконується. Тіло циклу в циклі з постумовою виконується хоча б один раз. Недоліком циклу з постумовою є потенційна можливість виконання тіла циклу навіть тоді, коли умова не виконувалася відразу. Іноді це є небезпечним.

Попередньо визначену суму

y = 12 + 22 + 32 + ... + n2

можна обчислити з використанням циклу do ... while:

int y = 0;
int i = 1;
do
{
    y += i * i;
    i++;
}
while (i <= n);

Недоліки циклу з постумовою виявляться навіть у цьому прикладі: якщо, наприклад, n дорівнює нулю, результат повинен бути 0, але цикл з постумовою дасть результат 1.

Іноді цикл з постумовою використовують під час введення даних, вимагаючи від користувача коректних даних. Наприклад:

double x;
do
{
    cout << "Уведiть додатне значення x\n";
    cin >> x;
    if (x <= 0)
    {
        cout << "Помилка!\n";
    }
}
while (x <= 0);

Використання таких конструкцій не завжди є коректним і може бути застосовано лише якщо це обумовлено завданням.

2.4.4 Цикл з параметром

Цикл з параметром будується за схемою

for (вираз1; вираз2; вираз3)
    твердження

Цикл з параметром реалізує такий алгоритм:

  • обчислюється вираз1 (зазвичай цей вираз виконує підготовку до початку циклу);
  • обчислюється вираз2 і якщо він дорівнює нулю, виконується перехід до наступного твердження програми (вихід з циклу);
  • якщо вираз2 не дорівнює нулю, виконується твердження – тіло циклу;
  • обчислюється вираз вираз3 – виконується підготовка до повторення циклу, після чого знову виконується вираз вираз2.

Найбільш компактним і надійним для обчислення сум і добутків з фіксованою кількістю кроків є цикл for.

Аналогічний приклад обчислення суми:

y = 12 + 22 + 32 + ... + n2

можна реалізувати з використанням циклу for:

int y = 0;
for (int i = 1; i <= n; i++)
{
    y += i * i;
}

У наведеному прикладі змінна i (параметр циклу) створюється у заголовку циклу. Область видимості цієї змінної обмежена заголовком і тілом циклу, а час життя – часом виконання кроків циклу. Такий підхід є рекомендованим, оскільки ймовірність використання раніше створеної змінної та втрати її попереднього значення відсутня. В усіх випадках створюється нова змінна, навіть, якщо змінна з таким ім'ям була створена раніше. Після закінчення циклу параметр, створений в заголовку, не може бути використаний.

Іноді необхідно використовувати значення параметра після завершення циклу. Тоді параметр треба визначити перед циклом. Наприклад:

int y = 0;
int i;
for (i = 1; i <= n; i++)
{
    y += i * i;
}
cout << i; // останнє значення i, яке дорівнює n + 1

На відміну від циклів з передумовою і постумовою, складніше випадково отримати нескінчений цикл, оскільки явно вказується початкове значення параметра та передбачається його зміна на кожному кроці.

Твердження

for ( ; ; );

створює нескінченний цикл. Малоймовірно, що такий код виник помилково. Але іноді помилкою буде неправильно визначений діапазон параметра. Такий цикл не буде нескінченим, оскільки рано чи пізно значення параметра досягне мінімального від'ємного значення і стане додатним:

int i;
for (i = 1; i <= n; i--)
{
    y += i * i;
}
cout << i; // 2147483647 - максимальне ціле значення

У заголовку циклу компілятор Visual Studio видасть попередження "Ill-defined for-loop".

Також не слід ставити крапку з комою після заголовку циклу for:

int y = 0;
int i;
for (i = 1; i <= n; i++); // помилка!
{
    y += i * i; 
}

Цикл не буде нескінченим, але код, який планувався як тіло циклу, буде виконано один раз для i зі значенням n + 1.

В цілому цикл for є більш надійним і ефективним, ніж цикли з передумовою і постумовою.

2.5 Твердження переходу

У сполученні з твердженнями циклу іноді використовують твердження переходуbreak, яке дозволяє перервати виконання поточного циклу, і continue, яке перериває поточну ітерацію циклу while, do або for та обумовлює достроковий перехід на наступну ітерацію. Найчастіше break і continue використовують у таких конструкціях:

if (умова_дострокового_завершення_циклу)
    break;
if (умова_дострокового_завершення_ітерації)
    continue;

Твердження goto дозволяє перейти на мітку. Мітка – це унікальний ідентифікатор із двокрапкою, що стоїть перед твердженням. Використовуючи goto і мітки, можна обійтись без блоків і циклів. Наприклад, попередню суму можна обчислити в такий спосіб:

    int y = 0;
    int i = 1;
label1:
    if (i > n)
        goto label2;
    y += i * i;
    i++;
    goto label1;
label2:
    cout << y;

В цьому прикладі label1 і label2 – це мітки.

Такий код нагадує стиль мови FORTRAN. Програму, побудовану на таких конструкціях, важко читати й ще важче зневаджувати. В сучасних програмах такий стиль не застосовують.

Єдиний випадок, коли використання goto виправдане, – це переривання декількох вкладених циклів. Наприклад:

  int a;
  . . .
  double b = 0;  
  for (int i = 0; i < 10; i++)
  {
      for (int j = 0; j < 10; j++)
      {
          if (i + j + a == 0)
          {
              goto label;
          }
          b += 1 / (i + j + a);
      }
  }
label:
  // інші твердження

3 Приклади програм

3.1 Коди символів

Програму виведення символів, наведену в прикладах до попередньої лабораторної роботи, можна модифікувати так, щоб користувач уводив з клавіатури символи в циклі. Для завершення циклу слід ввести літеру A:

#include <iostream>

using namespace std;

int main()
{
    char c;
    do
    {
        cin >> c;     // уводимо символ 
        int i = c;    // перетворюємо символ у ціле число
        cout << i << '\n'; // виводимо код
    }
    while (c != 'A');    // поки не отримаємо c == 'A'
    return 0;
}

Твердження do-while забезпечує виконання складеного твердження (блоку) кілька разів, поки визначена умова повторення (c != 'A') не отримає значення false.

3.2 Вкладені твердження if

Припустимо, необхідно створити програму, в якій здійснюється читання x та обчислення y відповідно до таблиці:

x y
менше, ніж -8 100
від -8 до 1 200
більше, ніж 1 300

Програма буде такою:

#include <iostream>

using namespace std;

int main()
{
    double x;
    cin >> x;
    double y;
    if (x < -8)
    { 
        y = 100;
    }
    else
    {
        if (x <= 1)
        {
            y = 200;
        }
        else
        {
            y = 300;
        }
    }
    cout << y;
    return 0;
}

3.3 Лінійне рівняння

Умовне твердження може бути використана для розв'язання лінійного рівняння:

ax + b = 0

У прикладі 3.1 першої лабораторної роботи наведено алгоритм з розгалуженням, який розв'язує цю задачу. Програма, яка реалізує цей алгоритм, може бути такою:

#include <iostream>
using namespace std;

int main()
{
    setlocale(LC_ALL,"UKRAINIAN");
    double a, b;
    cout << "Уведіть a і b: ";
    cin >> a >> b;
    if (a != 0)
    {
        double x = -b / a;
        cout << "Корінь: " << x << endl;
    }
    else 
    {
        if (b == 0)
        {
            cout << "Безмежна кількість коренів." << endl;
        }
        else
        {
            cout << "Немає коренів." << endl;
        }
    }
}

3.4 Використання твердження switch

Припустимо, необхідно створити програму, в якій здійснюється читання дійсного x і цілого n та обчислення y відповідно до таблиці:

n y
1 x
2 x2
3 x3
4 1 / x
інші значення 0

Для реалізації цієї програми слід використати твердження switch:

#include <iostream>

using namespace std;

int main()
{
    double x, y;
    int n;
    cin >> x >> n;
    switch (n)
    {
        case 1:
            y = x;
            break; 
        case 2:
            y = x * x;
            break; 
        case 3:
            y = x * x * x;
            break;
        case 4:
            y = 1 / x;
            break;
        default:
            y = 0;
    }
    cout << y;
    return 0
}

3.5 Обчислення суми

Припустимо, необхідно реалізувати програму, в якій здійснюється читання x і n та обчислюється y:

y = 1/(x - 1) + 1/(x - 2) + ... + 1/(x - n)

Програма повинна вивести повідомлення про помилку, якщо знаменник дорівнює нулю.

#include <iostream>

using namespace std;

int main()
{
    setlocale(LC_ALL,"UKRAINIAN");
    double x, y = 0;
    int i, n;
    cout << "Уведiть x i n: ";
    cin >> x >> n;
    for (i = 1; i <= n; i++)
    {
        if (x == i)
        {
            cout << "Помилка!\n";
            break;
        }
        y += 1/(x - i);
    }
    if (i > n) // сума обчислена
    {
        cout << "y = " << y << "\n";
    }
    return 0;
}

Альтернативне рішення:

#include <iostream>

using namespace std;

int main()
{
    setlocale(LC_ALL,"UKRAINIAN");
    double x, y = 0;
    int i, n;
    cout << "Уведiть x i n: ";
    cin >> x >> n;
    for (i = 1; i <= n; i++)
    {
        if (x == i)
        {
            cout << "Помилка!\n";
            return 1; // після return жодних дій не виконується
        }
        y += 1/(x - i);
    }
    cout << "y = " << y << "\n";
    return 0;
}

3.6 Добуток

У наведеній нижче програмі ми вводимо x, k і n і обчислюємо y:

y = x (x + 1) (x + 2) (x + 3) ... (x + k - 1)(x + k + 1) ... (x + n)
#include <iostream>
using namespace std;

int main()
{
    setlocale(LC_ALL,"UKRAINIAN");
    double x, y = 1;
    int i, k, n;
    cout << "Уведіть x, k та n: ";
    cin >> x >> k >> n;
    for (i = 0; i <= n; i++)
    {
        if (i == k)
        {
            continue;
        }
        y *= (x + i);
    }
    cout << "y = " << y << "\n";
    return 0;
}

Альтернативна реалізація:

#include <iostream>
using namespace std;

int main()
{
    setlocale(LC_ALL,"UKRAINIAN");
    double x, y = 1;
    int i, k, n;
    cout << "Уведіть x, k та n: ";
    cin >> x >> k >> n;
    for (i = 0; i <= n; i++)
    {
        if (i != k)
        {
            y *= (x + i);
        }
    }
    cout << "y = " << y << "\n";
    return 0;
}

3.7 Добуток з переміжними знаками

У прикладі 3.3 першої лабораторної роботи наведено алгоритм обчислення добутку з переміжними знаками в співмножниках:

p = x(x – 1)(x + 2)(x – 3) ... (x + (–1)n n)

Програма, яка реалізує цей алгоритм, може бути такою:

#include <iostream>
using namespace std;

int main()
{
    setlocale(LC_ALL,"UKRAINIAN");
    double x;
    int n;
    cout << "Уведіть x, n: ";
    cin >> x >> n;
    int k = 1;
    double p = 1;
    for (int i = 0; i <= n; i++)
    {
        p *= x + i * k;
        k = -k;
    }
    cout << "Добуток = " << p;
    return 0;
}

3.8 Експонента

Припустимо, необхідно реалізувати програму, в якій здійснюється читання x і обчислення ex:

y = ex = 1 + x + x2/2! + x3/3! + ...

 

Цикл завершується, якщо новий доданок менше 0.00001.

#include<iostream>

using namespace std;

int main()
{
    setlocale(LC_ALL,"UKRAINIAN");
    double x, y = 0;
    double z = 1; // доданок  
    int i = 1;
    cout << "Уведіть x: ";
    cin >> x;
    while (z > 0.00001)
    {
        y += z;
        z *= x / i;
        i++;
    }
    cout << "y = " << y << "\n";
    return 0;
}

Альтернативна реалізація:

#include <iostream>

using namespace std;

int main()
{
    setlocale(LC_ALL,"UKRAINIAN");
    double x, y = 0;
    double z = 1; // доданок  
    cout << "Уведіть x: ";
    cin >> x;
    for (int i = 1; z > 0.00001; i++)
    {
        y += z;
        z *= x / i;
    }
    cout << "y = " << y << "\n";
    return 0;
}

Як видно з прикладу, перевірка умови в циклі for не обов'язково пов'язана з параметром.

3.9 Вкладені цикли

У прикладі 3.4 першої лабораторної роботи наведено алгоритм обчислення суми добутків:

Обчислення реалізуємо за допомогою вкладених циклів. Програма може бути такою:

#include <iostream>
using namespace std;

int main()
{
    setlocale(LC_ALL,"UKRAINIAN");
    int n;
    cout << "Уведіть n: ";
    cin >> n;
    int sum = 0;
    for (int i = 1; i < n; i++)
    {
        int p = 1;
        for (int j = 1; j < n; j++)
        {
            p *= i + j * j;
        }
        sum += p;
    }
    cout << "Сума: " << sum;
}

3.10 Таблиця значень квадратних коренів чисел

Необхідно прочитати з клавіатури значення початку інтервалу, кінця інтервалу, величини кроку, з яким змінюється аргумент та у циклі вивести значення квадратних коренів чисел. Для обчислення квадратного кореня можна скористатися стандартною функцією sqrt(), яка оголошена в загловному файлі cmath.

Програма може мати такий вигляд:

#include <iostream>
#include <cmath>

using namespace std;

int main()
{
    setlocale(LC_ALL, "UKRAINIAN");
    double from, to, step;
    cout << "Введiть ліву границю, праву границю i крок аргументу: ";
    cin >> from >> to >> step;
    if (from < 0 || to < 0 || from >= to || step <= 0) 
    {
        cout << "Неправильнi данi\n";
    }
    else {
        // Основний цикл програми:
        for (double x = from; x <= to; x += step) {
            cout << "x = " << x << "\t y = " << sqrt(x) << endl;
        }
    }
    return 0;
}

Як результат виконання цієї програми на консолі з'являться пари значень x та y.

4 Вправи для контролю

Завдання 1

Розробити програму, в якій здійснюється читання символів і виведення їх шістнадцяткових кодів. Читання і виведення здійснювати в циклі.

Завдання 2

Написати програму, яка зчитує десяткові цілі числа і друкує символи з відповідними кодами. Читання і виведення здійснювати в циклі.

Завдання 3

Розробити програму, в якій здійснюється читання дійсного x та обчислення y (математична функція signum) з використанням твердження if:

x y
менше 0 -1
0 0
більше 0 1

Завдання 4

Розробити програму, в якій здійснюється читання цілого n та обчислення y відповідно до таблиці:

n y
0 2
1 4
2 5
3 3
4 1
інші значення 0

Для реалізації програми слід використати твердження switch.

5 Контрольні запитання

  1. Що таке твердження (твердження, statement)?
  2. Де і для чого використовують порожній вираз?
  3. Що таке твердження-вираз?
  4. Для чого використовують складене твердження (блок)?
  5. Опишіть синтаксис твердження if.
  6. Які помилки можуть бути пов'язані з використанням умовного твердження?
  7. Опишіть синтаксис твердження switch.
  8. Як використовувати твердження break всередині твердження switch?
  9. Для чого використовують твердження default?
  10. Що таке заголовок циклу і тіло циклу?
  11. У чому різниця між циклом з передумовою і циклом з постумовою?
  12. В чому є основний недолік циклу з постумовою?
  13. У чому переваги твердження for?
  14. У чому різниця між твердженнями break і continue?
  15. Як здійснити вихід з декількох вкладених циклів?
  16. Коли доцільно використовувати goto?

 

up