Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабы 1 курс 2 семестр / ЛР 4 Информатика 2 сем 2020

.pdf
Скачиваний:
11
Добавлен:
15.01.2021
Размер:
823.24 Кб
Скачать

5Лабораторная работа №4. Управляющие конструкции. Циклы.

5.1Цели и задачи работы:

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

Задача данной лабораторной работы — выполнить выданные типовые задания, алгоритм решения которых содержит повторы.

5.2Теоретическая часть

Втех случаях, когда необходимо выполнить один блок программного кода несколько раз, нужно использовать циклы. Наиболее простой по конструкции цикл «while» имеет следующий вид:

while( выражение )

{

// блок программного кода

}

Сначала вычисляется выражение в круглых скобках - условие цикла. Если оно имеет значение true, выполняется программный код в теле цикла, после чего условие проверяется повторно. Цикл работает до тех пор, пока значением этого выражения не станет false. Если значение выражения изначально false, то программный код в теле цикла не выполняется.

Пример использования цикла «while»: предположим, число, которое ввѐл пользователь, нужно удваивать до тех пор, пока оно не станет 1000 или больше. Тогда в программе можно написать:

std::cout<<"Input number:";

std::cin>>number;

while(number < 1000);

{

number *= 2;

}

62

Если нужно, что бы программный код в теле цикла выполнился хотя бы один раз в любом случае, следует использовать цикл «do-while»:

do

{

// блок программного кода }while(выражение);

Пример использования цикла «do-while»: предположим, нужно, что бы пользователь обязательно ввѐл число из диапазона от 20 до 40. Тогда в программе можно написать:

int number;

do

{

std::cout<<"Input number from 20 to 40:"; std::cin>>number;

}

while(number < 20 || number > 40);

В тех случаях, когда заранее известно, сколько итераций (проходов) цикл должен выполнить, удобно использовать конструкцию цикла «for».

for( выражение 1 ; выражение 2 ; выражение 3 )

{

// тело цикла

}

Цикл «for» работает следующим образом:

-выражение 1 вычисляется один раз перед началом цикла - обычно здесь объявляют переменную, служащую счѐтчиком итераций цикла;

-выражение 2 вычисляется перед каждой итерацией цикла, если его значение true – далее выполняется тело цикла, если false – выполнение цикла прекращается (аналогично, как в цикле «while»).

-выражение 3 вычисляется после каждой итерации цикла, обычно здесь происходит увеличение счѐтчика цикла.

Одно или несколько выражений могут быть опущены.

63

Пример использования цикла «for»: нужно возвести число a в целую неотрицательную степень b. Тогда в программе можно написать:

...

// Переменные a и b инициализированы где-то выше

int result = 1; // В переменную result будет записан результат вычислений

for (int i=0; i < b; i++) // i - служебная переменная –

«счётчик цикла»

{

result *= a;

}

В циклах «for», «while», «do-while» можно использовать инструкцию «break» для останова их выполнения (аналогично, как в конструкции switchcase). Выполнение программы продолжается с инструкции, следующей за закрывающей фигурной скобкой цикла.

Если нужно завершить выполнение только текущей итерации (прохождения) цикла, а не всего цикла, можно воспользоваться инструкцией «continue». Инструкция «continue» завершает текущую итерацию цикла и передает управление на вычисление условия, после чего цикл может продолжиться.

Для общих сведений, рассмотрим ещѐ оператор безусловного перехода goto. Он осуществляет передачу управления оператору, метка которого задана идентификатором.

goto mark; // mark - имя метки, на которую нужно перейти

...

// этот код выполнен не будет

...

mark: // метка

Метка, на которую нужно осуществить переход может располагаться как ниже, так и выше оператора goto. В последнем случае по сути может получиться конструкция подобная циклу. Поэтому оператор goto и рассмотрен в этом разделе наряду с конструкциями циклов.

mark: // метка

...

// этот код будет выполняться постоянно,

64

// может произойти зацикливание

...

goto mark; // mark - имя метки, на которую нужно перейти

Оператор goto использовать не рекомендуется, поскольку проверять такой программный код на ошибки в большинстве ситуаций будет затруднительно, как программе-отладчику так и человеку-программисту. Например, зацикливание в вышеприведѐнном примере отладчик не отследит.

Другой пример с возможным возникновением ошибки, которую не отследит отладчик:

int a; goto next; a = 5;

next:

printf("%i", a); // значение переменной a неизвестно, // она не инициализирована

Один из немногих примеров программного кода на языке «Си», где использование оператора goto может быть более-менее оправдано - организация выхода из нескольких вложенных циклов.

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

{

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

{

//Здесь может быть несколько вложенных циклов

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

{

//Некое условие, по выполнению которого

// нужно выйти изо всех циклов разом if ( ... ) {goto stop;}

}

}

}

stop: // метка

std::cout<< "Условие выполнено";

При отказе от оператора goto, нужно ввести дополнительную переменную и проверять еѐ значение в каждом из вложенных циклов, что делает код программы менее читабельным.

65

bool stop = false; // Служебная переменная (флаг)

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

{

// Дополнительная проверка в условии цикла for (int j = 0; j < 10 && stop; j++ )

{

// Здесь может быть несколько вложенных циклов

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

{

//Некое условие, по выполнению которого

//нужно выйти изо всех циклов разом

if ( ... )

{

stop = true; // Обозначаем, что нужно выходить из циклов

break;

}

}

}

// Дополнительная проверка в конце цикла if(stop){break;}

}

if(stop)

{

std::cout<< "Условие выполнено";

}

Также есть вариант – поместить вложенные циклы в отдельную функцию (что не всегда удобно) и воспользоваться оператором return для их прекращения. Создание функций и использование оператора return будет рассмотрено при выполнении следующих лабораторных работ.

Язык C++ поддерживает использование оператора goto в целях совместимости, но рекомендуется вместо него использовать более совершенные конструкции. Например, в вышеприведѐнном случае выход из нескольких вложенных циклов можно реализовать при помощи конструкции

«try-throw-catch».

66

5.3Примеры решения задач

Задача А. Вывести на экран первые 1000 чѐтных натуральных чисел

Решение

Составим блок-схему программы. Входных данных не предполагается, поэтому блок «Данные» будем использовать исключительно для вывода нужных чисел на экран. Прописывать все 1000 чисел не рационально, программа должна самостоятельно поочерѐдно определять их и выводить на экран. Значит, алгоритм программы будет содержать цикл, на каждой итерации (прохождении) которого будет определяться и выводиться на экран следующее число.

Начало

Целое неотрицательное число i = 1

да

нет

 

i <= 1000

Вывод i * 2

 

i++

Конец

Напишем программу на основе полученой блок-схемы. Для реалицации цикла воспользуемся конструкцией «for», поскольку количество необходимых итераций цикла (1000) нам известно заранее.

#include <conio.h> #include <iostream>

void main()

{

for(unsigned int i = 1; i <= 1000; i++)

{

std::cout<< i * 2 << "\t";

}

std::cout<<"\nPress any key to continue"; _getch();

67

}

Тесты:

Запустив программу, видим в консольном окне подряд идущие чѐтные числа, начиная с 2 и заканчивая 2000, что и требовалось вывести по заданию.

Задача Б Вычислить факториал введѐнного целого неотрицательного числа.

Решение

Составим блок-схему программы. Для вычисления факториала заданного числа будем последовательно перемножать целые числа попорядку начиная с 2 (факториал нуля равен 1, это особая ситуация на ноль не умножаем, на 1 умножать смысла также не имеет) пока не доберѐмся до заданного числа. Для определения следующего числа и домножения на него результата предыдущих вычислений включим в блок-схему алгоритма цикл.

 

Начало

Целое неотрицательное число x

 

Ввод x

Целое неотрицательное число f = 1

Целое неотрицательное число i = 2

да

нет

 

i <= x

f *= i++

Вывод f

 

Конец

На основе полученой блок-схемы составим программу. Для реализации цикла воспользуемя конструкцией «while» (можно так же воспользоваться и конструкцией «for», этот вариант не лучше и не хуже).

#include <conio.h> #include <iostream>

68

void main()

{

std::cout<<"Input x:"; unsigned int x; std::cin>>x;

unsigned int f = 1; unsigned int i = 2;

while(i <= x)

{

f *= i++;

}

std::cout<< "f(" << x << ") = " << f << "\nPress any key to continue"; _getch();

}

Тесты:

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

x

0

1

2

3

4

7

8

10

x!

1

1

2

6

24

5040

40320

3628800

Полученные результаты соответствуют действительности, значит, можно предположить, что программа работает верно.

Задача В. Ввести с клавиатуры натуральное число N. Вычислить

N

x

S

i

 

i 1

1 y

i

где: x1 = 1;

 

y1 = 1;

 

xi+1 = xi / 2;

 

yi+1 = yi + 1.5;

 

i = 1, 2 , … N.

 

Решение

 

Составим блок-схему программы. Для добавления очередного слагаемого к ранее посчитанному результату и определения следующих значений x и y нужно задать цикл.

69

Начало

Целое неотрицательное число N

Ввод N

Число с плавающей точкой x = 1 Число с плавающей точкой y = 1 Число с плавающей точкой sum = 0 Целое неотрицательное число i = 1

да

нет

 

i <= N

sum += x / (1 + y) x /= 2 y += 1.5 i++

Вывод sum

Конец

На основе полученой блок-схемы составим программу.

#include <conio.h> #include <iostream>

void main()

{

unsigned int N; std::cout<<"vvedite N:"; std::cin>>N;

float x = 1; float y = 1; float sum = 0;

for(unsigned int i = 1; i <= N; i++)

{

sum += x / (1 + y); x *= 0.5;

70

y += x;

}

std::cout<<"\nresultat: "<< sum << "\nPress any key to continue";

_getch();

}

Тесты:

Протестируем написанную программу, запустив еѐ несколько раз, и вводя различные значения N. Результаты работы программы для разных значений N, приведены в таблице ниже (с округлением до тысячных).

N

1

2

3

4

5

0.5

0.7

0.791

0.834

0.856

 

 

 

 

 

 

Полученные результаты соответствуют действительности, можно предположить, что программа работает верно.

Задача Г. Среди N введѐнных целых чисел найти количество соседств двух положительных чисел.

Решение

Составим блок-схему алгоритма решения задачи. Заранее неизвестно, сколько всего чисел будет введено, поэтому блок-схема алгоритма должна содержать цикл, на каждой итерации которого будет вводиться следующее число. Если это число положительно и предыдуще число положительно, нужно посчитать это «соседство». Для подсчѐта количества соседств положительных чисел нужно ввести вспомогательную переменную. Так же нужно ввести вспомогательную переменную для временного хранения предыдущего введѐнного числа. Чтобы на первой итерации цикла уже можно было проверить два соседних числа на положительность, первое число нужно ввести заранее, до начала цикла.

71