Печатать книгуПечатать книгу

§ 5. Аператар цыкла

Сайт: Профильное обучение
Курс: Інфарматыка. 10 клас (Павышаны ўзровень)
Книга: § 5. Аператар цыкла
Напечатано:: Гость
Дата: Понедельник, 6 Май 2024, 20:57

5.1. Аператар цыкла з перадумовай

 

Для запісу аператара цыкла з перадумовай выкарыстоўваецца каманда while. Фармат каманды:

while. Фармат каманды:

while (<умова>){

  цела цыкла;

}

Умова ў запісе аператара цыкла можа быць простай і састаўной. Фігурныя дужкі могуць быць прапушчаны, калі цела цыкла складаецца з адной каманды.

Пымер 5.1. Напісаць праграму, якая вызначыць колькасць лічбаў у натуральным ліку n.

Этапы выканання задання

I. Зыходныя даныя: n (зададзены лік).

II. Вынік: k — колькасць лічбаў у ліку.

III. Алгарытм рашэння задачы.

1. Увод зыходных значэнняў. 
2. Пачатковае значэнне пераменнай  k = 0. 
3. Каб палічыць колькасць лічбаў у ліку, будзем дзяліць лік на 10 да таго часу, пакуль лік большы за 1. Паколькі ўмова працягвання працы невядомая, то будзем выкарыстоўваць цыкл  while
4. У цыкле будзем памяншаць лік n у 10 разоў і павялічваць значэнне k на 1.
5. Вывад выніку.

IV. Апісанне пераменных: n – int.

Цыкл while працуе да таго часу, пакуль умова цыкла праўдзівая. Для таго каб цыкл завяршыў сваю работу, у целе цыкла павінны быць каманды, выкананне якіх прывядзе да таго, што ўмова цыкла стане непраўдзівай. Калі такіх каманд няма, цыкл выконваецца бясконца. Такую сітуацыю называюць зацыкліваннем. У выпадку зацыклівання трэба перапыніць выкананне праграмы. У Code::Blocks для гэтага можна выкарыстоўваць кнопку  .

Ппрыклад 5.1.

V. Праграма:

#include<iostream>

#include<math.h>

 

using namespace std;

 

int main()

{

  int n;

  cout << "n = ";

  cin >> n;

  int k = 0;

  while (> 0)

  {

    ///уменьшение числа в 10 раз

    /= 10;

    k++;

  }

  cout << "v chisle " << k; 

  cout << " cifr" << endl;

  return 0;

}

IV. Тэсціраванне. 

5.2. Аператар цыкла з постумовай

Цыкл, у якім умова для завяршэння работы правяраецца пасля выканання цела цыкла, у С++ запісваецца наступным чынам:

do {

  цела цыкла;

}

while (<умовы>);

Цыкл працуе, пакуль умова праўдзівая, і спыняе работу, калі ўмова становіцца непраўдзівай. Гэты цыкл называюць цыклам з постумовай, бо праверка ўмовы ажыццяўляецца пасля выканання цела цыкла. Выкарыстоўваць цыкл do...while лепш у тых выпадках, калі каманды ў целе цыкла павінны выканацца хоць бы адзін раз або калі ўнутры цела цыкла адбываецца ініцыялізацыя пераменных, якія ўдзельнічаюць у праверцы ўмовы заканчэння яго работы.

Фігурныя дужкі ў запісе цыкла з постумовай могуць быць апушчаны, калі цела цыкла складаецца з адной каманды.

Прыклад 5.2. Напісаць праграму, якая будзе генерыраваць выпадковыя лікі з прамежку [1; x] да таго часу, пакуль не будзе згенерыраваны лік, кратны k. Вывесці гэты лік і колькасць згенерыраваных лікаў. Значэнні k і x уводзяцца (k < x).

Этапы выканання задання

I. Зыходныя даныя: лікі k і r.

II. Вынік: r (шуканы лік) і n (колькасць лікаў).

III. Алгарытм рашэння задачы.

1. Увод зыходных значэнняў.
2. Ініцыялізацыя лічыльніка 
n = 0.
3.Паколькі нам вядома ўмова заканчэння цыкла — атрымаць лік, кратны k, то будзем выкарыстоўваць цыкл з постумовай. Умову можна запісаць так
: (r % k). Если значение этого выражения не равно нулю, то условие истинно. Калі значэнне гэтага выразу не роўна нулю, то ўмова праўдзівая.

3.1. Генерыруем выпадковы лік r. У С++ для гэтага выкарыстоўваецца функцыя rand(), якая генерыруе выпадковы лік у прамежку [0; 32767). Гэты лік будзе выкарыстоўвацца ва ўмове праверкі заканчэння работы цыкла.
3.2. Каб выпадковы лік трапіў у прамежак [1; x], знойдзем астачу ад дзялення на x ліку, які згенерыраваны функцыяй rand(), і прыбавім да яго 1.
3.3. Павялічым значэнне лічыльніка на 1.

4. Вывад выніку.

IV. Апісанне пераменных: n, k, x — int.

Лікі, згенерыраваныя функцыяй rand(), называюць псеўдавыпадковымі, паколькі пры кожным запуску праграмы будзе згенерыравана адна і тая ж паслядоўнасць лікаў. Кожны новы лік у паслядоўнасці генерыруецца па пэўным алгарытме з папярэдняга. Першы лік у гэтай паслядоўнасці — канстанта, вядомая кампілятару. Такі падыход зручны для адладкі праграмы. Аднак для атрымання вынікаў неабходна пры кожным запуску атрымліваць іншыя лікі. Функцыя srand(n) з бібліятэкі cstdlib дазваляе змяніць першы лік у паслядоўнасці ў залежнасці ад значэння параметра n. Аднак, калі значэнне n з’яўляецца канстантай, то паслядоўнасць лікаў зменіцца ў адносінах да пачатковай, але не будзе змяняцца пры новых запусках праграмы. Калі ў якасці значэння n узяць сістэмны час (функцыя time(NULL)з бібліятэкі ctime), то пры кожным запуску праграмы будзем атрымліваць новую паслядоўнасць выпадковых лікаў.

Прыклад 5.2.

V. Праграма:

#include <iostream>

#include <cstdlib>

#include <ctime>

 

using namespace std;

 

int main()

{

  srand(time(NULL));

  int x, k;

  cout << "vvedi x, k" << endl;

  cin >> x >> k;

  int r, n = 0;

  do {

    r = rand() % x + 1;

    n++;

  }

  while (% k);

  cout << "r = " << r << endl;

  cout << "chisel - " << n << endl;

  return 0;

}

VI. Тэсціраванне.

VII. Паколькі лікі генерыруюцца выпадкова, то для адных і тых жа зыходных даных могуць атрымлівацца розныя вынікі (тэсты 2—4).

5.3 Аператар цыкла з параметрам

Для запісу аператара цыкла з параметрам выкарыстоўваецца каманда for. Фармат каманды:

for (<Блок1>; <Блок2>; <Блок3>){
  цела цыкла;
}

Для арганізацыі работы такога цыкла неабходна апісаць тры аперацыі:

  • ініцыялізацыя (блок1) — прысвойванне пачатковых значэнняў пераменным, якія змяняюцца ў цыкле. Калі такіх каманд некалькі, то яны пералічваюцца праз коску;
  • умова (блок2) — праверка ўмовы паўтору цыкла. Умова можа быць простай і састаўной. У блок можа ўваходзіць некалькі ўмоў, пералічаных праз коску. У гэтым выпадку цыкл выконваецца да таго часу, пакуль хоць бы адна з умоў праўдзівая;
  • мадыфікацыя (блок3) — дзеянні, якія выконваюцца ў канцы кожнай ітэрацыі (праходу цыклу).

Калі ў целе цыкла for павінен выканацца адзін аператар, тады фігурныя дужкі можна прапусціць.

У запісе цыкла for можна прапусціць адзін ці некалькі блокаў, але нельга прапускаць кропку з коскай, якая падзяляе тры складальнікі цыкла (прыклад 5.3).

Найбольш распаўсюджаны прыватны выпадак запісу цыкла for, блізкі да запісу аналагічнага цыкла на мове Pascal:

for (лічыльнік = значэнне;
     лічыльнік значэнне;
     крок цыкла) {
    цела цыкла;
}

Лічыльнік цыкла (параметр цыкла) — пераменная, у якой захоўваецца колькасць праходаў дадзенага цыкла. У адрозненне ад Pascal параметр цыкла можа быць рэчыўным і змяняцца з любым значэннем кроку цыкла (прыклад 5.4).

Пераменныя, вызначаныя ў загалоўку цыкла for ці ў яго целе, маюць спецыяльны тып вобласці бачнасці: вобласць бачнасці цыкла. Такія пераменныя існуюць толькі ўнутры цыкла і недаступныя за яго межамі.

Прыклад 5.5. Напісаць праграму для вываду табліцы множання на зададзены лік x.

Этапы выканання задання

I. Зыходныя даныя:  (уведзены лік).

II. Вынік: 9 радкоў выгляду .

III. Алгарытм рашэння задачы.

  1. Увод зыходных значэнняў.
  2. Значэнне пераменнай a змяняецца ў цыкле ад 1 да 9.
  3. Значэнне пераменнай c = a × x.
  4. Паколькі колькасць паўтарэнняў загадзя вядомая, выкарыстаем цыкл for.
  5. Вывад значэнняў ажыццяўляецца ў цыкле.
  6. Апісанне пераменных: x, a, c – int.

Прыклад 5.6. Напісаць праграму, якая выведзе ўсе двухзначныя лікі ў выглядзе табліцы так, каб у кожным радку гэтай табліцы размяшчаліся лікі аднаго дзясятка.

Этапы выканання задання

I. Вынік праграмы не залежыць ад зыходных даных.

II. Табліца з лікамі.

III. Алгарытм рашэння задачы.

  1. Для вываду такой табліцы можна выкарыстоўваць два ўкладзеныя цыклы. Першы будзе вызначаць колькасць дзясяткаў у ліку, а другі — колькасць адзінак.
  2. Вывад значэнняў ажыццяўляецца ў цыкле.
  3. Пасля завяршэння вываду аднаго радка табліцы неабходна перавесці курсор на новы радок.
  4. Апісанне пераменных: i, j – int.
Усе цыклы, якія ёсць у С++, узаемазаменныя. Выбар таго ці іншага цыкла часта вызначаецца тым, які з цыклаў прасцей і хутчэй дазволіць рашыць пастаўленую задачу.

Прыклад 5.3. Розныя варыянты запісу загалоўка цыкла for:

for (int i = 0; i < n;)

for (; i * i < n; i++)

for (; ; )

for (int i = 0, j = 1;

         i < 10, j < 30;

         i++, j += 2)

Калі блок праверкі ўмовы пакінуць пустым, то ўмова заўсёды будзе лічыцца праўдзівай і цыкл будзе выконвацца бясконца. Таму ён павінен будзе быць перапынены якім-небудзь іншым спосабам.

У апошнім прыкладзе ў загалоўку цыкла абвешчаны дзве пераменныя, якія па-рознаму змяняюць свае значэнні на кожнай ітэрацыі цыкла. Апошні раз цыкл выканаецца для значэнняў   i = 14, j = 29  .

Прыклад 5.4. Розныя варыянты запісу загалоўка цыкла for з параметрам:

for (int i = 0; i < n; i++)

for (int i = n; i < 0; i--)

for (int k = 1< m; i += 2)

for (int j = 1; j < m; i *= 3)

for (double h = 0.1; h <= 1; h += 0.01)

У загалоўку цыкла прысутнічае блок3, у які можна ўпісваць дзеянні, што праходзяць на кожнай ітэрацыі. Таму ў некаторых выпадках цыкл for можа быць запісаны без каманд цела цыкла. У якасці прыкладу разгледзім некалькі варыянтаў вылічэння сумы першых 10 натуральных лікаў.

Варыянт 1

int s = 0;
for (int i = 1; i < 11; i++)
  s += i;

Варыянт 2

int s, i;
for (= 0, i = 1; i <= 11; 
     s += i, i++);

Варыянт 3

for (int s = 0, i = 1;
       i <= 11; s += i, i++);

У першых двух варыянтах, калі пасля цыкла запісаць каманду

   cout << s;  

атрымаем значэнне s = 55

 Паколькі каманды, змешчаныя ў блоку3, выконваюцца пасля выканання цела цыкла, то ў другім варыянце неабходна лішняя ітэрацыя.

У трэцім варыянце вывесці значэнне пераменнай s не атрымаецца, паколькі яе вобласць бачнасці абмежавана цыклам і яе значэнне за межамі цыкла недаступна.

Прыклад 5.5.

I. Праграма:

#include <iostream>

 

using namespace std;

 

int main()

{

  int x;

  cout << "x = ";

  cin >> x;

  for (int a = 1; a < 10; a++) {

    int c = a * x;

    cout << a << " * " << x;

    cout << " = " << c << endl;

  }

  return 0;

}

II. Тэсціраванне.

Прыклад 5.6.

V. Праграма:

#include <iostream>

 

using namespace std;

 

int main()

{

for (int i = 1; i < 10; i++) {

  for (int j = 0; j < 10; j++)

    cout << i * 10 + j << " ";

    cout << endl;

  }

  return 0;

}

 VI.  Тэсціраванне.

5.4. Аператары break і continue

Дастаткова часта пры выкарыстанні цыклаў і амаль заўсёды пры выкарыстанні аператара switch узнікае неабходнасць перапыніць выкананне цела цыкла ці каманды множнага выбару. Для гэтага выкарыстоўваецца каманда break. Выкарыстанне break для перарывання каманды switch разглядалася ў § 4.

Калі аператар break сустракаецца ў целе цыкла, то цыкл спыняе сваю работу, а праграма працягвае выконвацца з радка, наступнага за цыклам.

Прыклад 5.7. Напісаць праграму, якая выведзе толькі тыя лікі табліцы з прыкладу 5.6, якія знаходзяцца не вышэй за галоўную дыяганаль [1].

Этапы выканання задання

I. Вынік праграмы не залежыць ад зыходных даных.

II. Табліца з лікамі.

III. Алгарытм рашэння задачы.

1. Для вываду такой табліцы можна выкарыстоўваць два ўкладзеныя цыклы. Першы будзе вызначаць дзясяткі ліку, а другі — адзінкі. 
2. Другі цыкл будзем перарываць з дапамогай каманды break, калі колькасць адзінак роўна колькасці дзясяткаў. 
3. Вывад значэнняў ажыццяўляецца ў цыкле.
4. Пасля завяршэння вываду аднаго радка табліцы неабходна перавесці курсор на новы радок.

IV. Апісанне пераменных: i, j – int.

Аператар continue дазваляе прапусціць частку аператараў цела цыкла, якія стаяць пасля яго, і пачаць новую ітэрацыю. Гэта можна выкарыстоўваць у тых выпадках, калі трэба завяршыць бягучую ітэрацыю загадзя.

Прыклад 5.8. Напісаць праграму, якая выведзе ўсе лікі табліцы з прыкладу 5.6, выключаючы лікі, якія заканчваюцца на 5 ці 7.

Этапы выканання задання

I. Вынік праграмы не залежыць ад зыходных даных.

II. Табліца з лікамі.

III. Алгарытм рашэння задачы.

1. Для вываду такой табліцы можна выкарыстоўваць два ўкладзеныя цыклы. Першы будзе вызначаць дзясяткі ліку, а другі — адзінкі.
2. Калі значэнне параметру другога цыкла роўна 5 ці 7, то будзем прапускаць каманды вываду
.
3. Вывад значэнняў ажыццяўляецца ў цыкле
.
4. Пасля завяршэння вываду аднаго радка табліцы неабходна перавесці курсор на новы радок.

IV. Апісанне пераменных: i, j – int.


[1] Галоўная дыяганаль у табліцы лікаў (матрыцы) — усе такія лікі, у якіх нумар радка роўны нумару слупка. Нумарацыя пачынаецца з верхняга левага вугла..

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

do {

  cin >> n;

  if (> 9 && n < 100)

    break;

  else {

    cout << "Число не двузначное! ";

    cout << "Введите двузначное" << endl;

  }

}

while (true);

Пример 5.7.

V. Программа:

#include <iostream>

 

using namespace std;

 

int main()

{

  for (int i = 1; i < 10; i++) {

    for (int j = 0; j < 10; j++){

      if (>= i) break;

      cout << i * 10 + j << " ";

    }

    cout << endl;

  }

  return 0;

}


   VI. Тестирование.

    Многие программисты считают, что операторы break и continue нарушают структурность программного кода, и предпочитают обходится без них. Эти операторы всегда можно заменить операторами, которые относятся к основным алгоритмическим конструкциям. Однако разумное использование операторов break и continue может улучшить понятность циклов в программе.

    При вложенных циклах действия операторов break и continue распространяется только на тот цикл, в котором они содержатся.

    Пример 5.8.

    V. Программа:

    #include <iostream>

     

    using namespace std;

     

    int main()

    {

      for (int i = 1; i < 10; i++) {

        for (int j = 0; j < 10; j++){

          if (== 5 || j == 7)

            continue;

          cout << i * 10 + j << " ";

        }

        cout << endl;

      }

      return 0;

    }

     VI. Тестирование.

    5.5. Рашэнне задач з выкарыстаннем аператара цыкла

    У дадзеным пункце разгледзім магчымасць ужывання ўсіх трох відаў цыклаў для рашэння адной задачы.

    Прыклад 5.9. Вывесці на экран найбольшы натуральны лік з прамежку [n, m], які дзеліцца на зададзены лік x, ці паведамленне «няма такіх лікаў».».

    Этапы выканання задання

    I. Зыходныя даныя: n, m (межы прамежку), x (зададзены лік).

    II. Вынік: шуканы лік або паведамленне «няма такіх лікаў».

    III. Алгарытм рашэння задачы.

    1. Няхай i — бягучы лік з прамежку.
    2. Паколькі нас цікавіць найбольшы лік з прамежку, то прагляд лікаў пачнём са значэння i = m. На кожным кроку будзем памяншаць i на 1
    .
    3. Цыкл завершыцца, калі мы знайшлі лік, які дзеліцца на x без астачы (астача роўна нулю), ці прагледзелі ўсе лікі з прамежку 
     [n, m].
    4. Для рашэння з цыклам while — калі пасля заканчэння цыкла i = n – 1, то няма лікаў, якія задавальняюць умову задачы
    .
    5. Для рашэння з цыклам 
    do…while — калі пасля заканчэння цыкла i = n – 1, то няма лікаў, якія задавальняюць умову задачы. Паколькі памяншэнне значэння i адбываецца да праверкі ўмовы, то пачатковае значэнне i = m + 1.
    6. Для рашэння з цыклам for — калі лік знойдзены, выкарыстаем каманду break і перарвём выкананне цыкла. Значэнне знойдзенага ліку захаваем у пераменнай z, якой да пачатку работы цыкла прысвоім значэнне –1. Калі пасля заканчэння цыкла z засталося роўным –1, то лікі, якія задавальняюць умову задачы, не знойдзены
    .

    IV. Апісанне пераменных: n, m, x, i, z – int.

    Прыклад 5.9.

    V. Праграма (з цыклам  while):

    #include <iostream>

     

    using namespace std;

     

    int main()

    {

      int n, m, x;

      cout << "granicy" << endl;

      cin >> n >> m;

      cout << "x = ";

      cin >> x;

      ///while

      int i = m;

      while (>= n && i % x)

        i--;

      if (== n - 1)

        cout << "net takih" << endl;

      else

        cout << "naideno - " << i << endl;

      return 0;

    }

    Фрагмент рашэння з цыклам do…while:

      ///do...while

      int i = m + 1;

      do

        i--;

      while (>= n && i % x);

      if (== n - 1)

        cout << "net takih" << endl;

      else

        cout << "naideno - " << i << endl;

    Фрагмент рашэння з цыклам for:

    ///for

      int z = -1;

      for (int i = m; i >= n; i--)

        if  (% x == 0) {

          z = i;

          break;

        }

      if (== - 1)

        cout << "net takih" << endl;

      else

        cout << "naideno - " << z << endl;

    VI. Тэсціраванне.

    Пытанні к параграфу

    1. Што такое аператар цыкла?

    2. Якім чынам можна кіраваць колькасцю выкананняў цела цыкла?

    3. Як запісваецца аператар цыкла з перадумовай?

    4. Як запісваецца аператар цыкла з постумовай?

    5. Як запісваецца аператар цыкла з параметрам?

    6. Для чаго прызначаны аператар  break?

    7. У якіх выпадках можна выкарыстоўваць аператар continue?

    Практыкаванні

        

    1. Перапішыце праграмы з прыкладаў 5.1, 5.2, 5.5–5.8, выкарыстоўваючы іншыя цыклы. Прааналізуйце, калі выкарыстанне іншага цыкла менш эфектыўнае.

    2. Выканайце заданні для прыкладу 5.1.

    1. Каманды

                       i. cout << "v chisle " << k; 

      ii. cout << " cifr" << endl;

    замянілі камандамі

              iii. cout << "v chisle " << n; 

        iv. cout << k << " cifr" << endl;

    Які вынік будзе атрыманы і чаму? Якія змяненні трэба ўнесці ў праграму для атрымання правільнага выніку?

    2. Ці зменіцца вынік работы праграмы, калі замест умовы цыкла n > 0 выкарыстоўваць умову  n > 1?
    3. Праверце работу праграмы для n = 0. Чаму атрымаўся такі вынік? Што трэба змяніць у праграме для атрымання правільнага выніку?

    3. Унясіце змяненні ў праграму прыкладу 5.5. Карыстальнік задае значэнне другога множніка, а таксама пачатковае і канцавое значэнні першага множніка.

    4. Задачу з прыкладу 5.7 можна рашыць без выкарыстання каманды break. Для гэтага трэба змяніць умову цыкла. Напішыце праграму, якая рашыць задачу такім спосабам.

    5. У магазіне прадаюць цукеркі ва ўпакоўках па 0.1 кг, 0.2 кг, … 0.9 кг, 1 кг. Вядома, што 1 кг цукерак каштуе х рублёў. Выведзіце кошт кожнай упакоўкі ў выглядзе:

    0.1 кг цукерак каштуе … р.;
    0.2 кг цукерак каштуе … р. …

    6. Напісаць праграму, якая выведзе толькі тыя няцотныя лікі табліцы з прыкладу 5.6, якія знаходзяцца ніжэй за галоўную дыяганаль.

    7. Выведзіце на экран найменшы натуральны лік з прамежку [n, m], кякі з’яўляецца няцотным і падзяляецца на ўведзенае значэнне x.