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

§ 5. Оператор цикла

Сайт: Профильное обучение
Курс: Информатика. 10 класс (Повышенный уровень)
Книга: § 5. Оператор цикла
Напечатано:: Гость
Дата: Суббота, 4 Май 2024, 04:18

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. Исходные данные: x (введенное число).

II. Результат: 9 строк вида straight a space asterisk times space straight x space equals space straight c.

III. Алгоритм решения задачи.

1. Ввод исходных значений.
2. 
Значение переменной a изменяется в цикле от 1 до 9.
3.
Значение переменной c = a × x.
4. 
Так как количество повторений заранее известно, используем цикл for.
5. Вывод значений осуществляется в цикле.

VI. Описание переменных: x, a, c – int.

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

Этапы выполнения задания

I. Результат программы не зависит от исходных данных.

II. Таблица с числами.

III. Алгоритм решения задачи.

1. Для вывода такой таблицы можно использовать два вложенных цикла. Первый будет определять количество десятков в числе, а второй — количество единиц.
2. 
Вывод значений осуществляется в цикле.
3. 
После завершения вывода одной строки таблицы необходимо перевести курсор на новую строку.

IV. Описание переменных: 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)

Если блок проверки условия оставить пустым, то условие всегда будет считаться истинным, и цикл будет выполняться бесконечно. Поэтому он должен будет прерван каким-либо другим способом.

В последнем примере в заголовке цикла объявлены две переменные, которые по-разному меняют свои значения на каждой итерации цикла. Последний раз цикл выполнится для значений    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<= 11; s += i, i++);

Вариант 3

for (int s = 0, i = 1;

       i <= 11; s += i, i++);

В первых двух вариантах, если после цикла записать команду    cout << s;     получим значение =  55.

Поскольку команды, находящиеся в блоке3, выполняются после выполнения тела цикла, то во втором варианте необходима лишняя итерация.

В третьем варианте вывести значение переменной s не получится, поскольку ее область видимости ограничена циклом и ее значение за пределами цикла недоступно.

Пример 5.5.

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

#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;

}

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

Пример 5.6.

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

#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.