Алгоритмизация. Введение в язык программирования C++

Реализация циклического алгоритма

Показывать лекцию целиком

В данной лекции мы рассмотрим множество задач, соответствующих циклическому алгоритму. В каждой задаче будут представлены блок-схемы, коды программ для Microsoft Visual Studio, а также результаты выполнения программ (консоли).

Занятие 1. Программная реализация циклического алгоритма

Пример 1. Вычислить таблицу "$$x, f$$" значений функции $$f(x)=2x+1$$ при $$0\le х\le 4$$ с шагом 2,5.

Решение. Т.к. переменная х имеет не одно, а несколько значений (а именно 0; 2,5), то следует использовать циклический алгоритм. Решим данную задачу несколькими способами: блок-схема с предусловием, блок-схема с постусловием, программа с оператором while (соответствует блок-схеме с предусловием), программа с оператором for (соответствует блок-схеме с предусловием), программа с оператором do while (соответствует блок-схеме с постусловием).

В данной задаче мы имеем:

  • $$х$$ – переменная цикла, т.к. $$х$$ изменяется согласно условиям задачи;
  • $$х=0$$ – первоначальное значение переменной цикла $$х$$;
  • $$h=2,5$$ – шаг изменения переменной цикла $$х$$;
  • "$$x\le 4$$" - условие выполнения итерации цикла.
  • В теле цикла мы будем считать значение функции $$f$$ и выводить строку со значениями $$x, f$$ на экран.

    В программе мы будем использовать функцию setw(10) из библиотеки <iomanip>, чтобы таблица значений строилась ровно.

    Блок-схема с предусловием представлена на рис. 5.1.

    (рис 5.1) Блок-схема с предусловием для примера 1

    Выполнение блок-схемы:

    Начало
    вывод заголовка таблицы "x, f"
    x=0
    x≤4   0≤4   да
    f=2x+1=2*0+1=1
    вывод x, f
    Экран
    x	f
    0	1
    x=x+2,5=0+2,5=2,5
    наверх
    x≤4   2,5≤4   да
    f=2x+1=2*2,5+1=6
    вывод x, f
    Экран
    x	f
    0	1
    2,5	6
    x=x+2,5=2,5+2,5=5
    наверх
    x≤4   5≤4   нет
    выход из цикла по х
    Конец.

    Код программы с оператором while:

    // proga23while.cpp: определяет точку входа для консольного приложения.
    //
    #include "stdafx.h"
    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main()
    {
    	double x, f;
    	cout<<setw(10)<<"x"<<setw(10)<<"f"<<endl;
    	x=0;
    	while(x<=4){
    		f=2.0*x+1.0;
    		cout<<setw(10)<<x<<setw(10)<<f<<endl;
    		x=x+2.5;
    	}
    	return 0;}

    Код программы с оператором for:

    // proga23for.cpp: определяет точку входа для консольного приложения.
    //
    #include "stdafx.h"
    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main()
    {	
    	double x, f;
    	cout<<setw(10)<<"x"<<setw(10)<<"f"<<endl;
    	for(x=0; x<=4; x=x+2.5){
    		f=2.0*x+1.0;
    		cout<<setw(10)<<x<<setw(10)<<f<<endl;
    	}
    	return 0;}

    Блок-схема с постусловием представлена на рис. 5.2.

    (рис 5.2) Блок-схема с постусловием для примера 1

    Выполнение блок-схемы:

    Начало
    x=0
    f=2x+1=2*0+1=1
    вывод x, f
    Экран
    x	f
    0	1
    x=x+2,5=0+2,5=2,5
    x≤4   2,5≤4   да
    наверх
    f=2x+1=2*2,5+1=6
    вывод x, f
    Экран
    x	f
    0	1
    2,5	6
    x=x+2,5=2,5+2,5=5
    x≤4   5≤4   нет
    выход из цикла по х
    Конец.

    Код программы с оператором do while:

    // proga23dowhile.cpp: определяет точку входа для консольного приложения.
    //
    #include "stdafx.h"
    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main()
    {	
    	double x, f;
    	cout<<setw(10)<<"x"<<setw(10)<<"f"<<endl;
    	x=0;
    	do{
    		f=2.0*x+1.0;
    		cout<<setw(10)<<x<<setw(10)<<f<<endl;
    		x=x+2.5;
    	}while(x<=4);
    	return 0;
    }

    Результат выполнения программ с операторами while, for, do while:

    Ручной счет:

    Диапазон значений х: 0; 2,5.
    при x=0		f=2x+1=2*0+1=1
    при x=2,5	f=2x+1=2*2,5+1=6

    Пример 2. Вычислить таблицу "$$x, Z$$" значений функции $$Z(x,y)=\begin{cases}x+3,x<1\\4x,x\ge 1\end{cases}$$при $$-1\le х\le 2$$ с шагом 1.

    Решение. Функция $$Z$$ является кусочной, поэтому для ее расчета используем разветвляющийся алгоритм.

    Необходимо добавить реализацию одномерного цикла по переменной $$х$$.

    В данной задаче:

  • $$х=-1$$ – начальное задание переменной цикла;
  • $$h=1$$ – шаг изменения переменной цикла $$х$$;
  • "$$х\le 2$$" - условие для прохождения итерации цикла.
  • В теле цикла следует рассчитать значение функции $$Z$$ и вывести очередную строку значений $$x, Z$$ таблицы на экран.

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

    Приведем две блок-схемы: с предусловием и с постусловием.

    К блок-схеме с предусловием относятся две программы – с оператором while и for.

    К блок-схеме с постусловием относится одна программа с оператором do while.

    Блок-схема с предусловием приведена на рис. 5.3.

    (рис 5.3) Блок-схема с предусловием для примера 2

    Код программы с оператором while:

    // proga24while.cpp: определяет точку входа для консольного приложения.
    //
    #include "stdafx.h"
    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main(){
    	double x, Z;
    	cout<<setw(10)<<"x"<<setw(10)<<"Z"<<endl;
    	x=-1.0;
    	while(x<=2.0){
    		if(x<1){
    			Z=x+3;
    		}
    		else {
    			Z=4*x;
    		}
    		cout<<setw(10)<<x<<setw(10)<<Z<<endl;
    		x=x+1.0;
    	}
    	return 0;}

    Код программы с оператором for:

    // proga24for.cpp: определяет точку входа для консольного приложения.
    //
    #include "stdafx.h"
    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main(){
    	double x, Z;
    	cout<<setw(10)<<"x"<<setw(10)<<"Z"<<endl;
    	for(x=-1; x<=2; x=x+1){
    		if(x<1){
    			Z=x+3;
    		}
    		else {
    			Z=4*x;
    		}
    		cout<<setw(10)<<x<<setw(10)<<Z<<endl;
    	}
    	return 0;}

    Блок-схема с постусловием представлена на рис. 5.4.

    (рис 5.4) Блок-схема с постусловием для примера 2

    Код программы с оператором do while:

    // proga24dowhile.cpp: определяет точку входа для консольного приложения.
    //
    #include "stdafx.h"
    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main(){
    	double x, Z;
    	cout<<setw(10)<<"x"<<setw(10)<<"Z"<<endl;
    	x=-1;
    	do{
    		if(x<1){
    			Z=x+3;
    		}
    		else {
    			Z=4*x;
    		}
    		cout<<setw(10)<<x<<setw(10)<<Z<<endl;
    		x=x+1;
    	}while(x<2);
    	return 0;}

    Результат выполнения программ с операторами while, for, do while:

    Ручной счет:

    Диапазон значений х: -1; 0; 1; 2.
    при x=-1	Z={по первой ветви}=x+3=-1+3=2;
    при x=0		Z={по первой ветви}=x+3=0+3=3;
    при x=1		Z={по первой ветви}=4x=4*1=4;
    при x=2		Z={по первой ветви}=4x=4*2=8.

    Пример 3. Вычислить таблицу "$$x, y, Z$$" значений функции $$Z(x,y)=\begin{cases}x+y,xy<1\\x-y,xy\ge 1\end{cases}$$ при $$-1-\le х\le 0,5$$ с шагом 1, $$5\le y\le 15$$ с шагом 5 .

    Решение. В данной задаче изменяются две переменные: $$х$$ и $$у$$. Следовательно, нужно реализовать двумерный цикл: внешний цикл по переменной $$х$$, внутренний цикл по переменной $$у$$. Тело цикла будет содержать вычисление функции $$Z$$ и вывод на экран строчки значений $$x, y, Z$$.

    В данной задаче имеем:

  • $$х=-1$$ – начальное значение переменной внешнего цикла $$х$$;
  • $$hx=1$$ – шаг изменения переменной внешнего цикла $$х$$;
  • "$$х\le 0,5$$" - условие для выполнения итерации внешнего цикла по $$х$$;
  • $$у=5$$ – начальное значение переменной внутреннего цикла $$у$$;
  • $$hy=5$$ – шаг изменения переменной внутреннего цикла $$у$$;
  • "$$у\le 15$$" - условие для выполнения итерации внутреннего цикла по у.
  • Блок-схема с предусловием приведена на рис. 5.5.

    (рис 5.5) Блок-схема с предусловием для примера 3

    Код программы с оператором while:

    // proga25while.cpp: определяет точку входа для консольного приложения.
    //
    #include "stdafx.h"
    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main(){
    	double x, y, Z;
    	cout<<setw(10)<<"x"<<setw(10)<<"y"<<setw(10)<<"Z"<<endl;
    	x=-1;
    	while(x<=0.5){
    		y=5;
    		while(y<=15){
    			if(x*y<1){
    				Z=x+y;
    			}
    			else{
    				Z=x-y;
    			}
    			cout<<setw(10)<<x<<setw(10)<<y<<setw(10)<<Z<<endl;
    			y=y+5;
    		}
    		x=x+1;
    	}
    	return 0;}

    Код программы с оператором for:

    // proga25for.cpp: определяет точку входа для консольного приложения.
    //
    #include "stdafx.h"
    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main(){
    	double x, y, Z;
    	cout<<setw(10)<<"x"<<setw(10)<<"y"<<setw(10)<<"Z"<<endl;
    	for(x=-1; x<=0.5; x=x+1){
    		for(y=5; y<=15; y=y+5){
    			if(x*y<1){
    				Z=x+y;
    			}
    			else{
    				Z=x-y;
    			}
    			cout<<setw(10)<<x<<setw(10)<<y<<setw(10)<<Z<<endl;
    		}
    	}
    	return 0;}

    Блок-схема с постусловием приведена на рис. 5.6.

    (рис 5.6) Блок-схема с постусловием для примера 3

    Код программы (Visual Studio) с оператором do while (постусловие):

    // proga25dowhile.cpp: определяет точку входа для консольного приложения.
    //
    #include "stdafx.h"
    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main(){
    	double x, y, Z;
    	cout<<setw(10)<<"x"<<setw(10)<<"y"<<setw(10)<<"Z"<<endl;
    	x=-1;
    	do{
    		y=5;
    		do{
    			if(x*y<1){
    				Z=x+y;
    			}
    			else{
    				Z=x-y;
    			}
    			cout<<setw(10)<<x<<setw(10)<<y<<setw(10)<<Z<<endl;
    			y=y+5;
    		}while(y<=15);
    		x=x+1;
    	}while(x<=0.5);
    	return 0;}

    Результат выполнения программ с операторами while, for, do while:

    Ручной счет:

    Диапазон значений х: -1; 0.
    Диапазон значений у: 5, 10, 15.
    при x=-1	y=5	Z={по первой ветви}=x+y=-1+5=4;
    при x=-1	y=10	Z={по первой ветви}=x+y=-1+10=9;
    при x=-1	y=15	Z={по первой ветви}=x+y=-1+15=14;
    при x=0		y=5	Z={по первой ветви}=x+y=0+5=5;
    при x=0		y=10	Z={по первой ветви}=x+y=0+10=10;
    при x=0		y=15	Z={по первой ветви}=x+y=0+15=15.

    Примечание. В данном примере операторы вложенного и внешнего циклов совпадают. Например, в одной программе задействован один оператор while два раза. Можно сочетать операторы цикла как угодно: оператор do while может быть вложен в оператор for, оператор for в оператор while и т.д. Результат выполнения программы не должен зависеть от выбранного оператора цикла.

    Занятие 2. Исследование таблицы значений функции

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

  • Нахождение наибольшего $$\max$$ (наименьшего $$\min$$) значения функции.
    max=-10E10;
    for(x=xn; x<=xk; x=x+h){
    	f=…;
    	if(f>max){
    		max=f;
    }
    }
    Примечание. Если нужно найти наименьшее значение функции, то следует сделать следующие замены: "$$\max=-10^{10}$$" поменять на "$$\min=10^{10}$$", "$$f>\max$$" поменять на "$$f<\min$$", "$$\max=f$$" поменять на "$$\min=f$$".
  • Нахождение суммы $$S$$ значений функции
    S=0;
    for(x=xn; x<=xk; x=x+h){
    	f=…;
    	S=S+f;
    }
    cout<<"S="<<S<<endl;
  • Нахождение произведения $$P$$ значений функции
    P=1;
    for(x=xn; x<=xk; x=x+h){
    	f=…;
    	P=P*f;
    }
    cout<<"P="<<P<<endl;
  • Нахождение среднего арифметического значения $$S$$ и количества $$k$$ значений функции
    S=0;
    k=0;
    for(x=xn; x<=xk; x=x+h){
    	f=…;
    	S=S+f;
    	k=k+1;
    }
    S=S/k;
    cout<<"S="<<S<<endl;
    cout<<"k="<<k<<endl;
  • Пример 4. Вычислить таблицу "$$x, f$$" значений функции $$f(x)=2x+1$$ при $$0\le х\le 4$$ с шагом 1. Найти сумму всех значений функции; произведение значений, меньших 6; минимальное значение функции.

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

    Введем обозначения:

  • $$S$$ – сумма всех значений функции,
  • $$P$$ – произведение значений, меньших 6,
  • $$\min$$ – минимальное значение функции.
  • Т.к. нужно найти произведение значений, меньших 6, то следует добавить условие "$$f<6$$" при вычислении произведения.

    Будем реализовывать цикл с предусловием, используя оператор for.

    Блок-схема с предусловием: Код программы с оператором for:
    // proga26.cpp: определяет точку входа для консольного приложения.
    //
    #include "stdafx.h"
    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main()
    {
    	double x,f,S,P,min;
    	cout<<setw(10)<<"x"<<setw(10)<<"f"<<endl;
    	S=0;
    	P=1;
    	min=10E10;
    	for(x=0; x<=4; x=x+1){
    		f=2*x+1;
    		cout<<setw(10)<<x<<setw(10)<<f<<endl;
    		S=S+f;
    		if(f<6){
    			P=P*f;
    		}
    		if(f<min){
    			min=f;
    		}
    	}
    	cout<<"S="<<S<<endl;
    	cout<<"P="<<P<<endl;
    	cout<<"min="<<min<<endl;
    	return 0;
    }

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

    Ручной счет:

    Диапазон значений х: 0, 1, 2, 3, 4.
    при x=0	f=2x+1=2*0+1=1;
    при x=1	f=2x+1=2*1+1=3;
    при x=2	f=2x+1=2*2+1=5;
    при x=3	f=2x+1=2*3+1=7;
    при x=4	f=2x+1=2*4+1=9;
    сумма всех значений:S=1+3+5+7+9=25;
    произведение значений, меньших 6: P=1*3*5=15;
    наименьшее значение функции: min=1.

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

    Пример 5. Нарисовать на экране бесконечную "змейку" символами "*".

    Решение. Определим сначала внешний вид "змейки":

    *
     *
      *
       *
      *
     *
    *
     *
      *

    Т.к. "змейка" должна быть бесконечной, то необходимо организовать бесконечный цикл. В этом случае будем использовать оператор while с всегда выполняемым условием true: while(true). Внутри этого бесконечного цикла будем рисовать один период "змейки", т.е. один холм. За счет бесконечного цикла на экране будет бесконечное число раз рисоваться наш холм.

    Теперь стоит решить, какой ширины будет наша "змейка". Будем запрашивать ширину "змейки" у пользователя, т.е. с клавиатуры. Обозначим ширину переменной $$n$$. Холм состоит из двух частей – расширяющейся и сужающейся. Чтобы нарисовать расширяющуюся часть, будем использовать цикл for по переменной $$i$$ от 1 до $$n$$ и функцию setw(i). Чтобы нарисовать сужающуюся часть, будем использовать цикл for по переменной $$i$$ от $$n$$ до 1 и функцию setw(i).

    Таким образом, внутри бесконечного цикла while вложены последовательно два цикла for – первый с увеличением переменной цикла, второй с уменьшением.

    Код программы:

    // snake.cpp: определяет точку входа для консольного приложения.
    //
    #include "stdafx.h"
    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main()
    {
    	int i, n;
    	cout<<"vvedi n=";
    	cin>>n;
    	while (true){
    		for(i=1; i<=n; i=i+1){
    			cout<<setw(i)<<"*"<<endl;
    		}
    		for(i=n; i>=1; i=i-1){
    			cout<<setw(i)<<"*"<<endl;
    		}
    		}
    	return 0;
    }

    Результат выполнения программы: при $$n=5$$:

    Краткие итоги

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

    Упражнения

  • Составьте блок-схему и программу для вычисления суммы всех целых чисел от 1 до 100 включительно.
  • Постройте таблицу значений функции $$y(x)=5x^2-3x+4$$ при $$-20\le х\le 20$$ с шагом 0,5. Определите наименьшее значение функции и значение $$х$$, при котором оно достигается.
  • Составьте блок-схему и программу для вычисления таблицы значений функций $$z1=\arccos^3(0,05x), z2=0,45|x^3-x^2|+2\lg^{2,5}x$$ при $$0,8\le х\le 19$$ c шагом 1. Найдите сумму всех значений $$z1$$, количество значений $$z2$$, меньших 10, наимешьшее значение $$z1$$, наибольшее значение $$z2$$.
  • Составьте блок-схему и программу для вычисления таблицы значений функции $$Z(x,y)=\begin{cases}\sin^{0.4}(x^{4y})+\lg\sqrt{y-\frac{x}{y-0.8}},\text{если}\ x+y<-2\\2.3,\text{если}\ -2\le x+y\le 0\\\frac{\sqrt[3]{x}-\sqrt[3]{y}}{x}-y,\text{если}\ x+y>0\end{cases}$$ при $$0,5\le х\le 1$$ c шагом 0,05; y задать с клавиатуры.
  • Составьте блок-схему и программу для вычисления таблицы значений функции $$Z(x,y)=\min\{\max\{\sin x, \sin y\},x,y\}$$ при $$-1,7\le х\le 9,4$$ c шагом 9,3; $$0\le y\le 3$$ c шагом 0,75. Определите наибольшее отрицательное значение функции, наименьшее положительное значение функции, произведение ненулевых значений функции, количество значений функции, больших 1 или меньших -1.
  • Составьте программу, которая нарисует на экране геометрическую фигуру. Попробуйте разные варианты:
  • квадрат,
  • треугольник,
  • прямоугольник.
  • Модифицируйте программу таким образом, чтобы на экране появлялась фигура заданное число раз.
    Вернуться к учебному плану