матеріали для
підтримки вивчення предмету

Алгоримічна структура повторення. Цикли for та while

Для виконання деяких завдань людині іноді доводиться повторювати одні і ті самі дії багато разів. Наприклад, чистити казанок, поки він брудний; саджати картоплю, поки не скінчиться посадковий матеріал або місце на ділянці; 100 разів прописувати літеру А для правильної каліграфії; множити число 5 саме на себе 7 разів, щоб обчислити 58 і т.д.

В програмуванні для багаторазового повторення деяких дій використовують алгоритмічну структуру повторення, яку також називають циклом. Дії, що повторюються, називають тілом циклу, а одне повторення – ітерацією. В мові програмування C# існує чотири види циклів:

В даному розділі розглянемо два перших види циклів.

Цикл for – цикл з лічильником

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

Дана послідовність дій буде утворювати тіло циклу. Але виконавцю, окрім вказаних дій, потрібно виконувати ще одну – рахувати кількість принесених відер (кількість ітерацій). Для контролю кількості виконаних повторень в циклах використовують спеціальну змінну, яку називають лічильником (її прийнято називати i).

В мові C# цикл for записується таким чином:

for (стартове значення лічильника; умова повторення; зміна значення лічильника)
  {
     тіло циклу;
  }

Запишемо алгоритм для розв’язання поставленої задачі.

for (int i=1; i<=10; i=i+1)
  {
     набрати відро води;
     перенести його до діжки;
     вилити відро у діжку;
     повернутися до криниці;
  }

Перекласти даний алгоритм можна так: для значень лічильника від 1 до 10 виконувати дії, записані в тілі циклу; після кожної ітерації збільшувати значення лічильника на 1. Коли значення лічильника стане рівним 11, цикл припинить своє виконання – 11-е відро набирати не потрібно.

Зауваження: для збільшення або зменшення значення змінної на 1 краще використовувати операції інкременту (декременту): i++ замість i=i+1 та i-- замість i=i-1.

Розв’язування задач з використання циклу for. Об’єкт Cписок (ListBox)

Програмування на C#
рис. 8.1

Створіть рішення «Lesson_8» проект «Task_1». Скласти програму, яка виводить задане користувачем слово на екран 10 разів (рис. 8.1).

Для виведення результатів роботи програми, які складаються з багатьох рядків, будемо використовувати об’єкт ListBox – список. Основною властивістю даного об’єкту є властивість Items, в якій зберігаються елементи списку. Основним методом об‘єкту Список є метод Add, який додає новий елемент (рядок) у список, наприклад:

listBox1.Items.Add(“hello”);

Для розв’язання даної задачі спочатку дізнаємося, яке слово ввів користувач та запишемо його в рядкову величину (змінна типу string), а потім виведемо його на екран 10 разів, використавши цикл for.

private void button1_Click(object sender, EventArgs e)
    {
        string x = textBox1.Text;
        for (int i=1; i<=10; i++)
        {
            listBox1.Items.Add(x);
        }
    }

Якщо скористатися кнопкою «вивести» декілька разів, то в списку нові результати роботи програми будуть додаватися до попередніх. Тому потрібно використати метод Clear для очищення елементів (рядків) у списку. Додавши даний метод в кінець програмного коду отримаємо проблему: програма буде виводити результати на екран, а потім миттєво їх стирати. Обійти цю проблему можна написавши метод Clear в початку програми – тоді об’єкт Список спочатку буде очищатися, і лише потім у нього будуть виводитися нові результати.

Також, для зручності перевірки правильності роботи програми, виведення кожного рядка будемо супроводжувати номером цього рядка. Для цього окрім слова (змінна x) будемо виводити лічильник i, який проходить значення від 1 до 10 з кроком 1. Остаточний програмний код та програма (рис. 8.2) буде виглядати так:

private void button1_Click(object sender, EventArgs e)
    {
        string x = textBox1.Text;
        listBox1.Items.Clear();
        for (int i=1; i<=10; i++)
        {
            listBox1.Items.Add(i + ": " + x);
        }
    }
Програмування на C#
рис. 8.2
Програмування на C#
рис. 8.3

Задача №2 (Task_2). Скласти програму для знаходження суми всіх натуральних чисел від 1 до N включно. Для кращої наочності роботи програми будемо виводити не лише остаточний результат, а й усі проміжні результати обчислень (рис. 8.3).

Процес знаходження потрібної суми порівняємо зі збиранням грошей у скарбничку. Спочатку скарбничка порожня, а потім, згідно з умовою задачі, туди додаються 1 грн, 2 грн, 3 грн і т.д. Числа, що додаються до суми, позначимо змінною i – лічильник, а процес додавання кожного числа опишемо формулою s=s+i. Дана операція присвоювання буде виконуватися справа наліво: спочатку до попереднього значення суми додається число i, а потім отримане значення записується в змінну s. Тобто, після виконання цієї операції значення змінної s збільшиться на i. Дану операцію можна записувати коротше: s+=i.

Програмний код для розв’язання задачі:

private void button1_Click(object sender, EventArgs e)
    {
       int n = int.Parse(textBox1.Text);
       int s = 0;
       listBox1.Items.Clear();
       for (int i=1; i<=n; i++)
       {
          s = s + i;
          // s+=i;
          listBox1.Items.Add("Сума = " + s);
       }
    }

Нехай користувач ввів число 5 (n=5). Початкове значення суми s=0. Проілюструємо процес покрокового виконання циклу for за допомогою наступної таблиці.

i s
1 1
2 3
3 6
4 10
5 15
6
таблиця 1

Розглянемо ще декілька задач на знаходження сум чисел.

Програмування на C#
рис. 8.4

Задача №3 (Task_3). Скласти програму для знаходження суми всіх парних чисел, які не перевищують заданого користувачем числа N. (рис. 8.4).

private void button1_Click(object sender, EventArgs e)
    {
        string x = textBox1.Text;
        listBox1.Items.Clear();
        for (int i=1; i<=10; i++)
        {
            listBox1.Items.Add(i + ": " + x);
        }
    }

Програмування на C#
рис. 8.5

Задача №4. Скласти програму для знаходження суми всіх натуральних чисел на проміжку від A до B включно. (рис. 8.5).

private void button1_Click(object sender, EventArgs e)
    {
        int a = int.Parse(textBox1.Text);
        int b = int.Parse(textBox2.Text);
        int s = 0;
        listBox1.Items.Clear();
        for (int i = a; i <= b; i++)
        {
            s = s + i;
            listBox1.Items.Add("Сума = " + s);
        }
   }
   
Програмування на C#
рис. 8.6

Задача №5 «Таблиця множення». Відомо цифру (задає користувач). Скласти програму, яка виводить на екран таблицю множення до 9 для цієї цифри. (рис. 8.6).

Введемо позначення:
- перший множник позначимо літерою а (задається користувачем);
- другий множник проходить значення від 1 до 9 з кроком 1 – отже це лічильник і;
- добуток позначимо літерою d.

Для виконання даного завдання нам потрібно 9 разів повторювати такі дії: обчислювати значення добутку і виводити результат на екран. Рядок для виведення відповіді буде складатися з п’яти підрядків: значень змінних a, i, d та символів «х» і «=» між ними. Програмний код для реалізації даного алгоритму наведено нижче.

private void button1_Click(object sender, EventArgs e)
    {
        int a = int.Parse(textBox1.Text);
        int d;
        listBox1.Items.Clear();
        for (int i = 1; i <= 9; i++)
        {
            d = a * i;
            listBox1.Items.Add(a + " x " + i + " = " + d);
        }
    }
  
Програмування на C#
рис. 8.7

Задача №6. Спортсмен в перший день тренувань пробіг S км. Кожного наступного дня він збільшував дистанцію на V відсотків. Вивести інформацію про перші 10 днів тренувань спортсмена. (рис. 8.7).

Спортсмен почав збільшувати дистанцію з другого дня, отже, цикл для обчислення і виведення наступної дистанції будемо виконувати для значень лічильника від 2 до 10. Для того, щоб не «загубити» перший день тренувань, виведемо інформацію про нього окремо, перед виконанням циклу.

private void button1_Click(object sender, EventArgs e)
    {
        double s = double.Parse(textBox1.Text);
        double v = double.Parse(textBox2.Text);
        listBox1.Items.Clear();
        listBox1.Items.Add("1 день: " + s + " км");
        for (int i=2;i<=10; i++)
        {
            s = s + s * v / 100;
            s = Math.Round(s, 3);
            listBox1.Items.Add(i + " день: " + s + " км");
        }
    }

Форматований вивід дробових чисел

Програмування на C#
рис. 8.8

Задача №7. Протабулювати функцію y = x3 – 2 на проміжку від A до В з кроком k. Протабулювати функцію - означає обчислити значення функції для всіх х на деякому проміжку з деяким кроком. (рис. 8.8).

private void button1_Click(object sender, EventArgs e)
    {
        double a = double.Parse(textBox1.Text);
        double b = double.Parse(textBox2.Text);
        double k = double.Parse(textBox3.Text);
        double y;
        listBox1.Items.Clear();
        for (double i = a; i <= b; i = i + k)
        {
            y = Math.Pow(i, 3) - 2;
            listBox1.Items.Add("X=" + i + "; Y=" + y);
        }
    }

Програмування на C#
рис. 8.9

В наведеному вище програмному коді є один недолік – результати обчислень виводяться не в рівні колонки (рис.8.9). На це впливає різна кількість символів в значеннях х, наприклад х=1 та x=1,5. Для того, щоб «підрівняти» виведення результатів, скористаємось одним із способів форматованого виводу дробових чисел в C#, а саме - метод ToString() з параметром F2, де 2 – число знаків після коми.

Таким чином, замінивши в тілі циклу рядок для виведення результатів на наступний,

listBox1.Items.Add("X=" + i.ToString("F2") + "; Y=" + y.ToString("F2"));

отримаємо виведення результатів в дві рівні колонки (рис.8.8).

Цикл while – цикл з передумовою

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

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

Для задач, в яких наперед не відомо кількість ітерації зручно використовувати цикл з передумовою – цикл while, який в мові C# має такий вигляд:

while (умова повторення)
  {
     тіло циклу;
  }

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

Використаємо цикл while для розв’язання поставленої задачі.

while (діжка не повна)
  {
     набрати відро води;
     перенести його до діжки;
     вилити відро у діжку;
     повернутися до криниці;
  }

Даний цикл, в залежності від початкових даних, може виконати різну кількість повторень:

В останньому випадку відбувається процес зациклювання (програма не припиняє своє виконання). Для виходу з даної ситуації потрібно повернутися в середовище Visual Studio та натиснути кнопку Stop Debugging в панелі інструментів або [Shift] + [F5] на клавіатурі.

Розв’язування задач з використання циклу while

Для того, щоб краще зрозуміти різницю між циклами for і while розв’яжемо першу задачу, яка вже була розв’язана циклом for.

Задача №8. Скласти програму, яка виводить задане користувачем слово на екран 10 разів (рис. 8.10).

Програмування на C#
рис. 8.10
private void button1_Click(object sender, EventArgs e)
    {
        string x = textBox1.Text;
        listBox1.Items.Clear();
        int i = 1;
        while (i<=10)
        {
            listBox1.Items.Add(i + ": " + x);
            i++;
        }
    }

В програмах з використанням циклу while потрібно слідкувати, щоб в тілі циклу відбувалися деякі дії, які в той чи інший момент змінять умову повторення з істинної на хибну. В нашому алгоритмі такою дією є команда i++; , яка збільшує значення лічильника на 1 при кожному повторенні.

Програмування на C#
рис. 8.11

Задача №9. Спортсмен в перший день тренувань пробіг S км. Кожного наступного дня він збільшував дистанцію на V відсотків. Визначити, на який день спортсмен подвоїть стартову дистанцію. Вивести інформацію про кожен день тренування спортсмена та остаточну відповідь. (рис. 8.11).

В попередній аналогічній задачі спортсмен тренувався 10 днів. В даній задачі кількість днів тренувань (кількість повторень) невідомо, а, отже, для розв’язання зручно використати цикл while.

private void button1_Click(object sender, EventArgs e)
    {
        double s = double.Parse(textBox1.Text);
        double v = double.Parse(textBox2.Text);
        listBox1.Items.Clear();
        listBox1.Items.Add("1 день: " + s + " км");
        double x = 2 * s; // x - подвоєна дистанція
        int i = 2;
        while (s<x)
        {
            s = s + s * v / 100;
            s = Math.Round(s, 3);
            listBox1.Items.Add(i + " день: " + s + " км");
            i++;
        }
        listBox1.Items.Add("Дистанцію подвоєно на " + (i - 1) + " день");
    }

Звернемо увагу на те, що після досягнення потрібної дистанції, команда i++; виконається ще один «зайвий» раз. Тому, при виведенні остаточної відповіді потрібно змінну i зменшити на одиницю.

Програмування на C#
рис. 8.12

Задача №10. Відомо натуральне число. Вивести на екран цифри даного числа в зворотньому порядку. (рис. 8.12).

Для того, щоб дізнатися останню цифру числа, потрібно визначити його остачу при діленні на 10. Потім нам потрібно «відкинути» останню цифру числа, поділивши його на 10 націло. Якщо дані дії помістити в тіло циклу, який буде тривати, поки число більше 0, ми отримаємо алгоритм розв’язання поставленої задачі.

private void button1_Click(object sender, EventArgs e)
    {
        long a = long.Parse(textBox1.Text);
        long x;
        while (a>0)
        {
            x = a % 10;
            listBox1.Items.Add(x);
            a = a / 10;
        }
    }

Програмування на C#
рис. 8.13

Задача №11 «НСД - 1». Визначити НСД двох натуральних чисел. (рис. 8.13).

Для розв’язання задачі скористаємося алгоритмом Евкліда: будемо заміняти більше з двох чисел їх різницею, поки числа не стануть рівні. Отримані в результаті однакові числа і будуть НСД двох заданих чисел.

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

private void button1_Click(object sender, EventArgs e)
    {
        int a = int.Parse(textBox1.Text);
        int b = int.Parse(textBox2.Text);
        listBox1.Items.Clear();
        while (a!=b)
        {
            if (a>b)
            {
                a = a - b;
            }
            else
            {
                b = b - a;
            }
            listBox1.Items.Add("А = " + a + " B = " + b);
        }
        listBox1.Items.Add("==============");
        listBox1.Items.Add("НСД = " + a);
    }

Програмування на C#
рис. 8.14

Задача №12 «НСД - 2». Визначити НСД двох натуральних чисел. (рис. 8.14).

В деяких випадках попередній алгоритм працює дуже повільно. Наприклад, при вхідних даних А=1000, В=2 програма буде виконувати 499 ітерацій, постійно віднімаючи від числа А число В.

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

private void button1_Click(object sender, EventArgs e)
    {
        int a = int.Parse(textBox1.Text);
        int b = int.Parse(textBox2.Text);
        listBox1.Items.Clear();
        while (a!=0 && b!=0)
        {
            if (a > b)
            {
                a = a % b;
            }
            else
            {
                b = b % a;
            }
            listBox1.Items.Add("А = " + a + " B = " + b);
        }
        listBox1.Items.Add("==============");
        listBox1.Items.Add("НСД = " + (a+b));
    }

Практичне завдання

Завдання №13 (рішення lesson_8, проект task_13). Скласти програму, яка виводить на екран задане користувачем слово задану кількість разів (рис. 8.15).

Програмування на C#
рис. 8.15

Завдання №14 (рішення lesson_8, проект task_14). Скласти програму для знаходження суми всіх натуральних чисел кратних 3 і менших заданого користувачем числа N. (рис. 8.16).

Програмування на C#
рис. 8.16

Завдання №15 (рішення lesson_8, проект task_15). «Таблиця множення - 2». Відомо цифру (задає користувач). Скласти програму, яка виводить на екран таблицю множення до 9 для цієї цифри в зворотньому порядку (від 9 до 1). (рис. 8.17).

Програмування на C#
рис. 8.17

Завдання №16 (рішення lesson_8, проект task_16). Скласти програму, яка виводить таблицю переведення градусів Цельсія в градуси Фаренгейта. Діапазон температур задає користувач. °F = 9 / 5 ∙ °C + 32 (рис. 8.18).

Програмування на C#
рис. 8.18

Завдання №17 (рішення lesson_8, проект task_17). Скласти програму, яка виводить на екран значення квадратів усіх чисел від А до В (А і В задає користувач). (рис. 8.19).

Програмування на C#
рис. 8.19

Завдання №18 (рішення lesson_8, проект task_18). Скласти програму, яка виводить на екран значення квадратних коренів усіх натуральних чисел від А до В (А і В задаються користувачем). (рис. 8.20).

Програмування на C#
рис. 8.20

Завдання №19 (рішення lesson_8, проект task_19). Протабулювати функцію y = |x2 + 3x - 1| на проміжку від A до В з кроком k. Протабулювати функцію - означає обчислити значення функції для всіх х на деякому проміжку з деяким кроком (рис. 8.21).

Програмування на C#
рис. 8.21

Завдання №20 (рішення lesson_8, проект task_20). Скласти програму для обчислення факторіала числа N (рис. 8.22).

Програмування на C#
рис. 8.22

Завдання №21 (рішення lesson_8, проект task_21). «Яблука». Зібрали Х кг яблук для сушіння. За один день сушіння яблука втрачають V% маси. Визначити масу яблук протягом перших семи днів сушіння. (рис. 8.23).

Програмування на C#
рис. 8.23

Завдання №22 (рішення lesson_8, проект task_22). «Яблука - 2». Зібрали Х кг яблук для сушіння. За один день сушіння яблука втрачають V% маси. Визначити, на який день яблука втратять половину своєї маси. Вивести інформацію про кожен день сушіння яблук та остаточну відповідь. (рис. 8.24).

Програмування на C#
рис. 8.24

Завдання №23 (рішення lesson_8, проект task_23). «Банк». В банк на депозитний рахунок поклали X гривень на N років під V відсотків річних. Вивести стан рахунку на кінець кожного року (в кінці кожного року нараховані відсотки додаються до основного вкладу). (рис. 8.25).

Програмування на C#
рис. 8.25

Завдання №24 (рішення lesson_8, проект task_24). «Банк - 2». В банк на депозитний рахунок поклали X гривень під V відсотків річних. Визначити, скільки років знадобиться для того, щоб отримати M гривень. Вивести стан рахунку на кінець кожного року та кількість необхідних років. (рис. 8.26).

Програмування на C#
рис. 8.26