При разработке простейших программ несложно перейти от словесного описания к написанию программы. Однако большинство реально разрабатываемых программ довольно сложные и созданию программы предшествует разработка
(рис 3.1) Блок начала-конца алгоритма
(рис 3.2) Блок ввода-вывода данных
(рис 3.3) Арифметический блок
(рис 3.4) Условный блок
(рис 3.5) Линейный процесс
(рис 3.6) Разветвляющийся процесс
(рис 3.7) Циклический процесс
Рассмотренные блоки позволяют описать три основные конструкции алгоритма: линейный процесс, разветвляющийся процесс и циклический процесс.
Линейный процесс это конструкция, представляющая собой последовательное выполнение двух или более операторов (рис. 3.5). Разветвляющийся процесс задаёт выполнение одного или другого оператора в зависимости от выполнения условия (рис. 3.6). Циклический процесс задаёт многократное выполнение оператора или группы операторов (рис. 3.7).
Нетрудно заметить, что каждая из основных конструкций алгоритма имеет один вход и один выход. Это позволяет вкладывать конструкции друг в друга произвольным образом и составлять алгоритмы для решения задач любой сложности.
Одним из важных понятий при написании программ на С(С++) является понятие составного оператора.
Составной оператор — это группа операторов, отделённых друг от друга точкой с запятой, начинающихся с открывающей фигурной скобки { и заканчивающихся закрывающейся фигурной скобкой }:
{
оператор_1;
...
оператор_n;
}
Транслятор воспринимает составной оператор как одно целое.
Рассмотрим операторы языка С++, реализующие основные конструкции алгоритма.
Одна из основных конструкций алгоритма — разветвляющийся процесс. Он реализован в языке С++ двумя условными операторами: if и switch Рассмотрим каждый из них.
При решении большинства задач порядок вычислений зависит от определённых условий, например, от исходных данных или от промежуточных результатов, полученных на предыдущих шагах программы. Для организации вычислений в зависимости от какого-либо условия в С++ предусмотрен условный оператор if, который в общем виде записывается следующим образом:
if (условие) оператор_1; else оператор_2;
где условие — это логическое (или целое) выражение, переменная или константа, оператор_1 и оператор_2 — любой оператор языка С(С++) .
Работает условный оператор следующим образом. Сначала вычисляется значение выражения, указанного в скобках. Если оно не равно нулю, т.е. имеет значение истина (true), выполняется оператор_1. В противном случае, когда выражение равно нулю, т.е. имеет значение ложь (false), выполняется оператор_2. Алгоритм, который реализован в условном операторе if, представлен на рис. 3.8.
Например, чтобы сравнить значения переменных a и b нужно написать следующий программный код:
cin>>a; cin>>b; if ( a==b) cout<<" a равно b "; else cout<<" a не равно b ";
Внимание! Не путайте знак проверки равенства == и оператор присваивания =. Например, в записи if (a=0) b=1; синтаксической ошибки нет. Операция присваивания a=0 формирует результат и его значение проверяется в качестве условия. В данном примере присваивание b=1 не будет выполнено никогда, так как переменная a всегда будет принимать значение равное нулю, то есть ложь. Верная запись: if (a==0) b=1;.
(рис 3.8) Алгоритм условного оператора if ... else
(рис 3.9) Алгоритм условного оператора if
Внимание! Если в задаче требуется, чтобы в зависимости от значения условия выполнялся не один оператор, а несколько, их необходимо заключать в фигурные скобки, как составной оператор. В этом случае компилятор воспримет группу операторов как один:
if ( условие )
{
оператор_1;
оператор_2;
...
}
else
{
оператор_3;
оператор_4;
...
}
Альтернативная ветвь else в условном операторе может отсутствовать, если в ней нет необходимости:
if ( условие ) оператор;
или
if ( условие )
{
оператор_1;
оператор_2;
...
}
В таком "усечённом" виде условный оператор работает так: оператор (группа операторов) либо выполняется, либо пропускается, в зависимости от значения выражения, представляющего условие. Алгоритм этого условного процесса представлен на рис. 3.9.
Пример применения условного оператора без альтернативной ветви else может быть таким:
cin>>a; cin>>b; c =0; //Значение переменной c изменяется только при условии, что a не равно b if ( a!=b) c=a+b; cout<<" c = "<<c;
Условные операторы могут быть вложены друг в друга. При вложениях условных операторов всегда действует правило: альтернатива else считается принадлежащей ближайшему if. Например, в записи
if (условие_1) if (условие_2) оператор_А; else оператор_Б;
оператор_Б относится к условию_2, а в конструкции
if (условие_1) { if (условие_2) оператор_А; }
else оператор_Б;
он принадлежит оператору if с условием_1.
Рассмотрим несколько задач с применением условных процессов.
Задача 3.1. Дано вещественное число $$x$$. Для функции, график которой приведён на рис. 3.10, вычислить $$y = f(x)$$.
(рис 3.10) Графическое представление задачи 3.1
Аналитически функцию, представленную на рис. 3.10, можно записать так:
$$\begin{equation} y(x)=\left\{\begin{matrix} 4, x\leqslant -2\\ 1, x\geqslant 1\\ x^2, -2<x<1 \end{matrix}\right. \end{equation}$$Составим словесный алгоритм решения этой задачи:
Блок-схема, соответствующая описанному алгоритму, представлена на рис. 3.11.
(рис 3.11) Блок-схема алгоритма решения задачи 3.1
Текст программы на языке C++ будет иметь вид:
#include <iostream>
using namespace std;
int main ( )
{
float X,Y;
cout<<" X = "; cin >>X;
if (X<=-2) Y=4;
else if (X>=1) Y=1;
else Y=X*X;
cout <<" Y = " <<Y<< endl;
return 0;
}
Задача 3.2. Даны вещественные числа $$x$$ и $$y$$. Определить, принадлежит ли точка с координатами ($$x; y$$) заштрихованной области (рис. 3.12).
(рис 3.12) Графическое представление задачи 3.2
(рис 3.13) Алгоритм решения задачи 3.2
Как показано на рис. 3.12, область ограничена линиями $$x = -1, x = 3, y = -2$$ и $$y = 4$$. Значит точка с координатами ($$x; y$$) будет принадлежать этой области, если будут выполняться следующие условия: $$x \ge -1, x \le 3, y \ge -2$$ и $$y \le 4$$. Иначе точка лежит за пределами области.
Блок-схема, описывающая алгоритм решения данной задачи, представлена на рис. 3.13.
Текст программы к задаче 3.2:
#include <iostream>
using namespace std;
int main ( )
{ float X,Y;
cout<<" X = "; cin >>X;
cout<<" Y = "; cin >>Y;
if (X>=-1 X<=3 Y>=-2 Y<=4)
cout <<"Точка принадлежит области"<< endl;
else
cout<<"Точка не принадлежит области"<<endl;
return 0;
}
Задача 3.3. Даны вещественные числа $$x$$ и $$y$$. Определить, принадлежит ли точка с координатами ($$x; y$$) заштрихованной области (рис. 3.14).
Составим уравнения линий, ограничивающих заданные области. В общем виде уравнение прямой, проходящей через точки с координатами ($$x_1,y_1$$) и ($$x_2,y_2$$), имеет вид:
$$\frac{x-x_1}{x_2-x_1}=\frac{y-y_1}{y_2-y_1}$$
(рис 3.14) Графическое представление задачи 3.3
Треугольник в первой координатной области ограничен линиями, проходящими через точки:
Следовательно, уравнение первой линии:
$$\frac{x-0}{4-0}=\frac{y-1}{3-1}\Rightarrow \frac{x}{4}=\frac{y-1}{2}\Rightarrow y=1+\frac{1}{2}\cdot x,$$уравнение второй линии:
$$\frac{x-4}{5-4}=\frac{y-3}{1-3}\Rightarrow x-4=\frac{y-3}{-2}\Rightarrow -2\cdot x+8=y-3\Rightarrow y=-2\cdot x+11$$и уравнение третьей линии: $$y = 1$$.
Линии, которые формируют треугольник во второй координатной области, проходят через точки:
Следовательно, уравнение первой линии:
$$\frac{x-0}{-4-0}=\frac{y-1}{3-1}\Rightarrow \frac{x}{-4}=\frac{y-1}{2}\Rightarrow y=1-\frac{1}{2}\cdot x,$$уравнение второй линии:
$$\frac{x+4}{-5+4}=\frac{y-3}{1-3}\Rightarrow \frac{x+4}{-1}=\frac{y-3}{-2}\Rightarrow -2\cdot x-8=-y+3\Rightarrowy=2\cdot x+11$$и уравнение третьей линии: $$y = 1$$.
Таким образом, условие попадания точки в заштрихованную часть плоскости имеет вид:
$$\begin{equation}\left\{\begin{array}{c}y\leqslant 1+\frac{1}{2}\cdot x\\y\leqslant -2\cdot x+11\\y\geqslant 1\end{array}\right. \text{или}\ \ \left\{\begin{array}{c}y\leqslant 1-\frac{1}{2}\cdot x\\y\leqslant 2\cdot x+11\\y\geqslant 1\end{array}\right. \end{equation}$$Далее приведён текст программы для решения задачи 3.3.
#include <iostream>
using namespace std;
int main ( )
{
float X,Y;
cout<<" X = "; cin >>X;
cout<<" Y = "; cin >>Y;
if ( (Y<=1+( float ) 1/2 *X Y<=-2*X+11 Y>=1) | | (Y<=1-( float ) 1/2 *X Y<=2*X+11 Y>=1))
cout <<"Точка принадлежит области"<< endl;
else
cout<<"Точка не принадлежит области"<< endl;
return 0;
}
Задача 3.4. Написать программу решения квадратного уравнения $$ax^2 + bx + c = 0$$.
Исходные данные: вещественные числа $$a, b$$ и $$c$$ — коэффициенты квадратного уравнения.
Результаты работы программы: вещественные числа $$x1$$ и $$x2$$ — корни квадратного уравнения либо сообщение о том, что корней нет.
Вспомогательные переменные: вещественная переменная $$d$$, в которой будет храниться дискриминант квадратного уравнения.
Составим словесный алгоритм решения этой задачи.
"Действительных корней нет" и переход к п.8.Блок-схема, соответствующая этому описанию, представлена на рис. 3.15.
Текст программы, которая реализует решение квадратного уравнения:
#include <iostream>
#include <math.h>
using namespace std;
int main ( )
{
float a, b, c, d, x1, x2;
//Ввод значений коэффициентов квадратного уравнения.
cout<<" a = "; cin >>a;
cout<<" b = "; cin >>b;
cout<<" c = "; cin >>c;
d=b*b-4*a*c; //Вычисление дискриминанта.
if (d<0)
//Если дискриминант отрицательный, то вывод сообщения, о том что действительных корней нет,
cout<<"Нет действительных корней";
else
{
//иначе вычисление действительных корней
x1=( -b+sqrt (d) ) /2/a;
x2=( -b-sqrt (d) ) /(2 * a);
//и вывод их значений.
cout<<" X1 = "<<x1<<" \t X2 = "<<x2<<" \n ";
}
return 0;
}
(рис 3.15) Алгоритм решения квадратного уравнения
Задача 3.5. Составить программу нахождения действительных и комплексных корней квадратного уравнения $$ax^2 + bx + c = 0$$.
Исходные данные: вещественные числа a, b и c — коэффициенты квадратного уравнения.
Результаты работы программы: вещественные числа $$x1$$ и $$x2$$ — действительные корни квадратного уравнения либо $$x1$$ и $$x2$$ — действительная и мнимая части комплексных корней квадратного уравнения.
Вспомогательные переменные: вещественная переменная $$d$$, в которой будет храниться дискриминант квадратного уравнения.
Можно выделить следующие этапы решения задачи:
У обоих комплексных корней действительные части одинаковые, а мнимые отличаются знаком. Поэтому можно в переменной $$x1$$ хранить действительную часть числа $$\frac{-b}{2a}$$, в переменной $$x2$$ — модуль мнимой части $$\frac{\sqrt{\left|{d}\right|}}{2a}$$, а в качестве корней вывести $$x1 + i \cdot x2$$ и $$x1 - i \cdot x2$$.
На рис. 3.16 изображена блок-схема решения задачи. Блок 1 предназначен для ввода коэффициентов квадратного уравнения. В блоке 2 осуществляется вычисление дискриминанта. Блок 3 осуществляет проверку знака дискриминанта, если дискриминант отрицателен, то корни комплексные, их расчёт происходит в блоке 4 (действительная часть корня записывается в переменную $$x1$$, модуль мнимой — в переменную $$x2$$), а вывод — в блоке 5 (первый корень $$x1+i\cdot x2$$, второй — $$x1 - i \cdot x2$$). Если дискриминант положителен, то вычисляются действительные корни уравнения (блок 6) и выводятся на экран (блок 7).
Текст программы, реализующей поставленную задачу:
#include <iostream>
#include <math.h>
using namespace std;
int main ( )
{
float a, b, c, d, x1, x2;
cout<<" a = "; cin>>a;
cout<<" b = "; cin>>b;
cout<<" c = "; cin>>c;
d=b*b-4*a*c;
if (d<0)
{ //Если дискриминант отрицательный, то вывод соответствующего сообщения.
cout<<"Нет вещественных корней \n ";
x1=-b/(2 * a ); //Вычисление действительной части комплексных корней.
x2=sqrt ( fabs (d) ) /(2 * a ); //Вычисление модуля мнимой части комплексных корней
//Сообщение о комплексных корнях уравнения вида ax2 + bx + c = 0.
cout<<"Комплексные корни уравнения \n ";
cout<<a<<" x ^2+ "<<b<<" x + "<<c<<" =0 \n ";
//Вывод значений комплексных корней в виде x1 + ix2, x1 - ix2
if ( x2>=0)
{
cout<<x1<<" + "<<x2<<" i \t ";
cout<<x1<<" -"<<x2<<" i \n ";
}
else
{
cout<<x1<<" -"<<abs ( x2 )<<" i \t ";
cout<<x1<<" + "<<abs ( x2 )<<" i \n ";
}
}
else
{
//Если дискриминант положительный, вычисление действительных корней и вывод их на экран.
x1=( -b+sqrt (d) ) /2/a;
x2=( -b- sqrt (d) ) /(2 * a );
cout<<"Вещественные корни уравнения \n ";
cout<<a<<" x ^2+ "<<b<<" x + "<<c<<" =0 \n ";
cout<< X1 = "<<x1<<" \t X2 = "<<x2<<" \n ";
}
return 0;
}
(рис 3.16) Алгоритм решения задачи 3.5
Результаты работы программы к задаче 3.5 показаны ниже.
a=-5 b=-3 c=-4 Нет вещественных корней Комплексные корни уравнения -5x^2+-3x+-4=0 -0.3-0.842615i -0.3+0.842615i ============================== a=2 b=-3 c=1 Вещественные корни уравнения 2x^2+-3x+1=0 X1=1 X2=0.5
Задача 3.6. Составить программу для решения кубического уравнения $$ax^3 + bx^2 + cx + d = 0$$.
Кубическое уравнение имеет вид
$$ax^3 + bx^2 + cx + d = 0$$После деления на a уравнение 3.1 принимает канонический вид:
$$x^3 + rx^2 + sx + t = 0,$$где $$r=\frac{b}{a},s=\frac{c}{a},t=\frac{d}{a}$$.
В уравнении 3.2 сделаем замену $$x=y-\frac{r}{3}$$ и получим приведённое уравнение:
$$y^3+py+q=0,$$где $$p=\frac{3s-r^2}{3},q=\frac{2r^3}{27}-\frac{rs}{3}+t$$.
Число действительных корней приведённого уравнения (3.3) зависит от знака дискриминанта (табл. 3.1) $$D=(\frac{p}{3})^3+(\frac{q}{2})^2$$.
| Дискриминант | Количество действительных корней | Количество комплексных корней |
|---|---|---|
| $$D\ge 0$$ | 1 | 2 |
| $$D<0$$ | 3 | - |
Корни приведённого уравнения могут быть рассчитаны по формулам Кардано:
$$\begin{array}{l} y_1=u+v\\ y_2=\frac{-{u+v}}{2}+\frac{u-v}{2}i\sqrt{3}\\ y_3=\frac{-{u+v}}{2}-\frac{u-v}{2}i\sqrt{3}, \end{array}$$где $$u=\sqrt[{3}]{\frac{-q}{2}+\sqrt{D}},v=\sqrt[{3}]{\frac{-q}{2}-\sqrt{D}}$$.
При отрицательном дискриминанте уравнение (3.1) имеет три действительных корня, но они будут вычисляться через вспомогательные комплексные величины. Чтобы избавиться от этого, можно воспользоваться формулами:
$$\begin{array}{l} y_1=2\sqrt[{3}]{\rho}\cos(\frac{\phi}{3}),\\ y_2=2\sqrt[{3}]{\rho}\cos(\frac{\phi}{3}+\frac{2\pi}{3}),\\ y_3=2\sqrt[{3}]{\rho}\cos(\frac{\phi}{3}+\frac{4\pi}{3}), \end{array}$$где $$\rho =\sqrt{\frac{-{p^{3}}}{27}}, \cos(\phi )=\frac{-{q}}{2\rho}$$.
Таким образом, при положительном дискриминанте кубического уравнения (3.3) расчёт корней будем вести по формулам (3.4), а при отрицательном — по формулам (3.5). После расчёта корней приведённого уравнения (3.3) по формулам (3.4) или (3.5), необходимо по формулам
$$x_{k}=y_{k}-\frac{r}{3},\ k=1,2,3..,$$перейти к корням заданного кубического уравнения (3.1).
Блок-схема решения кубического уравнения представлена на рис. 3.18.
Описание блок-схемы. В блоке 1 вводятся коэффициенты кубического уравнения, в блоках 2–3 рассчитываются коэффициенты канонического и приведённого уравнений. Блок 4 предназначен для вычисления дискриминанта. В блоке 5 проверяется знак дискриминанта кубического уравнения. Если он отрицателен, то корни вычисляются по формулам 3.5 (блоки 6–7). При положительном значении дискриминанта расчёт идёт по формулам 3.4 (блок 9, 10). Блоки 8 и 11 предназначены для вывода результатов на экран.
Текст программы с комментариями приведён
#include <iostream>
#include <math.h>
using namespace std;
#define pi 3.14159 //Определение константы
int main ( )
{
float a, b, c, d,D, r, s, t, p, q, ro, fi, x1, x2, x3, u, v, h, g;
//Ввод коэффициентов кубического уравнения.
cout<<" a = "; cin >>a;
cout<<" b = "; cin >>b;
cout<<" c = "; cin >>c;
cout<<" d = "; cin >>d;
//Расчёт коэффициентов канонического уравнения по формуле 3.2
r=b/a; s=c /a; t=d/a;
//Вычисление коэффициентов приведённого уравнения по формуле 3.3
p=(3*s -r * r ) / 3; q=2* r* r * r /27 - r * s/3+t;
//Вычисление дискриминанта кубического уравнения
D=(p /3) * ( p /3) * ( p /3) +(q /2) * ( q /2);
if (D<0)
{
//Формулы 3.5
ro=sqrt ( ( float )( -p* p* p/27) );
fi=-q /(2 * ro );
fi=pi/2 - atan ( fi / sqrt (1 - fi * f i ) );
x1=2*pow( ro, ( float ) 1/3) * cos ( f i /3)- r /3;
x2=2*pow( ro, ( float ) 1/3) * cos ( f i /3+2* pi /3)- r /3;
x3=2*pow( ro, ( float ) 1/3) * cos ( f i /3+4* pi /3)- r /3;
cout<<" \n x1 = "<<x1<<" \t x2 = "<<x2;
cout<<" \t x3 = "<<x3<<" \n ";
}
else
{
//Формулы 3.4
if ( -q/2+sqrt (D) >0) u=pow(( - q/2+sqrt (D) ),( float ) 1/3);
else
if ( -q/2+sqrt (D) <0) u=-pow( fabs( -q/2+sqrt (D) ),( float ) 1/3);
else u=0;
if (-q/2 - sqrt (D) >0) v=pow(( -q/2 - sqrt (D) ),( float ) 1/3);
else
if ( -q/2 - sqrt (D) <0) v=-pow( fabs( -q/2 - sqrt (D) ),( float ) 1/3);
else v=0;
x1=u+v-r /3; //Вычисление действительного корня кубического уравнения.
h= -(u+v)/2 - r /3; //Вычисление действительной
g=(u-v) /2 -sqrt (( float ) 3); //и мнимой части комплексных корней
cout<<" \ n x1 = "<<x1;
if (x2>=0)
{
cout<<x1<<" + "<<x2<<" i \t ";
cout<<x1<<" -"<<x2<<" i \n ";
}
else
{
cout<<x1<<" -"<<fabs ( x2 )<<" i \t ";
cout<<x1<<" + "<<fabs ( x2 )<<" i \n ";
}
}
if (g>=0)
{
cout<<" \t x2 = "<<h<<" + "<<g<<" i ";
cout<<" \t x3 = "<<h<<" -"<<g<<" i \n ";
}
else
{
cout<<" \t x2 = "<<h<<" -"<<fabs (g)<<" i ";
cout<<" \t x2 = "<<h<<" + "<<fabs (g)<<" i ";
}
return 0;
}
(рис 3.17) Алгоритм решения кубического уравнения
Задача 3.7. Заданы коэффициенты $$a, b$$ и $$c$$ биквадратного уравнения $$ax^4+bx^2 +c = 0$$. Найти все его действительные корни.
Входные данные: $$a, b, c$$.
Выходные данные: $$x1, x2, x3, x4$$.
Для решения биквадратного уравнения необходимо заменой $$y = x^2$$ привести его к квадратному уравнению $$ay^2 + by + c = 0$$ и решить это уравнение.
Опишем алгоритм решения этой задачи (рис. 3.18):
d < 0 (блок 3), вывод сообщения, что корней нет (блок 4), а иначе определяются корни соответствующего квадратного уравнения y1 и y2(блок 5).y1 < 0 и y2 < 0 (блок 6), то вывод сообщения, что корней нет (блок 7).y1 >= 0 и y2 >= 0 (блок 8), то вычисляются четыре корня по формулам $$\pm\sqrt{y_1}, \pm\sqrt{y_2}$$ (блок 9) и выводятся значения корней (блок 10).y1. Если y1 >= 0 (блок 11), то вычисляются два корня по формуле $$\pm\sqrt{y_1}$$ (блок 12), иначе (если y2 >= 0) вычисляются два корня по формуле $$\pm\sqrt{y_2}$$ (блок 13). Вывод вычисленных значений корней (блок 14).
(рис 3.18) Алгоритм решения биквадратного уравнения
Текст программы решения биквадратного уравнения приведён ниже.
Внимание! Если в условном операторе проверяется двойное условие, необходимо применять логические операции ||, , !.Например, условие "если y1 и y2 положительны" правильно записать так: if (y1>=0 y2>=0).
#include <iostream>
#include <math.h>
using namespace std;
int main ( )
{ //Описание переменных:
//a, b, c - коэффициенты биквадратного уравнения,
//d - дискриминант,
// x1, x2, x3, x4 - корни биквадратного уравнения,
//y1, y2 - корни квадратного уравнения ay^2+by+c =0,
float a, b, c, d, x1, x2, x3, x4, y1, y2;
//Ввод коэффициентов уравнения.
cout<<" a = "; cin >>a;
cout<<" b = "; cin >>b;
cout<<" c = "; cin >>c;
d=b* b-4*a*c; //Вычисление дискриминанта.
if ( d<0) //Если дискриминант отрицательный, вывод сообщения "Корней нет".
cout<<" Нет действительных корней \ n ";
else //Если дискриминант положительный,
{
//Вычисление корней соответствующего квадратного уравнения .
y1=( -b+sqrt ( d ) ) /2/ a;
y2=( -b- sqrt ( d ) ) /(2 * a );
//Если оба корня квадратного уравнения отрицательные,
if ( y1<0 y2<0)
//вывод сообщения "Корней нет"
cout<<" Нет действительных корней \ n ";
//Если оба корня квадратного уравнения положительные,
else if ( y1>=0 y2>=0)
{ //Вычисление четырёх корней биквадратного уравнения
x1=sqrt ( y1 );
x2=-x1;
x3=sqrt ( y2 );
x4=- sqrt ( y2 );
//Вывод корней уравнения на экран .
cout<<" \t X1 = "<<x1<<" \t X2 = "<<x2;
cout<<" \t X3 = "<<x3<<" \t X4 = "<<x4<<" \n ";
}
//Если не выполнились условия
// 1.y1<0 и y2<0
// 2.y1>=0 и y2>=0,
//то проверяем условие y1>=0.
else if ( y1>=0) //Если оно истинно
{ //вычисляем два корня биквадратного уравнения.
x1=sqrt ( y1 );
x2=-x1;
cout<<" X1 = "<<x1<<" \t X2 = "<<x2<<" \n ";
}
else
{ //Если условие y1>=0 ложно, то вычисляем два корня биквадратного уравнения
x1=sqrt ( y2 );
x2=-x1;
cout<<" X1 = "<<x1<<" \t X2 = "<<x2<<" \n ";
}
}
return 0;
}
Читателю предлагается самостоятельно модифицировать программу таким образом, чтобы она находила все корни (как действительные, так и комплексные) биквадратного уравнения.
Оператор варианта switch необходим в тех случаях, когда в зависимости от значений какой-либо переменной надо выполнить те или иные операторы:
switch (выражение)
{
case значение_1: Операторы_1; break;
case значение_2: Операторы_2; break;
case значение_3: Операторы_3; break;
...
case значение_n: Операторы_n; break;
default : Операторы; break;
}
Оператор работает следующим образом. Вычисляется значение выражения (оно должно быть целочисленным). Если выражение принимает значение_1, то выполняются операторы_1. Если выражение принимает значение_2, то выполняется операторы_2 и так далее. Если выражение не принимает ни одно из значений, то выполняются операторы, расположенные после ключевого слова default.
Альтернативная ветвь default может отсутствовать, тогда оператор имеет вид:
switch (выражение)
{
case значение_1: Операторы_1; break;
case значение_2: Операторы_2; break;
case значение_3: Операторы_3; break;
...
case значение_n: Операторы_n; break;
}
Оператор break необходим для того, чтобы осуществить выход из оператора switch. Если оператор break не указан, то будут выполняться следующие операторы из списка, несмотря на то, что значение, которым они помечены, не совпадает со значением выражения.
Рассмотрим применение оператора варианта.
Задача 3.8. Вывести на печать название дня недели, соответствующее заданному числу $$D$$, при условии, что в месяце 31 день и 1-е число — понедельник.
Для решения задачи воспользуемся операцией %, позволяющей вычислить остаток от деления двух чисел, и условием, что 1-е число — понедельник. Если в результате остаток от деления (обозначим его $$R$$) заданного числа $$D$$ на семь будет равен единице, то это понедельник, двойке — вторник, тройке — среда и так далее. Следовательно, при построении алгоритма необходимо использовать семь условных операторов, как показано рис. 3.19. Решение задачи станет значительно проще, если при написании программы воспользоваться оператором варианта switch:
#include <iostream>
using namespace std;
int main ( )
{ unsigned int D,R; //Описаны целые положительные числа.
cout<<" D = "; cin>>D; //Ввод числа от 1 до 31.
R=D%7;
switch (R)
{
case 1 : cout<<" Понедельник \n "; break;
case 2 : cout<<" Вторник \n "; break;
case 3 : cout<<" Среда \n "; break;
case 4 : cout<<" Четверг \n "; break;
case 5 : cout<<" Пятница \n "; break;
case 6 : cout<<" Суббота \n "; break;
case 0 : cout<<" Воскресенье \n "; break;
}
return 0;
}
В предложенной записи оператора варианта отсутствует ветвь default. Это объясняется тем, что переменная $$R$$ может принимать только одно из указанных значений, т.е. 1, 2, 3, 4, 5, 6 или 0. Однако программа будет работать неправильно, если пользователь введёт значение $$D$$, превышающее 31. Чтобы избежать подобной ошибки лучше сделать дополнительную проверку входных данных:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int D,R;
cout<<" \ n D = "; cin >>D;
if (D<32) //Проверка введённого значения.
{
R=D%7;
switch (R)
{
case 1 : cout<<" Понедельник \n "; break;
case 2 : cout<<" Вторник \n "; break;
case 3 : cout<<" Среда \n "; break;
case 4 : cout<<" Четверг \n "; break;
case 5 : cout<<" Пятница \n "; break;
case 6 : cout<<" Суббота \n "; break;
case 0 : cout<<" Воскресенье \n "; break;
}
}
//Сообщение об ошибке в случае некорректного ввода.
else cout<<" ОШИБКА! \n ";
return 0;
}
(рис 3.19) Алгоритм решения задачи 3.8
Задача 3.9. По заданному номеру месяца $$m$$ вывести на экран его название.
Для решения данной задачи необходимо проверить выполнение двенадцати условий. Если $$m$$ равно единице, то это январь, если двойке, то февраль, тройке — март и так далее. Понятно, что область возможных значений переменной $$m$$ находится в диапазоне от 1 до 12 и если пользователь введёт число не входящее в этот интервал, то появится сообщение об ошибке.
#include <iostream>
using namespace std;
int main ( )
{
unsigned int m; //Описано целое положительное число.
cout<<" m = "; cin >>m;
switch (m)
{
//В зависимости от значения m выводится название месяца.
case 1 : cout<<" Январь \n "; break;
case 2 : cout<<" Февраль \n "; break;
case 3 : cout<<" Март \n "; break;
case 4 : cout<<" Апрель \n "; break;
case 5 : cout<<" Май \n "; break;
case 6 : cout<<" Июнь \n "; break;
case 7 : cout<<" Июль \n "; break;
case 8 : cout<<" Август \n "; break;
case 9 : cout<<" Сентябрь \n "; break;
case 1 0 : cout<<" Октябрь \n "; break;
case 1 1 : cout<<" Ноябрь \n "; break;
case 1 2 : cout<<" Декабрь \n "; break;
//Если значение переменной m выходит за пределы области
//допустимых значений, то выдаётся сообщение.
default : cout<<" ОШИБКА! \n "; break;
}
return 0;
}
Циклический процесс или просто цикл это повторение одних и тех же действий. Последовательность действий, которые повторяются в цикле, называют телом цикла. Один проход цикла называют шагом или итерацией. Переменные, которые изменяются внутри цикла и влияют на его окончание, называются параметрами цикла.
При написании циклических алгоритмов следует помнить следующее. Во- первых, чтобы цикл имел шанс когда-нибудь закончиться, содержимое его тела должно обязательно влиять на условие цикла. Во-вторых, условие должно состоять из корректных выражений и значений, определённых ещё до первого выполнения тела цикла.
В С++ для удобства пользователя предусмотрены три оператора, реализующих циклический процесс: while, do...while и for.
На рис. 3.20 изображена блок-схема алгоритма цикла с предусловием. Оператор, реализующий этот алгоритм в С++, имеет вид:
while (условие) оператор;
здесь условие — логическое или целочисленное выражение, оператор — любой оператор языка С(С++) .
(рис 3.20) Алгоритм циклической структуры с предусловием
Работает цикл с предусловием следующим образом. Вычисляется условие. Если оно истинно (не равно нулю), то выполняется оператор, и условие проверяется вновь. В противном случае цикл заканчивается, и управление передаётся оператору, следующему за телом цикла. Условие вычисляется перед каждой итерацией цикла. Если при первой проверке выражение равно нулю, цикл не выполнится ни разу. Тип выражения должен быть арифметическим или приводимым к нему.
Если тело цикла состоит более чем из одного оператора, необходимо использовать составной оператор:
while (условие)
{
оператор 1;
оператор 2;
...
оператор n;
}
Рассмотрим пример. Пусть необходимо вывести на экран таблицу значений функции $$y=e^{\sin (x)}\cos (x)$$ на отрезке [0; π] с шагом 0.1. Применив цикл с предусловием, получим:
#include <stdio.h>
#include <math.h>
#define PI 3.14159
using namespace std;
int main ( )
{
float x, y; //Описание переменных
x=0; //Присваивание параметру цикла стартового значения
//Цикл с предусловием
while (x<=PI ) //Пока параметр цикла не превышает конечное значение
{ //выполнять тело цикла
y=exp ( sin ( x ) ) * cos ( x ); //Вычислить значение y
//Вывод на экран пары x и y .
printf ( " \t x =%5.2 f \t y =%5.4 f \n ",x, y );
x+=0.1; //Изменение параметра цикла
// (переход к следующему значению x )
} //Конец цикла
return 0;
}
В результате работы данного фрагмента программы на экран последовательно будут выводиться сообщения со значениями переменных $$x$$ и $$y$$:
x= 1.00 y=1.2534 x= 2.10 y=-1.1969 x= 1.10 y=1.1059 x= 2.20 y=-1.3209 x= 1.20 y=0.9203 x= 2.30 y=-1.4045 x= 1.30 y=0.7011 x= 2.40 y=-1.4489 x= 1.40 y=0.4553 x= 2.50 y=-1.4576 x= 1.50 y=0.1918 x= 2.60 y=-1.4348 x= 1.60 y=-0.0793 x= 2.70 y=-1.3862 x= 1.70 y=-0.3473 x= 2.80 y=-1.3172 x= 1.80 y=-0.6017 x= 2.90 y=-1.2334 x= 1.90 y=-0.8328 x= 3.00 y=-1.1400 x= 2.00 y=-1.0331 x= 3.10 y=-1.0416
В цикле с предусловием предварительной проверкой определяется, выполнять тело цикла или нет, до первой итерации. Если это не соответствует логике алгоритма, то можно использовать цикл с постусловием. На рис. 3.21 видно, что в этом цикле проверяется, делать или нет очередную итерацию, лишь после завершения предыдущей. Это имеет принципиальное значение лишь на первом шаге, а далее циклы ведут себя идентично.
(рис 3.21) Алгоритм циклической структуры с постусловием
В С++ цикл с постусловием реализован конструкцией
do оператор while (условие);
здесь условие — логическое или целочисленное выражение, оператор — любой оператор языка С(С++). Если тело цикла состоит более чем из одного оператора:
do
{
оператор_1;
оператор_2;
...
оператор_n;
}
while (условие);
Работает цикл следующим образом. В начале выполняется оператор, представляющий собой тело цикла. Затем вычисляется условие. Если оно истинно (не равно нулю), оператор тела цикла выполняется ещё раз. В противном случае цикл завершается, и управление передаётся оператору, следующему за циклом.
Таким образом, не трудно заметить, что цикл с постусловием всегда будет выполнен хотя бы один раз, в отличие от цикла с предусловием, который может не выполниться ни разу.
Если применить цикл с постусловием для создания программы, которая выводит таблицу значений функции $$y=e^{\sin (x)}\cos(x)$$ на отрезке [0; π] с шагом 0.1, получим:
#include <iostream>
#include <stdio.h>
#include <math.h>
#define PI 3.14159
using namespace std;
int main ( )
{
float x, y; //Описание переменных
x=0; //Присваивание параметру цикла стартового значения
do //Цикл с постусловием
{ //Выполнять тело цикла
y=exp ( sin ( x ) ) * cos ( x );
printf ( " \t x =%5.2 f \t y =%5.4 f \n ",x, y );
x+=0.1; //Изменение параметра цикла
}
while (x<=PI ); //пока параметр цикла не превышает конечное значение
return 0;
}
Результаты работы этой программы будут такими.
Кроме того, в С++ предусмотрен цикл for с параметром:
for (начальные_присваивания;условие;последействие) оператор;
где начальные_присваивания — оператор или группа операторов, разделённых условие — целое или логическое выражение, которое определяет условие входа в цикл, если условие истинно (не равно нулю), то цикл выполняется; последействие — оператор или группа операторов, разделённых запятой, которые выполняются после каждой итерации и служат для изменения параметра цикла; оператор — любой оператор языка, представляющий собой тело цикла. Последействие или оператор должны влиять на условие, иначе цикл никогда не закончится. Начальные_присваивания, выражение или последействие в записи оператора for могут отсутствовать, но при этом "точки с запятой" должны оставаться на своих местах. Опишем алгоритм работы цикла for:
начальные_присваивания.условие, если оно не равно 0 (true), то выполняется переход к п.3. В противном случае выполнение цикла завершается.оператор.последействие и осуществляется переход к п.2, опять вычисляется значение выражения и т.д.Понятно, что этот алгоритм представляет собой цикл с предусловием (рис. 3.22).
(рис 3.22) Алгоритм работы цикла с параметром
В дальнейшем, чтобы избежать создания слишком громоздких алгоритмов, в блок-схемах цикл for будем изображать, так как показано на рис. 3.23.
В случае если тело цикла состоит более чем из одного оператора, необходимо использовать составной оператор:
for (начальные_присваивания; условие; последействие)
{
оператор_1;
...
оператор_n;
}
Применение цикла for рассмотрим на примере печати таблицы значений функции $$y=e^{\sin (x)}\cos (x)$$ на отрезке [0;π] с шагом 0.1:
#include <stdio.h>
#include <math.h>
#define PI 3.14159
using namespace std;
int main ( )
{
float x, y;
//Параметру цикла присваивается начальное значение, если оно не превышает конечное значение,
//то выполняются операторы тела цикла и значение параметра изменяется, в противном случае
//цикл заканчивается.
for ( x=0;x<=PI; x+=0.1)
{
y=exp ( sin ( x ) ) * cos ( x );
printf ( " \t x =%5.2 f \t y =%5.4 f \n ", x, y );
}
return 0;
}
(рис 3.23) Блок-схема цикла с параметром
Программный код выдаст результат.
Операторы передачи управления принудительно изменяют порядок выполнения команд. В С++ таких операторов четыре: goto, break, continue и return.
Оператор goto метка, где метка обычный идентификатор, применяют для безусловного перехода, он передаёт управление оператору с меткой: метка:
Оператор break осуществляет немедленный выход из циклов while, do... while и for, а так же из оператора выбора switch. Управление передаётся оператору, находящемуся непосредственно за циклом или оператором выбора.
Оператор continue начинает новую итерацию цикла, даже если предыдущая не была завершена.
Оператор return выражение завершает выполнение функции и передаёт управление в точку её вызова. Если функция возвращает значение типа void, то выражение в записи оператора отсутствует. В противном случае выражение должно иметь скалярный тип.
Рассмотрим использование циклических операторов на конкретных примерах.
Задача 3.10. Написать программу решения квадратного уравнения $$ax^2+bx+c =0$$. Предусмотреть проверку ввода данных.
Решение квадратного уравнения было подробно рассмотрено в задаче 3.4. Однако алгоритм, изображённый на рис. 3.15, не будет работать, если пользователь введёт нулевое значение в переменную a (при попытке вычислить корни уравнения произойдёт деление на ноль). Чтобы избежать подобной ошибки нужно в программе предусмотреть проверку входных данных, например, так как показано на рис. 3.24. Вводится значение переменной a, если оно равно нулю, то ввод повторяется, иначе следует алгоритм вычисления корней квадратного уравнения. Здесь применяется цикл с постусловием, так как значение переменной необходимо ввести, а затем проверить его на равенство нулю.
(рис 3.24) Блок-схема проверки ввода данных
Программа решения задачи:
#include <iostream>
#include <math.h>
using namespace std;
int main ( )
{
float a, b, c, d, x1, x2;
//Проверка ввода значения коэффициента a .
do //Выполнять тело цикла пока а равно нулю
{
cout<<" a = "; cin >>a;
}
while ( a==0);
cout<<" b = "; cin >>b;
cout<<" c = "; cin >>c;
d=b* b-4*a*c;
if (d<0) cout<<" Нет вещественных корней";
else
{
x1=( -b+sqrt (d) ) /2/a;
x2=( -b- sqrt (d) ) /(2 *a );
cout<<" X1 = "<<x1<<" \t X2 = "<<x2<<" \n ";
}
return 0;
}
Задача 3.11. Найти наибольший общий делитель (НОД) натуральных чисел $$A$$ и $$B$$.
Входные данные: $$A$$ и $$B$$.
Выходные данные: $$A$$ — НОД.
Для решения поставленной задачи воспользуемся алгоритмом Евклида: будем уменьшать каждый раз большее из чисел на величину меньшего до тех пор, пока оба значения не станут равными, так, как показано в табл. 3.2.
| Шаг | A | B |
|---|---|---|
| Исходные данные | 25 | 15 |
| Шаг 1 | 10 | 15 |
| Шаг 2 | 10 | 5 |
| Шаг 3, НОД | 5 | 5 |
В блок–схеме, представленной на рис. 3.25, для решения поставленной задачи используется цикл с предусловием, то есть тело цикла повторяется до тех пор, пока $$A$$ не равно $$B$$. Следовательно, при создании программы воспользуемся циклом while:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int a, b;
cout<<" A = "; cin>>a;
cout<<" B = "; cin>>b;
//Если числа не равны, выполнять тело цикла
while ( a!=b)
//Если число A больше, чем B, то уменьшить его значение на B,
if ( a>b) a=a-b;
//иначе уменьшить значение числа B на A
else b=b-a;
cout<<" НОД= "<<a<<" \n ";
return 0;
}
Результат работы программы не изменится, если для её решения воспользоваться циклом с постусловием do...while:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int a, b;
cout<<" A = "; cin >>a;
cout<<" B = "; cin >>b;
do
if ( a>b ) a=a-b; else b=b-a;
while ( a !=b );
cout<<" НОД= "<<a<<" \n ";
return 0;
}
(рис 3.25) Поиск наибольшего общего делителя двух чисел.
Задача 3.12. Вычислить факториал числа $$N ( N! = 1 · 2 · 3 · ... · N)$$.
Входные данные: $$N$$ — целое число, факториал которого необходимо вычислить.
Выходные данные: factorial — целое число, значение факториала числа $$N$$, произведение чисел от 1 до $$N$$.
Промежуточные переменные: $$i$$ — параметр цикла, целочисленная переменная, последовательно принимающая значения 2, 3, 4 и так далее до $$N$$.
Блок-схема приведена на рис. 3.26.
Итак, вводится число $$N$$. Переменной factorial, предназначенной для хранения значения произведения последовательности чисел, присваивается начальное значение, равное единице. Затем организуется цикл, параметром которого выступает переменная $$i$$. Если значение параметра цикла не превышает $$N$$, то выполняется оператор тела цикла, в котором из участка памяти с именем factorial считывается предыдущее значение произведения, умножается на текущее значение параметра цикла, а результат снова помещается в участок памяти с именем factorial. Когда параметр $$i$$ превысит $$N$$, цикл заканчивается, и на экран выводится значение переменой factorial, которая была вычислена в теле цикла.
(рис 3.26) Алгоритм вычисления факториала.
Обратите внимание, как в программе записан оператор цикла. Здесь операторы ввода и операторы присваивания стартовых значений записаны как начальные присваивания цикла for, а оператор накапливания произведения и оператор модификации параметра цикла представляют собой последействие:
#include <iostream>
using namespace std;
int main ( )
{
unsigned long long int factorial;
unsigned int N, i;
for ( cout<<" N = ", cin >>N, factorial =1, i =2; i<=N; factorial*=i, i ++);
cout<<" факториал= "<<factorial <<" \ n ";
return 0;
}
Задача 3.13. Вычислить сумму натуральных чётных чисел, не превышающих $$N$$.
Входные данные: $$N$$ — целое число.
Выходные данные: $$S$$ — сумма чётных чисел.
Промежуточные переменные: $$i$$ — параметр цикла, принимает значения 2, 4, 6, 8 и так далее, также имеет целочисленное значение.
При сложении нескольких чисел необходимо накапливать результат в определённом участке памяти ($$S$$), каждый раз считывая из этого участка ($$S$$) предыдущее значение суммы ($$S$$) и прибавляя к нему слагаемое $$i$$. Для выполнения первого оператора накапливания суммы из участка памяти необходимо взять такое число, которое не влияло бы на результат сложения. Перед началом цикла переменной, предназначенной для накапливания сумы, необходимо присвоить значение нуль. Блок-схема решения этой задачи представлена на рис. 3.27.
Решим задачу двумя способами: с применением циклов while и for:
//Решение задачи с помощью цикла while
#include <iostream>
using namespace std;
int main ( )
{
unsigned int N, i, S;
cout<<" N = "; cin >>N;
S=0;
i =2;
while ( i<=N)
{
S=S+i;
i=i +2;
}
cout<<" S = "<<S<<" \n ";
return 0;
}
//__________________________________
//Решение задачи с помощью цикла for
#include <iostream>
using namespace std;
int main ( )
{
unsigned int N, i, S;
for ( cout<<" N = ", cin >>N, S=0, i =2; i<=N; S+=i, i +=2);
cout<<" S = "<<S<<" \n ";
return 0;
}
(рис 3.27) Алгоритм вычисления суммы чётных натуральных чисел.
Задача 3.14. Дано натуральное число $$N$$. Определить $$K$$ — количество делителей этого числа, меньших самого числа (Например, для $$N=12$$ делители 1, 2, 3, 4, 6. Количество $$K=5$$).
Входные данные: $$N$$ — целое число.
Выходные данные: целое число $$K$$ — количество делителей $$N$$.
Промежуточные переменные: $$i$$ — параметр цикла, возможные делители числа $$N$$.
В блок-схеме, изображённой на рис. 3.28, реализован следующий алгоритм: в переменную $$K$$, предназначенную для подсчёта количества делителей заданного числа, помещается значение, которое не влияло бы на результат, т.е. нуль. Далее организовывается цикл, в котором изменяющийся параметр $$i$$ выполняет роль возможных делителей числа $$N$$. Если заданное число $$N$$ делится нацело на параметр цикла $$i$$, это означает, что $$i$$ является делителем $$N$$, и значение переменной $$K$$ следует увеличить на единицу. Цикл необходимо повторить $$\frac{N}{2}$$ раз.
(рис 3.28) Алгоритм определения делителей натурального числа.
Текст программы на С++:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int N, i,K;
cout<<" N = "; cin >>N;
for (K=0, i =1; i<=N/ 2; i ++) if (N%i ==0) K++;
cout<<" K = "<<K<<" \n ";
return 0;
}
Задача 3.15. Дано натуральное число $$N$$. Определить, является ли оно простым. Натуральное число $$N$$ называется простым, если оно делится без остатка только на единицу и на само себя. Число 13 — простое, так как делится только на 1 и 13, а число 12 таковым не является, так как делится на 1, 2, 3, 4, 6 и 12.
Входные данные: $$N$$ — целое число.
Выходные данные: сообщение.
Промежуточные переменные: $$i$$ — параметр цикла, возможные делители числа $$N$$.
Необходимо проверить, есть ли делители числа $$N$$ в диапазоне от 2 до $$N/2$$ (рис. 3.29). Если делителей нет, $$N$$ — простое число, иначе оно таковым не является. Обратите внимание на то, что в алгоритме предусмотрено два выхода из цикла. Первый — естественный, при исчерпании всех значений параметра, а второй — досрочный. Нет смысла продолжать цикл, если будет найден хотя бы один делитель из указанной области изменения параметра.
(рис 3.29) Алгоритм определения простого числа.
При составлении программы на языке С++ досрочный выход из цикла удобно выполнять при помощи оператора break:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int N, i;
bool Pr;
cout<<" N = "; cin >>N;
Pr=true; //Предположим, что число простое
for ( i =2; i <=N/ 2; i ++)
if (N%i ==0) //Если найдётся хотя бы один делитель, то
{
Pr=false; //число простым не является и
break; //досрочный выход из цикла
}
if ( Pr ) //Проверка значения логического параметра и вывод на печать
//соответствующего сообщения
cout<<N<<" - простое число\n ";
else
cout<<N<<" - не является простым\n ";
return 0;
}
Задача 3.16. Дано натуральное число $$N$$. Определить количество цифр в числе.
Входные данные: $$N$$ — целое число.
Выходные данные: $$kol$$ — количество цифр в числе.
Промежуточные данные: $$M$$ — переменная для временного хранения значения $$N$$
Для того, чтобы подсчитать количество цифр в числе, необходимо определить, сколько раз заданное число можно разделить на десять нацело. Например, пусть $$N = 12345$$, тогда количество цифр $$kol = 5$$. Результаты вычислений сведены в табл. 3.3.
| kol | N |
|---|---|
| 1 | 12345 |
| 2 | 12345 / 10 = 1234 |
| 3 | 1234 / 10 = 123 |
| 4 | 123 / 10 = 12 |
| 5 | 12 / 10 = 1 |
| 1 / 10 = 0 |
Алгоритм определения количества цифр в числе представлен на рис. 3.30.
#include <iostream>
using namespace std;
int main ( )
{
unsigned long int N, M;
unsigned int kol;
cout<<" N = "; cin >>N;
for (M=N, kol =1; M/10 >0; kol ++,M/=10);
cout<<" kol = "<<kol <<endl;
return 0;
}
(рис 3.30) Алгоритм определения количества цифр в числе.
Задача 3.17. Дано натуральное число $$N$$. Определить, содержит ли это число нули и в каких разрядах они расположены (например, число 11011110111 содержит ноль в третьем и восьмом разрядах, а число 120405 — в первом и третьем).
Входные данные: $$N$$ — целое число.
Выходные данные: $$pos$$ — позиция цифры в числе.
Промежуточные данные: $$i$$ — параметр цикла, $$M$$ — переменная для временного хранения значения $$N$$.
В связи с тем, что разряды в числе выделяются начиная с последнего, для определения номера разряда в числе, необходимо знать количество цифр в
| i | Число М | Цифра | Номер позиции |
|---|---|---|---|
| 1 | 120405 | 120405 % 10 = 5 | 0 |
| 2 | 12040/10 = 1204 | 12040 % 10 = 0 | 1 |
| 3 | 1204/10 = 120 | 1204 % 10 = 4 | 2 |
| 4 | 120/10 = 12 | 120 % 10 = 0 | 3 |
| 5 | 12/10 = 1 | 12 % 10 = 2 | 4 |
| 6 | 1/10 = 0 | 1 % 10 = 1 | 5 |
Программный код к задаче 3.17.
#include <iostream>
using namespace std;
int main ( )
{
unsigned long int N,M; int kol, i;
cout<<" N = "; cin >>N;
for ( kol =1,M=N;M/10 >0; kol ++,M/=10);
for (M=N, i =0; i <kol;M/=10, i ++)
if (M%10==0) cout<<"Позиция = "<<i <<endl;
return 0;
}
Задача 3.18. Дано натуральное число $$N$$. Получить новое число, записав цифры числа $$N$$ в обратном порядке. Например, 17852 — 25871.
Входные данные: $$N$$ — целое число.
Выходные данные: $$S$$ — целое число, полученное из цифр числа $$N$$, записанных в обратном порядке.
Промежуточные данные: $$i$$ — параметр цикла, $$M$$ — переменная для временного хранения значения $$N, kol$$ — количество разрядов в заданном числе, $$R = 10^{kol}$$ — старший разряд заданного числа.
Рассмотрим пример. Пусть $$N = 17852$$, тогда $$S = 2 \cdot 10^4 + 5 \cdot 10^3 + 8 \cdot 10^2 + 7 \cdot 10^1 + 1 \cdot 10^0 = 25871$$.
Значит, для решения поставленной задачи, нужно знать количество разрядов в заданном числе $$kol$$ и его старший разряд $$R = 10^{kol}$$. Новое число $$S$$ формируют как сумму произведений последней цифры заданного числа на старший разряд $$S+ = M\%10 * R$$. Цикл выполняют $$kol$$ раз, при каждой итерации уменьшая само число и старший разряд в десять раз.
#include <iostream>
using namespace std;
int main ( )
{ unsigned long int N,M, R, S; int kol, i;
cout<<" N = "; cin >>N;
for (R=1, kol =1,M=N;M/10 >0; kol ++,R* =10,M/=10);
for ( S=0,M=N, i =1; i<=kol; S+=M%10*R,M/=10,R/=10, i ++);
cout<<" S = "<<S<<endl;
return 0;
}
Задача 3.19. Проверить, является ли заданное число $$N$$
Входные данные: $$N$$ — целое число.
Выходные данные: сообщение.
Промежуточные данные: $$i$$ — параметр цикла, $$M$$ — переменная для временного хранения значения $$N, kol$$ — количество разрядов в заданном числе, $$R = 10^{kol}$$ — старший разряд заданного числа, $$S$$ — целое число, полученное из цифр числа $$N$$, записанных в обратном порядке.
Можно предложить следующий алгоритм решения задачи. Записать цифры заданного числа $$N$$ в обратном порядке (задача 3.18), получится новое число $$S$$. Сравнить полученное число $$S$$ с исходным $$N$$. Если числа равны, то заданное число является палиндромом.
Текст программы на языке С++:
#include <iostream>
using namespace std;
int main ( )
{ unsigned long int N,M,R, S;
int kol, i;
cout<<" N = "; cin>>N;
for (R=1, kol =1,M=N;M/10 >0; kol++,R* =10,M/=10);
for (S=0,M=N, i =1; i<=kol; S+=M%10*R,M/=10,R/=10, i++);
if (N==S) cout<<"Число - палинром"<<endl;
else cout<<"Число не является палиндромом"<<endl;
return 0;
}
Задача 3.20. Поступает последовательность из $$N$$ вещественных чисел. Определить наибольший элемент последовательности.
Входные данные: $$N$$ — целое число; $$X$$ — вещественное число, определяет текущий элемент последовательности.
Выходные данные: $$Max$$ — вещественное число, элемент последовательности с наибольшим значением.
Промежуточные переменные: $$i$$ — параметр цикла, номер вводимого элемента последовательности.
Алгоритм поиска наибольшего элемента в последовательности следующий (рис. 3.31). Вводится $$N$$ — количество элементов последовательности и $$X$$ — первый элемент последовательности. В памяти компьютера отводится ячейка, например с именем $$Max$$, в которой будет храниться наибольший элемент последовательности — максимум. Далее предполагаем, что первый элемент последовательности наибольший и записываем его в $$Max$$. Затем вводим второй элемент последовательности и сравниваем его с предполагаемым максимумом. Если окажется, что второй элемент больше, его записывают в ячейку $$Max$$. В противном случае никаких действий не предпринимаем. Потом переходим к вводу следующего элемента последовательности ($$X$$), и алгоритм повторяется с начала. В результате в ячейке $$Max$$ сохранится элемент последовательности с наибольшим
(рис 3.31) Алгоритм поиска наибольшего числа в последовательности.
Текст программы на С++:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int i,N;
float X,Max;
cout<<" N = "; cin>>N;
cout<<" X = "; cin>>X; //Ввод первого элемента последовательности
//Параметр цикла принимает стартовое значение i =2, т.к. первый элемент
//уже введён предположим, что он максимальный, т.е. Max=X.
for ( i =2, Max=X; i<=N; i++)
{
cout<<" X = "; cin>>X; //Ввод следующих элементов последовательности.
//Если найдётся элемент, превышающий максимум, записать его в ячейку Max,
//теперь он предполагаемый максимум.
if (X>Max) Max=X;
}
//Вывод наибольшего элемента последовательности.
cout<<" Max = "<<Max<<" \n ";
return 0;
}
Задача 3.21. Вводится последовательность целых чисел, 0 — конец последовательности. Найти наименьшее число среди положительных, если таких значений
Блок-схема решения задачи приведена на рис. 3.32.
(рис 3.32) Алгоритм поиска минимального положительного числа в последовательности.
Далее приведён текст подпрограммы с подробными
#include <iostream>
using namespace std;
int main ( )
{
float N, Min; int K;
//Предположим, что в последовательности нет положительных чисел, K=0.
//Вводим число и если оно не равно нулю
for ( cout<<" N = ", cin>>N,K=0;N!=0; cout<<" N = ", cin>>N)
//проверяем является ли оно положительным.
if (N>0)
//если K=0, поступил 1-й положительный элемент, предположим, что он минимальный.
if (K==0) {K=1;Min=N; }
//если элемент не первый, сравниваем его с предполагаемым минимумом,
//если элемент меньше, записываем его в Min и сбрасываем счётчик
else if (N<Min) {Min=N;K=1;}
//если элемент равен минимуму, увеличиваем значение счётчика.
else if (N==Min) K++; //Конец цикла
//Если значение счётчика не равно нулю, печатаем значение
//минимального элемента и количество таких элементов.
if (K!=0) cout<<" Min = "<<Min<<" \n "<<" K = "<<K<<" \n ";
//в противном случае выдаём сообщаем.
else cout<<"В последовательности нет положительных элементов \n ";
return 0;
}
Задача 3.22. Определить, сколько раз последовательность из $$N$$ произвольных чисел меняет знак.
Чтобы решить задачу, нужно попарно перемножать элементы последовательности. Если результат произведения пары чисел — отрицательное число, значит, эти числа имеют разные знаки.
Пусть в переменной $$B$$ хранится текущий элемент последовательности, в $$A$$ — предыдущий. Введём первое число $$A$$ (до цикла) и второе $$B$$ (в цикле). Если их произведение отрицательно, то увеличиваем количество смен знака на 1 (k++). После чего сохраняем значение $$B$$ в переменную $$A$$ и повторяем цикл (рис. 3.33).
(рис 3.33) Алгоритм решения задачи 3.22.
Предлагаем читателю самостоятельно разобраться с текстом программы на С++:
#include <iostream>
using namespace std;
int main ( )
{
float A,B; int i,K,N;
cout<<" N = "; cin>>N;
for (K=0, cout<<" A = ", cin>>A, i =2; i<=N; i++)
{
cout<<" B = "; cin>>B;
if (A*B<0) K++;
A=B;
}
cout<<" K = "<<K<<" \n ";
return 0;
}
Задача 3.23. Поступает последовательность из $$N$$ вещественных чисел. Определить количество простых чисел в последовательности.
Блок-схема алгоритма изображена на рис. 3.34. Обратите внимание, что для решения задачи было организовано два цикла. Первый цикл обеспечивает ввод элементов последовательности. Второй цикл находится внутри первого и определяет, является ли поступившее число простым (задача 3.15).
(рис 3.34) Алгоритм поиска простых чисел в последовательности.
#include <iostream>
using namespace std;
int main ( )
{
unsigned long int X;
unsigned int N;
int i, k, j;
bool Pr;
for ( k=0, cout<<" N = ", cin >>N, i =1; i<=N; i ++)
{
for ( cout<<" X = ", cin >>X, Pr=true, j =2; j<=X/ 2; j ++)
if (X%j ==0)
{
Pr=false;
break;
}
if ( Pr ) k++;
}
if ( k==0) cout<<"Простых чисел нет \n ";
else cout<<"Количество простых чисел k = "<<k<<" \n ";
return 0;
}
Задача 3.24. Дано $$K$$ наборов ненулевых целых чисел. Каждый набор содержит не менее двух элементов, признаком его завершения является число 0. Найти количество наборов, элементы которых возрастают.
Блок-схема алгоритма решения задачи показана на рис. 3.35. Нетрудно заметить, что алгоритм реализован с помощью двух циклических процессов. Внутренний цикл проверяет является ли последовательность возрастающей, а внешний повторяет алгоритм для новой последовательности.
(рис 3.35) Алгоритм решения задачи 3.24.
Программный код решения задачи 3.24:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int K, i, kol, A, B; bool pr;
for ( cout<< "K = ", cin >>K, kol =0, i =1; i<=K; i ++)
{
for ( pr=true, cout<<" A = ", cin >>A;A! = 0; A=B)
{
cout<<" B = "; cin >>B;
if (B!=0 A>=B) pr=false;
}
if ( pr ) kol++;
}
cout << " kol = " << kol <<endl;
return 0;
}
Разработать программу на языке С++. Дано вещественное число a. Для функции $$y = f(x)$$, график которой приведён ниже, вычислить $$f(a)$$. Варианты заданий представлены на рисунках ниже.
(рис 3.36) Задание 1
(рис 3.37) Задание 2
(рис 3.38) Задание 3
(рис 3.39) Задание4
(рис 3.40) Задание 5
(рис 3.41) Задание 6
(рис 3.42) Задание 7
(рис 3.43) Задание 8
(рис 3.44) Задание 9
(рис 3.45) Задание 10
(рис 3.46) Задание 11
(рис 3.47) Задание 12
(рис 3.48) Задание 13
(рис 3.49) Задание 14
(рис 3.50) Задание 15
(рис 3.51) Задание 16
(рис 3.52) Задание 17
(рис 3.53) Задание 18
(рис 3.54) Задание 19
(рис 3.55) Задание 20
(рис 3.56) Задание 21
(рис 3.57) Задание 22
(рис 3.58) Задание 23
(рис 3.59) Задание 24
(рис 3.60) Задание 25
Разработать программу на языке С++. Даны вещественные числа $$x$$ и $$y$$. Определить, принадлежит ли точка с координатами ($$x; y$$) заштрихованной области. Варианты заданий представлены на рисунках ниже.
(рис 3.61) Задание 1
(рис 3.62) Задание 2
(рис 3.63) Задание 3
(рис 3.64) Задание 4
(рис 3.65) Задание 5
(рис 3.66) Задание 6
(рис 3.67) Задание 7
(рис 3.68) Задание 8
(рис 3.69) Задание 9
(рис 3.70) Задание 10
(рис 3.71) Задание 11
(рис 3.72) Задание 12
(рис 3.73) Задание 13
(рис 3.74) Задание 14
(рис 3.75) Задание 15
(рис 3.76) Задание 16
(рис 3.77) Задание 17
(рис 3.78) Задание 18
(рис 3.79) Задание 19
(рис 3.80) Задание 20
(рис 3.81) Задание 21
(рис 3.82) Задание 22
(рис 3.83) Задание 23
(рис 3.84) Задание 24
(рис 3.85) Задание 25
Разработать программу на языке С++ для следующих заданий:
Разработать программу на языке С++. Для решения задачи использовать операторы for, while, do. Варианты заданий:
Разработать программу на языке С++ для следующих заданий:
Разработать программу на языке С++ для следующих заданий:
Разработать программу на языке С++ для следующих заданий:
Разработать программу на языке С++ для следующих заданий:
При разработке простейших программ несложно перейти от словесного описания к написанию программы. Однако большинство реально разрабатываемых программ довольно сложные и созданию программы предшествует разработка
(рис 3.1) Блок начала-конца алгоритма
(рис 3.2) Блок ввода-вывода данных
(рис 3.3) Арифметический блок
(рис 3.4) Условный блок
(рис 3.5) Линейный процесс
(рис 3.6) Разветвляющийся процесс
(рис 3.7) Циклический процесс
Рассмотренные блоки позволяют описать три основные конструкции алгоритма: линейный процесс, разветвляющийся процесс и циклический процесс.
Линейный процесс это конструкция, представляющая собой последовательное выполнение двух или более операторов (рис. 3.5). Разветвляющийся процесс задаёт выполнение одного или другого оператора в зависимости от выполнения условия (рис. 3.6). Циклический процесс задаёт многократное выполнение оператора или группы операторов (рис. 3.7).
Нетрудно заметить, что каждая из основных конструкций алгоритма имеет один вход и один выход. Это позволяет вкладывать конструкции друг в друга произвольным образом и составлять алгоритмы для решения задач любой сложности.
Одним из важных понятий при написании программ на С(С++) является понятие составного оператора.
Составной оператор — это группа операторов, отделённых друг от друга точкой с запятой, начинающихся с открывающей фигурной скобки { и заканчивающихся закрывающейся фигурной скобкой }:
{
оператор_1;
...
оператор_n;
}
Транслятор воспринимает составной оператор как одно целое.
Рассмотрим операторы языка С++, реализующие основные конструкции алгоритма.
Одна из основных конструкций алгоритма — разветвляющийся процесс. Он реализован в языке С++ двумя условными операторами: if и switch Рассмотрим каждый из них.
При решении большинства задач порядок вычислений зависит от определённых условий, например, от исходных данных или от промежуточных результатов, полученных на предыдущих шагах программы. Для организации вычислений в зависимости от какого-либо условия в С++ предусмотрен условный оператор if, который в общем виде записывается следующим образом:
if (условие) оператор_1; else оператор_2;
где условие — это логическое (или целое) выражение, переменная или константа, оператор_1 и оператор_2 — любой оператор языка С(С++) .
Работает условный оператор следующим образом. Сначала вычисляется значение выражения, указанного в скобках. Если оно не равно нулю, т.е. имеет значение истина (true), выполняется оператор_1. В противном случае, когда выражение равно нулю, т.е. имеет значение ложь (false), выполняется оператор_2. Алгоритм, который реализован в условном операторе if, представлен на рис. 3.8.
Например, чтобы сравнить значения переменных a и b нужно написать следующий программный код:
cin>>a; cin>>b; if ( a==b) cout<<" a равно b "; else cout<<" a не равно b ";
Внимание! Не путайте знак проверки равенства == и оператор присваивания =. Например, в записи if (a=0) b=1; синтаксической ошибки нет. Операция присваивания a=0 формирует результат и его значение проверяется в качестве условия. В данном примере присваивание b=1 не будет выполнено никогда, так как переменная a всегда будет принимать значение равное нулю, то есть ложь. Верная запись: if (a==0) b=1;.
(рис 3.8) Алгоритм условного оператора if ... else
(рис 3.9) Алгоритм условного оператора if
Внимание! Если в задаче требуется, чтобы в зависимости от значения условия выполнялся не один оператор, а несколько, их необходимо заключать в фигурные скобки, как составной оператор. В этом случае компилятор воспримет группу операторов как один:
if ( условие )
{
оператор_1;
оператор_2;
...
}
else
{
оператор_3;
оператор_4;
...
}
Альтернативная ветвь else в условном операторе может отсутствовать, если в ней нет необходимости:
if ( условие ) оператор;
или
if ( условие )
{
оператор_1;
оператор_2;
...
}
В таком "усечённом" виде условный оператор работает так: оператор (группа операторов) либо выполняется, либо пропускается, в зависимости от значения выражения, представляющего условие. Алгоритм этого условного процесса представлен на рис. 3.9.
Пример применения условного оператора без альтернативной ветви else может быть таким:
cin>>a; cin>>b; c =0; //Значение переменной c изменяется только при условии, что a не равно b if ( a!=b) c=a+b; cout<<" c = "<<c;
Условные операторы могут быть вложены друг в друга. При вложениях условных операторов всегда действует правило: альтернатива else считается принадлежащей ближайшему if. Например, в записи
if (условие_1) if (условие_2) оператор_А; else оператор_Б;
оператор_Б относится к условию_2, а в конструкции
if (условие_1) { if (условие_2) оператор_А; }
else оператор_Б;
он принадлежит оператору if с условием_1.
Рассмотрим несколько задач с применением условных процессов.
Задача 3.1. Дано вещественное число $$x$$. Для функции, график которой приведён на рис. 3.10, вычислить $$y = f(x)$$.
(рис 3.10) Графическое представление задачи 3.1
Аналитически функцию, представленную на рис. 3.10, можно записать так:
$$\begin{equation} y(x)=\left\{\begin{matrix} 4, x\leqslant -2\\ 1, x\geqslant 1\\ x^2, -2<x<1 \end{matrix}\right. \end{equation}$$Составим словесный алгоритм решения этой задачи:
Блок-схема, соответствующая описанному алгоритму, представлена на рис. 3.11.
(рис 3.11) Блок-схема алгоритма решения задачи 3.1
Текст программы на языке C++ будет иметь вид:
#include <iostream>
using namespace std;
int main ( )
{
float X,Y;
cout<<" X = "; cin >>X;
if (X<=-2) Y=4;
else if (X>=1) Y=1;
else Y=X*X;
cout <<" Y = " <<Y<< endl;
return 0;
}
Задача 3.2. Даны вещественные числа $$x$$ и $$y$$. Определить, принадлежит ли точка с координатами ($$x; y$$) заштрихованной области (рис. 3.12).
(рис 3.12) Графическое представление задачи 3.2
(рис 3.13) Алгоритм решения задачи 3.2
Как показано на рис. 3.12, область ограничена линиями $$x = -1, x = 3, y = -2$$ и $$y = 4$$. Значит точка с координатами ($$x; y$$) будет принадлежать этой области, если будут выполняться следующие условия: $$x \ge -1, x \le 3, y \ge -2$$ и $$y \le 4$$. Иначе точка лежит за пределами области.
Блок-схема, описывающая алгоритм решения данной задачи, представлена на рис. 3.13.
Текст программы к задаче 3.2:
#include <iostream>
using namespace std;
int main ( )
{ float X,Y;
cout<<" X = "; cin >>X;
cout<<" Y = "; cin >>Y;
if (X>=-1 X<=3 Y>=-2 Y<=4)
cout <<"Точка принадлежит области"<< endl;
else
cout<<"Точка не принадлежит области"<<endl;
return 0;
}
Задача 3.3. Даны вещественные числа $$x$$ и $$y$$. Определить, принадлежит ли точка с координатами ($$x; y$$) заштрихованной области (рис. 3.14).
Составим уравнения линий, ограничивающих заданные области. В общем виде уравнение прямой, проходящей через точки с координатами ($$x_1,y_1$$) и ($$x_2,y_2$$), имеет вид:
$$\frac{x-x_1}{x_2-x_1}=\frac{y-y_1}{y_2-y_1}$$
(рис 3.14) Графическое представление задачи 3.3
Треугольник в первой координатной области ограничен линиями, проходящими через точки:
Следовательно, уравнение первой линии:
$$\frac{x-0}{4-0}=\frac{y-1}{3-1}\Rightarrow \frac{x}{4}=\frac{y-1}{2}\Rightarrow y=1+\frac{1}{2}\cdot x,$$уравнение второй линии:
$$\frac{x-4}{5-4}=\frac{y-3}{1-3}\Rightarrow x-4=\frac{y-3}{-2}\Rightarrow -2\cdot x+8=y-3\Rightarrow y=-2\cdot x+11$$и уравнение третьей линии: $$y = 1$$.
Линии, которые формируют треугольник во второй координатной области, проходят через точки:
Следовательно, уравнение первой линии:
$$\frac{x-0}{-4-0}=\frac{y-1}{3-1}\Rightarrow \frac{x}{-4}=\frac{y-1}{2}\Rightarrow y=1-\frac{1}{2}\cdot x,$$уравнение второй линии:
$$\frac{x+4}{-5+4}=\frac{y-3}{1-3}\Rightarrow \frac{x+4}{-1}=\frac{y-3}{-2}\Rightarrow -2\cdot x-8=-y+3\Rightarrowy=2\cdot x+11$$и уравнение третьей линии: $$y = 1$$.
Таким образом, условие попадания точки в заштрихованную часть плоскости имеет вид:
$$\begin{equation}\left\{\begin{array}{c}y\leqslant 1+\frac{1}{2}\cdot x\\y\leqslant -2\cdot x+11\\y\geqslant 1\end{array}\right. \text{или}\ \ \left\{\begin{array}{c}y\leqslant 1-\frac{1}{2}\cdot x\\y\leqslant 2\cdot x+11\\y\geqslant 1\end{array}\right. \end{equation}$$Далее приведён текст программы для решения задачи 3.3.
#include <iostream>
using namespace std;
int main ( )
{
float X,Y;
cout<<" X = "; cin >>X;
cout<<" Y = "; cin >>Y;
if ( (Y<=1+( float ) 1/2 *X Y<=-2*X+11 Y>=1) | | (Y<=1-( float ) 1/2 *X Y<=2*X+11 Y>=1))
cout <<"Точка принадлежит области"<< endl;
else
cout<<"Точка не принадлежит области"<< endl;
return 0;
}
Задача 3.4. Написать программу решения квадратного уравнения $$ax^2 + bx + c = 0$$.
Исходные данные: вещественные числа $$a, b$$ и $$c$$ — коэффициенты квадратного уравнения.
Результаты работы программы: вещественные числа $$x1$$ и $$x2$$ — корни квадратного уравнения либо сообщение о том, что корней нет.
Вспомогательные переменные: вещественная переменная $$d$$, в которой будет храниться дискриминант квадратного уравнения.
Составим словесный алгоритм решения этой задачи.
"Действительных корней нет" и переход к п.8.Блок-схема, соответствующая этому описанию, представлена на рис. 3.15.
Текст программы, которая реализует решение квадратного уравнения:
#include <iostream>
#include <math.h>
using namespace std;
int main ( )
{
float a, b, c, d, x1, x2;
//Ввод значений коэффициентов квадратного уравнения.
cout<<" a = "; cin >>a;
cout<<" b = "; cin >>b;
cout<<" c = "; cin >>c;
d=b*b-4*a*c; //Вычисление дискриминанта.
if (d<0)
//Если дискриминант отрицательный, то вывод сообщения, о том что действительных корней нет,
cout<<"Нет действительных корней";
else
{
//иначе вычисление действительных корней
x1=( -b+sqrt (d) ) /2/a;
x2=( -b-sqrt (d) ) /(2 * a);
//и вывод их значений.
cout<<" X1 = "<<x1<<" \t X2 = "<<x2<<" \n ";
}
return 0;
}
(рис 3.15) Алгоритм решения квадратного уравнения
Задача 3.5. Составить программу нахождения действительных и комплексных корней квадратного уравнения $$ax^2 + bx + c = 0$$.
Исходные данные: вещественные числа a, b и c — коэффициенты квадратного уравнения.
Результаты работы программы: вещественные числа $$x1$$ и $$x2$$ — действительные корни квадратного уравнения либо $$x1$$ и $$x2$$ — действительная и мнимая части комплексных корней квадратного уравнения.
Вспомогательные переменные: вещественная переменная $$d$$, в которой будет храниться дискриминант квадратного уравнения.
Можно выделить следующие этапы решения задачи:
У обоих комплексных корней действительные части одинаковые, а мнимые отличаются знаком. Поэтому можно в переменной $$x1$$ хранить действительную часть числа $$\frac{-b}{2a}$$, в переменной $$x2$$ — модуль мнимой части $$\frac{\sqrt{\left|{d}\right|}}{2a}$$, а в качестве корней вывести $$x1 + i \cdot x2$$ и $$x1 - i \cdot x2$$.
На рис. 3.16 изображена блок-схема решения задачи. Блок 1 предназначен для ввода коэффициентов квадратного уравнения. В блоке 2 осуществляется вычисление дискриминанта. Блок 3 осуществляет проверку знака дискриминанта, если дискриминант отрицателен, то корни комплексные, их расчёт происходит в блоке 4 (действительная часть корня записывается в переменную $$x1$$, модуль мнимой — в переменную $$x2$$), а вывод — в блоке 5 (первый корень $$x1+i\cdot x2$$, второй — $$x1 - i \cdot x2$$). Если дискриминант положителен, то вычисляются действительные корни уравнения (блок 6) и выводятся на экран (блок 7).
Текст программы, реализующей поставленную задачу:
#include <iostream>
#include <math.h>
using namespace std;
int main ( )
{
float a, b, c, d, x1, x2;
cout<<" a = "; cin>>a;
cout<<" b = "; cin>>b;
cout<<" c = "; cin>>c;
d=b*b-4*a*c;
if (d<0)
{ //Если дискриминант отрицательный, то вывод соответствующего сообщения.
cout<<"Нет вещественных корней \n ";
x1=-b/(2 * a ); //Вычисление действительной части комплексных корней.
x2=sqrt ( fabs (d) ) /(2 * a ); //Вычисление модуля мнимой части комплексных корней
//Сообщение о комплексных корнях уравнения вида ax2 + bx + c = 0.
cout<<"Комплексные корни уравнения \n ";
cout<<a<<" x ^2+ "<<b<<" x + "<<c<<" =0 \n ";
//Вывод значений комплексных корней в виде x1 + ix2, x1 - ix2
if ( x2>=0)
{
cout<<x1<<" + "<<x2<<" i \t ";
cout<<x1<<" -"<<x2<<" i \n ";
}
else
{
cout<<x1<<" -"<<abs ( x2 )<<" i \t ";
cout<<x1<<" + "<<abs ( x2 )<<" i \n ";
}
}
else
{
//Если дискриминант положительный, вычисление действительных корней и вывод их на экран.
x1=( -b+sqrt (d) ) /2/a;
x2=( -b- sqrt (d) ) /(2 * a );
cout<<"Вещественные корни уравнения \n ";
cout<<a<<" x ^2+ "<<b<<" x + "<<c<<" =0 \n ";
cout<< X1 = "<<x1<<" \t X2 = "<<x2<<" \n ";
}
return 0;
}
(рис 3.16) Алгоритм решения задачи 3.5
Результаты работы программы к задаче 3.5 показаны ниже.
a=-5 b=-3 c=-4 Нет вещественных корней Комплексные корни уравнения -5x^2+-3x+-4=0 -0.3-0.842615i -0.3+0.842615i ============================== a=2 b=-3 c=1 Вещественные корни уравнения 2x^2+-3x+1=0 X1=1 X2=0.5
Задача 3.6. Составить программу для решения кубического уравнения $$ax^3 + bx^2 + cx + d = 0$$.
Кубическое уравнение имеет вид
$$ax^3 + bx^2 + cx + d = 0$$После деления на a уравнение 3.1 принимает канонический вид:
$$x^3 + rx^2 + sx + t = 0,$$где $$r=\frac{b}{a},s=\frac{c}{a},t=\frac{d}{a}$$.
В уравнении 3.2 сделаем замену $$x=y-\frac{r}{3}$$ и получим приведённое уравнение:
$$y^3+py+q=0,$$где $$p=\frac{3s-r^2}{3},q=\frac{2r^3}{27}-\frac{rs}{3}+t$$.
Число действительных корней приведённого уравнения (3.3) зависит от знака дискриминанта (табл. 3.1) $$D=(\frac{p}{3})^3+(\frac{q}{2})^2$$.
| Дискриминант | Количество действительных корней | Количество комплексных корней |
|---|---|---|
| $$D\ge 0$$ | 1 | 2 |
| $$D<0$$ | 3 | - |
Корни приведённого уравнения могут быть рассчитаны по формулам Кардано:
$$\begin{array}{l} y_1=u+v\\ y_2=\frac{-{u+v}}{2}+\frac{u-v}{2}i\sqrt{3}\\ y_3=\frac{-{u+v}}{2}-\frac{u-v}{2}i\sqrt{3}, \end{array}$$где $$u=\sqrt[{3}]{\frac{-q}{2}+\sqrt{D}},v=\sqrt[{3}]{\frac{-q}{2}-\sqrt{D}}$$.
При отрицательном дискриминанте уравнение (3.1) имеет три действительных корня, но они будут вычисляться через вспомогательные комплексные величины. Чтобы избавиться от этого, можно воспользоваться формулами:
$$\begin{array}{l} y_1=2\sqrt[{3}]{\rho}\cos(\frac{\phi}{3}),\\ y_2=2\sqrt[{3}]{\rho}\cos(\frac{\phi}{3}+\frac{2\pi}{3}),\\ y_3=2\sqrt[{3}]{\rho}\cos(\frac{\phi}{3}+\frac{4\pi}{3}), \end{array}$$где $$\rho =\sqrt{\frac{-{p^{3}}}{27}}, \cos(\phi )=\frac{-{q}}{2\rho}$$.
Таким образом, при положительном дискриминанте кубического уравнения (3.3) расчёт корней будем вести по формулам (3.4), а при отрицательном — по формулам (3.5). После расчёта корней приведённого уравнения (3.3) по формулам (3.4) или (3.5), необходимо по формулам
$$x_{k}=y_{k}-\frac{r}{3},\ k=1,2,3..,$$перейти к корням заданного кубического уравнения (3.1).
Блок-схема решения кубического уравнения представлена на рис. 3.18.
Описание блок-схемы. В блоке 1 вводятся коэффициенты кубического уравнения, в блоках 2–3 рассчитываются коэффициенты канонического и приведённого уравнений. Блок 4 предназначен для вычисления дискриминанта. В блоке 5 проверяется знак дискриминанта кубического уравнения. Если он отрицателен, то корни вычисляются по формулам 3.5 (блоки 6–7). При положительном значении дискриминанта расчёт идёт по формулам 3.4 (блок 9, 10). Блоки 8 и 11 предназначены для вывода результатов на экран.
Текст программы с комментариями приведён
#include <iostream>
#include <math.h>
using namespace std;
#define pi 3.14159 //Определение константы
int main ( )
{
float a, b, c, d,D, r, s, t, p, q, ro, fi, x1, x2, x3, u, v, h, g;
//Ввод коэффициентов кубического уравнения.
cout<<" a = "; cin >>a;
cout<<" b = "; cin >>b;
cout<<" c = "; cin >>c;
cout<<" d = "; cin >>d;
//Расчёт коэффициентов канонического уравнения по формуле 3.2
r=b/a; s=c /a; t=d/a;
//Вычисление коэффициентов приведённого уравнения по формуле 3.3
p=(3*s -r * r ) / 3; q=2* r* r * r /27 - r * s/3+t;
//Вычисление дискриминанта кубического уравнения
D=(p /3) * ( p /3) * ( p /3) +(q /2) * ( q /2);
if (D<0)
{
//Формулы 3.5
ro=sqrt ( ( float )( -p* p* p/27) );
fi=-q /(2 * ro );
fi=pi/2 - atan ( fi / sqrt (1 - fi * f i ) );
x1=2*pow( ro, ( float ) 1/3) * cos ( f i /3)- r /3;
x2=2*pow( ro, ( float ) 1/3) * cos ( f i /3+2* pi /3)- r /3;
x3=2*pow( ro, ( float ) 1/3) * cos ( f i /3+4* pi /3)- r /3;
cout<<" \n x1 = "<<x1<<" \t x2 = "<<x2;
cout<<" \t x3 = "<<x3<<" \n ";
}
else
{
//Формулы 3.4
if ( -q/2+sqrt (D) >0) u=pow(( - q/2+sqrt (D) ),( float ) 1/3);
else
if ( -q/2+sqrt (D) <0) u=-pow( fabs( -q/2+sqrt (D) ),( float ) 1/3);
else u=0;
if (-q/2 - sqrt (D) >0) v=pow(( -q/2 - sqrt (D) ),( float ) 1/3);
else
if ( -q/2 - sqrt (D) <0) v=-pow( fabs( -q/2 - sqrt (D) ),( float ) 1/3);
else v=0;
x1=u+v-r /3; //Вычисление действительного корня кубического уравнения.
h= -(u+v)/2 - r /3; //Вычисление действительной
g=(u-v) /2 -sqrt (( float ) 3); //и мнимой части комплексных корней
cout<<" \ n x1 = "<<x1;
if (x2>=0)
{
cout<<x1<<" + "<<x2<<" i \t ";
cout<<x1<<" -"<<x2<<" i \n ";
}
else
{
cout<<x1<<" -"<<fabs ( x2 )<<" i \t ";
cout<<x1<<" + "<<fabs ( x2 )<<" i \n ";
}
}
if (g>=0)
{
cout<<" \t x2 = "<<h<<" + "<<g<<" i ";
cout<<" \t x3 = "<<h<<" -"<<g<<" i \n ";
}
else
{
cout<<" \t x2 = "<<h<<" -"<<fabs (g)<<" i ";
cout<<" \t x2 = "<<h<<" + "<<fabs (g)<<" i ";
}
return 0;
}
(рис 3.17) Алгоритм решения кубического уравнения
Задача 3.7. Заданы коэффициенты $$a, b$$ и $$c$$ биквадратного уравнения $$ax^4+bx^2 +c = 0$$. Найти все его действительные корни.
Входные данные: $$a, b, c$$.
Выходные данные: $$x1, x2, x3, x4$$.
Для решения биквадратного уравнения необходимо заменой $$y = x^2$$ привести его к квадратному уравнению $$ay^2 + by + c = 0$$ и решить это уравнение.
Опишем алгоритм решения этой задачи (рис. 3.18):
d < 0 (блок 3), вывод сообщения, что корней нет (блок 4), а иначе определяются корни соответствующего квадратного уравнения y1 и y2(блок 5).y1 < 0 и y2 < 0 (блок 6), то вывод сообщения, что корней нет (блок 7).y1 >= 0 и y2 >= 0 (блок 8), то вычисляются четыре корня по формулам $$\pm\sqrt{y_1}, \pm\sqrt{y_2}$$ (блок 9) и выводятся значения корней (блок 10).y1. Если y1 >= 0 (блок 11), то вычисляются два корня по формуле $$\pm\sqrt{y_1}$$ (блок 12), иначе (если y2 >= 0) вычисляются два корня по формуле $$\pm\sqrt{y_2}$$ (блок 13). Вывод вычисленных значений корней (блок 14).
(рис 3.18) Алгоритм решения биквадратного уравнения
Текст программы решения биквадратного уравнения приведён ниже.
Внимание! Если в условном операторе проверяется двойное условие, необходимо применять логические операции ||, , !.Например, условие "если y1 и y2 положительны" правильно записать так: if (y1>=0 y2>=0).
#include <iostream>
#include <math.h>
using namespace std;
int main ( )
{ //Описание переменных:
//a, b, c - коэффициенты биквадратного уравнения,
//d - дискриминант,
// x1, x2, x3, x4 - корни биквадратного уравнения,
//y1, y2 - корни квадратного уравнения ay^2+by+c =0,
float a, b, c, d, x1, x2, x3, x4, y1, y2;
//Ввод коэффициентов уравнения.
cout<<" a = "; cin >>a;
cout<<" b = "; cin >>b;
cout<<" c = "; cin >>c;
d=b* b-4*a*c; //Вычисление дискриминанта.
if ( d<0) //Если дискриминант отрицательный, вывод сообщения "Корней нет".
cout<<" Нет действительных корней \ n ";
else //Если дискриминант положительный,
{
//Вычисление корней соответствующего квадратного уравнения .
y1=( -b+sqrt ( d ) ) /2/ a;
y2=( -b- sqrt ( d ) ) /(2 * a );
//Если оба корня квадратного уравнения отрицательные,
if ( y1<0 y2<0)
//вывод сообщения "Корней нет"
cout<<" Нет действительных корней \ n ";
//Если оба корня квадратного уравнения положительные,
else if ( y1>=0 y2>=0)
{ //Вычисление четырёх корней биквадратного уравнения
x1=sqrt ( y1 );
x2=-x1;
x3=sqrt ( y2 );
x4=- sqrt ( y2 );
//Вывод корней уравнения на экран .
cout<<" \t X1 = "<<x1<<" \t X2 = "<<x2;
cout<<" \t X3 = "<<x3<<" \t X4 = "<<x4<<" \n ";
}
//Если не выполнились условия
// 1.y1<0 и y2<0
// 2.y1>=0 и y2>=0,
//то проверяем условие y1>=0.
else if ( y1>=0) //Если оно истинно
{ //вычисляем два корня биквадратного уравнения.
x1=sqrt ( y1 );
x2=-x1;
cout<<" X1 = "<<x1<<" \t X2 = "<<x2<<" \n ";
}
else
{ //Если условие y1>=0 ложно, то вычисляем два корня биквадратного уравнения
x1=sqrt ( y2 );
x2=-x1;
cout<<" X1 = "<<x1<<" \t X2 = "<<x2<<" \n ";
}
}
return 0;
}
Читателю предлагается самостоятельно модифицировать программу таким образом, чтобы она находила все корни (как действительные, так и комплексные) биквадратного уравнения.
Оператор варианта switch необходим в тех случаях, когда в зависимости от значений какой-либо переменной надо выполнить те или иные операторы:
switch (выражение)
{
case значение_1: Операторы_1; break;
case значение_2: Операторы_2; break;
case значение_3: Операторы_3; break;
...
case значение_n: Операторы_n; break;
default : Операторы; break;
}
Оператор работает следующим образом. Вычисляется значение выражения (оно должно быть целочисленным). Если выражение принимает значение_1, то выполняются операторы_1. Если выражение принимает значение_2, то выполняется операторы_2 и так далее. Если выражение не принимает ни одно из значений, то выполняются операторы, расположенные после ключевого слова default.
Альтернативная ветвь default может отсутствовать, тогда оператор имеет вид:
switch (выражение)
{
case значение_1: Операторы_1; break;
case значение_2: Операторы_2; break;
case значение_3: Операторы_3; break;
...
case значение_n: Операторы_n; break;
}
Оператор break необходим для того, чтобы осуществить выход из оператора switch. Если оператор break не указан, то будут выполняться следующие операторы из списка, несмотря на то, что значение, которым они помечены, не совпадает со значением выражения.
Рассмотрим применение оператора варианта.
Задача 3.8. Вывести на печать название дня недели, соответствующее заданному числу $$D$$, при условии, что в месяце 31 день и 1-е число — понедельник.
Для решения задачи воспользуемся операцией %, позволяющей вычислить остаток от деления двух чисел, и условием, что 1-е число — понедельник. Если в результате остаток от деления (обозначим его $$R$$) заданного числа $$D$$ на семь будет равен единице, то это понедельник, двойке — вторник, тройке — среда и так далее. Следовательно, при построении алгоритма необходимо использовать семь условных операторов, как показано рис. 3.19. Решение задачи станет значительно проще, если при написании программы воспользоваться оператором варианта switch:
#include <iostream>
using namespace std;
int main ( )
{ unsigned int D,R; //Описаны целые положительные числа.
cout<<" D = "; cin>>D; //Ввод числа от 1 до 31.
R=D%7;
switch (R)
{
case 1 : cout<<" Понедельник \n "; break;
case 2 : cout<<" Вторник \n "; break;
case 3 : cout<<" Среда \n "; break;
case 4 : cout<<" Четверг \n "; break;
case 5 : cout<<" Пятница \n "; break;
case 6 : cout<<" Суббота \n "; break;
case 0 : cout<<" Воскресенье \n "; break;
}
return 0;
}
В предложенной записи оператора варианта отсутствует ветвь default. Это объясняется тем, что переменная $$R$$ может принимать только одно из указанных значений, т.е. 1, 2, 3, 4, 5, 6 или 0. Однако программа будет работать неправильно, если пользователь введёт значение $$D$$, превышающее 31. Чтобы избежать подобной ошибки лучше сделать дополнительную проверку входных данных:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int D,R;
cout<<" \ n D = "; cin >>D;
if (D<32) //Проверка введённого значения.
{
R=D%7;
switch (R)
{
case 1 : cout<<" Понедельник \n "; break;
case 2 : cout<<" Вторник \n "; break;
case 3 : cout<<" Среда \n "; break;
case 4 : cout<<" Четверг \n "; break;
case 5 : cout<<" Пятница \n "; break;
case 6 : cout<<" Суббота \n "; break;
case 0 : cout<<" Воскресенье \n "; break;
}
}
//Сообщение об ошибке в случае некорректного ввода.
else cout<<" ОШИБКА! \n ";
return 0;
}
(рис 3.19) Алгоритм решения задачи 3.8
Задача 3.9. По заданному номеру месяца $$m$$ вывести на экран его название.
Для решения данной задачи необходимо проверить выполнение двенадцати условий. Если $$m$$ равно единице, то это январь, если двойке, то февраль, тройке — март и так далее. Понятно, что область возможных значений переменной $$m$$ находится в диапазоне от 1 до 12 и если пользователь введёт число не входящее в этот интервал, то появится сообщение об ошибке.
#include <iostream>
using namespace std;
int main ( )
{
unsigned int m; //Описано целое положительное число.
cout<<" m = "; cin >>m;
switch (m)
{
//В зависимости от значения m выводится название месяца.
case 1 : cout<<" Январь \n "; break;
case 2 : cout<<" Февраль \n "; break;
case 3 : cout<<" Март \n "; break;
case 4 : cout<<" Апрель \n "; break;
case 5 : cout<<" Май \n "; break;
case 6 : cout<<" Июнь \n "; break;
case 7 : cout<<" Июль \n "; break;
case 8 : cout<<" Август \n "; break;
case 9 : cout<<" Сентябрь \n "; break;
case 1 0 : cout<<" Октябрь \n "; break;
case 1 1 : cout<<" Ноябрь \n "; break;
case 1 2 : cout<<" Декабрь \n "; break;
//Если значение переменной m выходит за пределы области
//допустимых значений, то выдаётся сообщение.
default : cout<<" ОШИБКА! \n "; break;
}
return 0;
}
Циклический процесс или просто цикл это повторение одних и тех же действий. Последовательность действий, которые повторяются в цикле, называют телом цикла. Один проход цикла называют шагом или итерацией. Переменные, которые изменяются внутри цикла и влияют на его окончание, называются параметрами цикла.
При написании циклических алгоритмов следует помнить следующее. Во- первых, чтобы цикл имел шанс когда-нибудь закончиться, содержимое его тела должно обязательно влиять на условие цикла. Во-вторых, условие должно состоять из корректных выражений и значений, определённых ещё до первого выполнения тела цикла.
В С++ для удобства пользователя предусмотрены три оператора, реализующих циклический процесс: while, do...while и for.
На рис. 3.20 изображена блок-схема алгоритма цикла с предусловием. Оператор, реализующий этот алгоритм в С++, имеет вид:
while (условие) оператор;
здесь условие — логическое или целочисленное выражение, оператор — любой оператор языка С(С++) .
(рис 3.20) Алгоритм циклической структуры с предусловием
Работает цикл с предусловием следующим образом. Вычисляется условие. Если оно истинно (не равно нулю), то выполняется оператор, и условие проверяется вновь. В противном случае цикл заканчивается, и управление передаётся оператору, следующему за телом цикла. Условие вычисляется перед каждой итерацией цикла. Если при первой проверке выражение равно нулю, цикл не выполнится ни разу. Тип выражения должен быть арифметическим или приводимым к нему.
Если тело цикла состоит более чем из одного оператора, необходимо использовать составной оператор:
while (условие)
{
оператор 1;
оператор 2;
...
оператор n;
}
Рассмотрим пример. Пусть необходимо вывести на экран таблицу значений функции $$y=e^{\sin (x)}\cos (x)$$ на отрезке [0; π] с шагом 0.1. Применив цикл с предусловием, получим:
#include <stdio.h>
#include <math.h>
#define PI 3.14159
using namespace std;
int main ( )
{
float x, y; //Описание переменных
x=0; //Присваивание параметру цикла стартового значения
//Цикл с предусловием
while (x<=PI ) //Пока параметр цикла не превышает конечное значение
{ //выполнять тело цикла
y=exp ( sin ( x ) ) * cos ( x ); //Вычислить значение y
//Вывод на экран пары x и y .
printf ( " \t x =%5.2 f \t y =%5.4 f \n ",x, y );
x+=0.1; //Изменение параметра цикла
// (переход к следующему значению x )
} //Конец цикла
return 0;
}
В результате работы данного фрагмента программы на экран последовательно будут выводиться сообщения со значениями переменных $$x$$ и $$y$$:
x= 1.00 y=1.2534 x= 2.10 y=-1.1969 x= 1.10 y=1.1059 x= 2.20 y=-1.3209 x= 1.20 y=0.9203 x= 2.30 y=-1.4045 x= 1.30 y=0.7011 x= 2.40 y=-1.4489 x= 1.40 y=0.4553 x= 2.50 y=-1.4576 x= 1.50 y=0.1918 x= 2.60 y=-1.4348 x= 1.60 y=-0.0793 x= 2.70 y=-1.3862 x= 1.70 y=-0.3473 x= 2.80 y=-1.3172 x= 1.80 y=-0.6017 x= 2.90 y=-1.2334 x= 1.90 y=-0.8328 x= 3.00 y=-1.1400 x= 2.00 y=-1.0331 x= 3.10 y=-1.0416
В цикле с предусловием предварительной проверкой определяется, выполнять тело цикла или нет, до первой итерации. Если это не соответствует логике алгоритма, то можно использовать цикл с постусловием. На рис. 3.21 видно, что в этом цикле проверяется, делать или нет очередную итерацию, лишь после завершения предыдущей. Это имеет принципиальное значение лишь на первом шаге, а далее циклы ведут себя идентично.
(рис 3.21) Алгоритм циклической структуры с постусловием
В С++ цикл с постусловием реализован конструкцией
do оператор while (условие);
здесь условие — логическое или целочисленное выражение, оператор — любой оператор языка С(С++). Если тело цикла состоит более чем из одного оператора:
do
{
оператор_1;
оператор_2;
...
оператор_n;
}
while (условие);
Работает цикл следующим образом. В начале выполняется оператор, представляющий собой тело цикла. Затем вычисляется условие. Если оно истинно (не равно нулю), оператор тела цикла выполняется ещё раз. В противном случае цикл завершается, и управление передаётся оператору, следующему за циклом.
Таким образом, не трудно заметить, что цикл с постусловием всегда будет выполнен хотя бы один раз, в отличие от цикла с предусловием, который может не выполниться ни разу.
Если применить цикл с постусловием для создания программы, которая выводит таблицу значений функции $$y=e^{\sin (x)}\cos(x)$$ на отрезке [0; π] с шагом 0.1, получим:
#include <iostream>
#include <stdio.h>
#include <math.h>
#define PI 3.14159
using namespace std;
int main ( )
{
float x, y; //Описание переменных
x=0; //Присваивание параметру цикла стартового значения
do //Цикл с постусловием
{ //Выполнять тело цикла
y=exp ( sin ( x ) ) * cos ( x );
printf ( " \t x =%5.2 f \t y =%5.4 f \n ",x, y );
x+=0.1; //Изменение параметра цикла
}
while (x<=PI ); //пока параметр цикла не превышает конечное значение
return 0;
}
Результаты работы этой программы будут такими.
Кроме того, в С++ предусмотрен цикл for с параметром:
for (начальные_присваивания;условие;последействие) оператор;
где начальные_присваивания — оператор или группа операторов, разделённых условие — целое или логическое выражение, которое определяет условие входа в цикл, если условие истинно (не равно нулю), то цикл выполняется; последействие — оператор или группа операторов, разделённых запятой, которые выполняются после каждой итерации и служат для изменения параметра цикла; оператор — любой оператор языка, представляющий собой тело цикла. Последействие или оператор должны влиять на условие, иначе цикл никогда не закончится. Начальные_присваивания, выражение или последействие в записи оператора for могут отсутствовать, но при этом "точки с запятой" должны оставаться на своих местах. Опишем алгоритм работы цикла for:
начальные_присваивания.условие, если оно не равно 0 (true), то выполняется переход к п.3. В противном случае выполнение цикла завершается.оператор.последействие и осуществляется переход к п.2, опять вычисляется значение выражения и т.д.Понятно, что этот алгоритм представляет собой цикл с предусловием (рис. 3.22).
(рис 3.22) Алгоритм работы цикла с параметром
В дальнейшем, чтобы избежать создания слишком громоздких алгоритмов, в блок-схемах цикл for будем изображать, так как показано на рис. 3.23.
В случае если тело цикла состоит более чем из одного оператора, необходимо использовать составной оператор:
for (начальные_присваивания; условие; последействие)
{
оператор_1;
...
оператор_n;
}
Применение цикла for рассмотрим на примере печати таблицы значений функции $$y=e^{\sin (x)}\cos (x)$$ на отрезке [0;π] с шагом 0.1:
#include <stdio.h>
#include <math.h>
#define PI 3.14159
using namespace std;
int main ( )
{
float x, y;
//Параметру цикла присваивается начальное значение, если оно не превышает конечное значение,
//то выполняются операторы тела цикла и значение параметра изменяется, в противном случае
//цикл заканчивается.
for ( x=0;x<=PI; x+=0.1)
{
y=exp ( sin ( x ) ) * cos ( x );
printf ( " \t x =%5.2 f \t y =%5.4 f \n ", x, y );
}
return 0;
}
(рис 3.23) Блок-схема цикла с параметром
Программный код выдаст результат.
Операторы передачи управления принудительно изменяют порядок выполнения команд. В С++ таких операторов четыре: goto, break, continue и return.
Оператор goto метка, где метка обычный идентификатор, применяют для безусловного перехода, он передаёт управление оператору с меткой: метка:
Оператор break осуществляет немедленный выход из циклов while, do... while и for, а так же из оператора выбора switch. Управление передаётся оператору, находящемуся непосредственно за циклом или оператором выбора.
Оператор continue начинает новую итерацию цикла, даже если предыдущая не была завершена.
Оператор return выражение завершает выполнение функции и передаёт управление в точку её вызова. Если функция возвращает значение типа void, то выражение в записи оператора отсутствует. В противном случае выражение должно иметь скалярный тип.
Рассмотрим использование циклических операторов на конкретных примерах.
Задача 3.10. Написать программу решения квадратного уравнения $$ax^2+bx+c =0$$. Предусмотреть проверку ввода данных.
Решение квадратного уравнения было подробно рассмотрено в задаче 3.4. Однако алгоритм, изображённый на рис. 3.15, не будет работать, если пользователь введёт нулевое значение в переменную a (при попытке вычислить корни уравнения произойдёт деление на ноль). Чтобы избежать подобной ошибки нужно в программе предусмотреть проверку входных данных, например, так как показано на рис. 3.24. Вводится значение переменной a, если оно равно нулю, то ввод повторяется, иначе следует алгоритм вычисления корней квадратного уравнения. Здесь применяется цикл с постусловием, так как значение переменной необходимо ввести, а затем проверить его на равенство нулю.
(рис 3.24) Блок-схема проверки ввода данных
Программа решения задачи:
#include <iostream>
#include <math.h>
using namespace std;
int main ( )
{
float a, b, c, d, x1, x2;
//Проверка ввода значения коэффициента a .
do //Выполнять тело цикла пока а равно нулю
{
cout<<" a = "; cin >>a;
}
while ( a==0);
cout<<" b = "; cin >>b;
cout<<" c = "; cin >>c;
d=b* b-4*a*c;
if (d<0) cout<<" Нет вещественных корней";
else
{
x1=( -b+sqrt (d) ) /2/a;
x2=( -b- sqrt (d) ) /(2 *a );
cout<<" X1 = "<<x1<<" \t X2 = "<<x2<<" \n ";
}
return 0;
}
Задача 3.11. Найти наибольший общий делитель (НОД) натуральных чисел $$A$$ и $$B$$.
Входные данные: $$A$$ и $$B$$.
Выходные данные: $$A$$ — НОД.
Для решения поставленной задачи воспользуемся алгоритмом Евклида: будем уменьшать каждый раз большее из чисел на величину меньшего до тех пор, пока оба значения не станут равными, так, как показано в табл. 3.2.
| Шаг | A | B |
|---|---|---|
| Исходные данные | 25 | 15 |
| Шаг 1 | 10 | 15 |
| Шаг 2 | 10 | 5 |
| Шаг 3, НОД | 5 | 5 |
В блок–схеме, представленной на рис. 3.25, для решения поставленной задачи используется цикл с предусловием, то есть тело цикла повторяется до тех пор, пока $$A$$ не равно $$B$$. Следовательно, при создании программы воспользуемся циклом while:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int a, b;
cout<<" A = "; cin>>a;
cout<<" B = "; cin>>b;
//Если числа не равны, выполнять тело цикла
while ( a!=b)
//Если число A больше, чем B, то уменьшить его значение на B,
if ( a>b) a=a-b;
//иначе уменьшить значение числа B на A
else b=b-a;
cout<<" НОД= "<<a<<" \n ";
return 0;
}
Результат работы программы не изменится, если для её решения воспользоваться циклом с постусловием do...while:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int a, b;
cout<<" A = "; cin >>a;
cout<<" B = "; cin >>b;
do
if ( a>b ) a=a-b; else b=b-a;
while ( a !=b );
cout<<" НОД= "<<a<<" \n ";
return 0;
}
(рис 3.25) Поиск наибольшего общего делителя двух чисел.
Задача 3.12. Вычислить факториал числа $$N ( N! = 1 · 2 · 3 · ... · N)$$.
Входные данные: $$N$$ — целое число, факториал которого необходимо вычислить.
Выходные данные: factorial — целое число, значение факториала числа $$N$$, произведение чисел от 1 до $$N$$.
Промежуточные переменные: $$i$$ — параметр цикла, целочисленная переменная, последовательно принимающая значения 2, 3, 4 и так далее до $$N$$.
Блок-схема приведена на рис. 3.26.
Итак, вводится число $$N$$. Переменной factorial, предназначенной для хранения значения произведения последовательности чисел, присваивается начальное значение, равное единице. Затем организуется цикл, параметром которого выступает переменная $$i$$. Если значение параметра цикла не превышает $$N$$, то выполняется оператор тела цикла, в котором из участка памяти с именем factorial считывается предыдущее значение произведения, умножается на текущее значение параметра цикла, а результат снова помещается в участок памяти с именем factorial. Когда параметр $$i$$ превысит $$N$$, цикл заканчивается, и на экран выводится значение переменой factorial, которая была вычислена в теле цикла.
(рис 3.26) Алгоритм вычисления факториала.
Обратите внимание, как в программе записан оператор цикла. Здесь операторы ввода и операторы присваивания стартовых значений записаны как начальные присваивания цикла for, а оператор накапливания произведения и оператор модификации параметра цикла представляют собой последействие:
#include <iostream>
using namespace std;
int main ( )
{
unsigned long long int factorial;
unsigned int N, i;
for ( cout<<" N = ", cin >>N, factorial =1, i =2; i<=N; factorial*=i, i ++);
cout<<" факториал= "<<factorial <<" \ n ";
return 0;
}
Задача 3.13. Вычислить сумму натуральных чётных чисел, не превышающих $$N$$.
Входные данные: $$N$$ — целое число.
Выходные данные: $$S$$ — сумма чётных чисел.
Промежуточные переменные: $$i$$ — параметр цикла, принимает значения 2, 4, 6, 8 и так далее, также имеет целочисленное значение.
При сложении нескольких чисел необходимо накапливать результат в определённом участке памяти ($$S$$), каждый раз считывая из этого участка ($$S$$) предыдущее значение суммы ($$S$$) и прибавляя к нему слагаемое $$i$$. Для выполнения первого оператора накапливания суммы из участка памяти необходимо взять такое число, которое не влияло бы на результат сложения. Перед началом цикла переменной, предназначенной для накапливания сумы, необходимо присвоить значение нуль. Блок-схема решения этой задачи представлена на рис. 3.27.
Решим задачу двумя способами: с применением циклов while и for:
//Решение задачи с помощью цикла while
#include <iostream>
using namespace std;
int main ( )
{
unsigned int N, i, S;
cout<<" N = "; cin >>N;
S=0;
i =2;
while ( i<=N)
{
S=S+i;
i=i +2;
}
cout<<" S = "<<S<<" \n ";
return 0;
}
//__________________________________
//Решение задачи с помощью цикла for
#include <iostream>
using namespace std;
int main ( )
{
unsigned int N, i, S;
for ( cout<<" N = ", cin >>N, S=0, i =2; i<=N; S+=i, i +=2);
cout<<" S = "<<S<<" \n ";
return 0;
}
(рис 3.27) Алгоритм вычисления суммы чётных натуральных чисел.
Задача 3.14. Дано натуральное число $$N$$. Определить $$K$$ — количество делителей этого числа, меньших самого числа (Например, для $$N=12$$ делители 1, 2, 3, 4, 6. Количество $$K=5$$).
Входные данные: $$N$$ — целое число.
Выходные данные: целое число $$K$$ — количество делителей $$N$$.
Промежуточные переменные: $$i$$ — параметр цикла, возможные делители числа $$N$$.
В блок-схеме, изображённой на рис. 3.28, реализован следующий алгоритм: в переменную $$K$$, предназначенную для подсчёта количества делителей заданного числа, помещается значение, которое не влияло бы на результат, т.е. нуль. Далее организовывается цикл, в котором изменяющийся параметр $$i$$ выполняет роль возможных делителей числа $$N$$. Если заданное число $$N$$ делится нацело на параметр цикла $$i$$, это означает, что $$i$$ является делителем $$N$$, и значение переменной $$K$$ следует увеличить на единицу. Цикл необходимо повторить $$\frac{N}{2}$$ раз.
(рис 3.28) Алгоритм определения делителей натурального числа.
Текст программы на С++:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int N, i,K;
cout<<" N = "; cin >>N;
for (K=0, i =1; i<=N/ 2; i ++) if (N%i ==0) K++;
cout<<" K = "<<K<<" \n ";
return 0;
}
Задача 3.15. Дано натуральное число $$N$$. Определить, является ли оно простым. Натуральное число $$N$$ называется простым, если оно делится без остатка только на единицу и на само себя. Число 13 — простое, так как делится только на 1 и 13, а число 12 таковым не является, так как делится на 1, 2, 3, 4, 6 и 12.
Входные данные: $$N$$ — целое число.
Выходные данные: сообщение.
Промежуточные переменные: $$i$$ — параметр цикла, возможные делители числа $$N$$.
Необходимо проверить, есть ли делители числа $$N$$ в диапазоне от 2 до $$N/2$$ (рис. 3.29). Если делителей нет, $$N$$ — простое число, иначе оно таковым не является. Обратите внимание на то, что в алгоритме предусмотрено два выхода из цикла. Первый — естественный, при исчерпании всех значений параметра, а второй — досрочный. Нет смысла продолжать цикл, если будет найден хотя бы один делитель из указанной области изменения параметра.
(рис 3.29) Алгоритм определения простого числа.
При составлении программы на языке С++ досрочный выход из цикла удобно выполнять при помощи оператора break:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int N, i;
bool Pr;
cout<<" N = "; cin >>N;
Pr=true; //Предположим, что число простое
for ( i =2; i <=N/ 2; i ++)
if (N%i ==0) //Если найдётся хотя бы один делитель, то
{
Pr=false; //число простым не является и
break; //досрочный выход из цикла
}
if ( Pr ) //Проверка значения логического параметра и вывод на печать
//соответствующего сообщения
cout<<N<<" - простое число\n ";
else
cout<<N<<" - не является простым\n ";
return 0;
}
Задача 3.16. Дано натуральное число $$N$$. Определить количество цифр в числе.
Входные данные: $$N$$ — целое число.
Выходные данные: $$kol$$ — количество цифр в числе.
Промежуточные данные: $$M$$ — переменная для временного хранения значения $$N$$
Для того, чтобы подсчитать количество цифр в числе, необходимо определить, сколько раз заданное число можно разделить на десять нацело. Например, пусть $$N = 12345$$, тогда количество цифр $$kol = 5$$. Результаты вычислений сведены в табл. 3.3.
| kol | N |
|---|---|
| 1 | 12345 |
| 2 | 12345 / 10 = 1234 |
| 3 | 1234 / 10 = 123 |
| 4 | 123 / 10 = 12 |
| 5 | 12 / 10 = 1 |
| 1 / 10 = 0 |
Алгоритм определения количества цифр в числе представлен на рис. 3.30.
#include <iostream>
using namespace std;
int main ( )
{
unsigned long int N, M;
unsigned int kol;
cout<<" N = "; cin >>N;
for (M=N, kol =1; M/10 >0; kol ++,M/=10);
cout<<" kol = "<<kol <<endl;
return 0;
}
(рис 3.30) Алгоритм определения количества цифр в числе.
Задача 3.17. Дано натуральное число $$N$$. Определить, содержит ли это число нули и в каких разрядах они расположены (например, число 11011110111 содержит ноль в третьем и восьмом разрядах, а число 120405 — в первом и третьем).
Входные данные: $$N$$ — целое число.
Выходные данные: $$pos$$ — позиция цифры в числе.
Промежуточные данные: $$i$$ — параметр цикла, $$M$$ — переменная для временного хранения значения $$N$$.
В связи с тем, что разряды в числе выделяются начиная с последнего, для определения номера разряда в числе, необходимо знать количество цифр в
| i | Число М | Цифра | Номер позиции |
|---|---|---|---|
| 1 | 120405 | 120405 % 10 = 5 | 0 |
| 2 | 12040/10 = 1204 | 12040 % 10 = 0 | 1 |
| 3 | 1204/10 = 120 | 1204 % 10 = 4 | 2 |
| 4 | 120/10 = 12 | 120 % 10 = 0 | 3 |
| 5 | 12/10 = 1 | 12 % 10 = 2 | 4 |
| 6 | 1/10 = 0 | 1 % 10 = 1 | 5 |
Программный код к задаче 3.17.
#include <iostream>
using namespace std;
int main ( )
{
unsigned long int N,M; int kol, i;
cout<<" N = "; cin >>N;
for ( kol =1,M=N;M/10 >0; kol ++,M/=10);
for (M=N, i =0; i <kol;M/=10, i ++)
if (M%10==0) cout<<"Позиция = "<<i <<endl;
return 0;
}
Задача 3.18. Дано натуральное число $$N$$. Получить новое число, записав цифры числа $$N$$ в обратном порядке. Например, 17852 — 25871.
Входные данные: $$N$$ — целое число.
Выходные данные: $$S$$ — целое число, полученное из цифр числа $$N$$, записанных в обратном порядке.
Промежуточные данные: $$i$$ — параметр цикла, $$M$$ — переменная для временного хранения значения $$N, kol$$ — количество разрядов в заданном числе, $$R = 10^{kol}$$ — старший разряд заданного числа.
Рассмотрим пример. Пусть $$N = 17852$$, тогда $$S = 2 \cdot 10^4 + 5 \cdot 10^3 + 8 \cdot 10^2 + 7 \cdot 10^1 + 1 \cdot 10^0 = 25871$$.
Значит, для решения поставленной задачи, нужно знать количество разрядов в заданном числе $$kol$$ и его старший разряд $$R = 10^{kol}$$. Новое число $$S$$ формируют как сумму произведений последней цифры заданного числа на старший разряд $$S+ = M\%10 * R$$. Цикл выполняют $$kol$$ раз, при каждой итерации уменьшая само число и старший разряд в десять раз.
#include <iostream>
using namespace std;
int main ( )
{ unsigned long int N,M, R, S; int kol, i;
cout<<" N = "; cin >>N;
for (R=1, kol =1,M=N;M/10 >0; kol ++,R* =10,M/=10);
for ( S=0,M=N, i =1; i<=kol; S+=M%10*R,M/=10,R/=10, i ++);
cout<<" S = "<<S<<endl;
return 0;
}
Задача 3.19. Проверить, является ли заданное число $$N$$
Входные данные: $$N$$ — целое число.
Выходные данные: сообщение.
Промежуточные данные: $$i$$ — параметр цикла, $$M$$ — переменная для временного хранения значения $$N, kol$$ — количество разрядов в заданном числе, $$R = 10^{kol}$$ — старший разряд заданного числа, $$S$$ — целое число, полученное из цифр числа $$N$$, записанных в обратном порядке.
Можно предложить следующий алгоритм решения задачи. Записать цифры заданного числа $$N$$ в обратном порядке (задача 3.18), получится новое число $$S$$. Сравнить полученное число $$S$$ с исходным $$N$$. Если числа равны, то заданное число является палиндромом.
Текст программы на языке С++:
#include <iostream>
using namespace std;
int main ( )
{ unsigned long int N,M,R, S;
int kol, i;
cout<<" N = "; cin>>N;
for (R=1, kol =1,M=N;M/10 >0; kol++,R* =10,M/=10);
for (S=0,M=N, i =1; i<=kol; S+=M%10*R,M/=10,R/=10, i++);
if (N==S) cout<<"Число - палинром"<<endl;
else cout<<"Число не является палиндромом"<<endl;
return 0;
}
Задача 3.20. Поступает последовательность из $$N$$ вещественных чисел. Определить наибольший элемент последовательности.
Входные данные: $$N$$ — целое число; $$X$$ — вещественное число, определяет текущий элемент последовательности.
Выходные данные: $$Max$$ — вещественное число, элемент последовательности с наибольшим значением.
Промежуточные переменные: $$i$$ — параметр цикла, номер вводимого элемента последовательности.
Алгоритм поиска наибольшего элемента в последовательности следующий (рис. 3.31). Вводится $$N$$ — количество элементов последовательности и $$X$$ — первый элемент последовательности. В памяти компьютера отводится ячейка, например с именем $$Max$$, в которой будет храниться наибольший элемент последовательности — максимум. Далее предполагаем, что первый элемент последовательности наибольший и записываем его в $$Max$$. Затем вводим второй элемент последовательности и сравниваем его с предполагаемым максимумом. Если окажется, что второй элемент больше, его записывают в ячейку $$Max$$. В противном случае никаких действий не предпринимаем. Потом переходим к вводу следующего элемента последовательности ($$X$$), и алгоритм повторяется с начала. В результате в ячейке $$Max$$ сохранится элемент последовательности с наибольшим
(рис 3.31) Алгоритм поиска наибольшего числа в последовательности.
Текст программы на С++:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int i,N;
float X,Max;
cout<<" N = "; cin>>N;
cout<<" X = "; cin>>X; //Ввод первого элемента последовательности
//Параметр цикла принимает стартовое значение i =2, т.к. первый элемент
//уже введён предположим, что он максимальный, т.е. Max=X.
for ( i =2, Max=X; i<=N; i++)
{
cout<<" X = "; cin>>X; //Ввод следующих элементов последовательности.
//Если найдётся элемент, превышающий максимум, записать его в ячейку Max,
//теперь он предполагаемый максимум.
if (X>Max) Max=X;
}
//Вывод наибольшего элемента последовательности.
cout<<" Max = "<<Max<<" \n ";
return 0;
}
Задача 3.21. Вводится последовательность целых чисел, 0 — конец последовательности. Найти наименьшее число среди положительных, если таких значений
Блок-схема решения задачи приведена на рис. 3.32.
(рис 3.32) Алгоритм поиска минимального положительного числа в последовательности.
Далее приведён текст подпрограммы с подробными
#include <iostream>
using namespace std;
int main ( )
{
float N, Min; int K;
//Предположим, что в последовательности нет положительных чисел, K=0.
//Вводим число и если оно не равно нулю
for ( cout<<" N = ", cin>>N,K=0;N!=0; cout<<" N = ", cin>>N)
//проверяем является ли оно положительным.
if (N>0)
//если K=0, поступил 1-й положительный элемент, предположим, что он минимальный.
if (K==0) {K=1;Min=N; }
//если элемент не первый, сравниваем его с предполагаемым минимумом,
//если элемент меньше, записываем его в Min и сбрасываем счётчик
else if (N<Min) {Min=N;K=1;}
//если элемент равен минимуму, увеличиваем значение счётчика.
else if (N==Min) K++; //Конец цикла
//Если значение счётчика не равно нулю, печатаем значение
//минимального элемента и количество таких элементов.
if (K!=0) cout<<" Min = "<<Min<<" \n "<<" K = "<<K<<" \n ";
//в противном случае выдаём сообщаем.
else cout<<"В последовательности нет положительных элементов \n ";
return 0;
}
Задача 3.22. Определить, сколько раз последовательность из $$N$$ произвольных чисел меняет знак.
Чтобы решить задачу, нужно попарно перемножать элементы последовательности. Если результат произведения пары чисел — отрицательное число, значит, эти числа имеют разные знаки.
Пусть в переменной $$B$$ хранится текущий элемент последовательности, в $$A$$ — предыдущий. Введём первое число $$A$$ (до цикла) и второе $$B$$ (в цикле). Если их произведение отрицательно, то увеличиваем количество смен знака на 1 (k++). После чего сохраняем значение $$B$$ в переменную $$A$$ и повторяем цикл (рис. 3.33).
(рис 3.33) Алгоритм решения задачи 3.22.
Предлагаем читателю самостоятельно разобраться с текстом программы на С++:
#include <iostream>
using namespace std;
int main ( )
{
float A,B; int i,K,N;
cout<<" N = "; cin>>N;
for (K=0, cout<<" A = ", cin>>A, i =2; i<=N; i++)
{
cout<<" B = "; cin>>B;
if (A*B<0) K++;
A=B;
}
cout<<" K = "<<K<<" \n ";
return 0;
}
Задача 3.23. Поступает последовательность из $$N$$ вещественных чисел. Определить количество простых чисел в последовательности.
Блок-схема алгоритма изображена на рис. 3.34. Обратите внимание, что для решения задачи было организовано два цикла. Первый цикл обеспечивает ввод элементов последовательности. Второй цикл находится внутри первого и определяет, является ли поступившее число простым (задача 3.15).
(рис 3.34) Алгоритм поиска простых чисел в последовательности.
#include <iostream>
using namespace std;
int main ( )
{
unsigned long int X;
unsigned int N;
int i, k, j;
bool Pr;
for ( k=0, cout<<" N = ", cin >>N, i =1; i<=N; i ++)
{
for ( cout<<" X = ", cin >>X, Pr=true, j =2; j<=X/ 2; j ++)
if (X%j ==0)
{
Pr=false;
break;
}
if ( Pr ) k++;
}
if ( k==0) cout<<"Простых чисел нет \n ";
else cout<<"Количество простых чисел k = "<<k<<" \n ";
return 0;
}
Задача 3.24. Дано $$K$$ наборов ненулевых целых чисел. Каждый набор содержит не менее двух элементов, признаком его завершения является число 0. Найти количество наборов, элементы которых возрастают.
Блок-схема алгоритма решения задачи показана на рис. 3.35. Нетрудно заметить, что алгоритм реализован с помощью двух циклических процессов. Внутренний цикл проверяет является ли последовательность возрастающей, а внешний повторяет алгоритм для новой последовательности.
(рис 3.35) Алгоритм решения задачи 3.24.
Программный код решения задачи 3.24:
#include <iostream>
using namespace std;
int main ( )
{
unsigned int K, i, kol, A, B; bool pr;
for ( cout<< "K = ", cin >>K, kol =0, i =1; i<=K; i ++)
{
for ( pr=true, cout<<" A = ", cin >>A;A! = 0; A=B)
{
cout<<" B = "; cin >>B;
if (B!=0 A>=B) pr=false;
}
if ( pr ) kol++;
}
cout << " kol = " << kol <<endl;
return 0;
}
Разработать программу на языке С++. Дано вещественное число a. Для функции $$y = f(x)$$, график которой приведён ниже, вычислить $$f(a)$$. Варианты заданий представлены на рисунках ниже.
(рис 3.36) Задание 1
(рис 3.37) Задание 2
(рис 3.38) Задание 3
(рис 3.39) Задание4
(рис 3.40) Задание 5
(рис 3.41) Задание 6
(рис 3.42) Задание 7
(рис 3.43) Задание 8
(рис 3.44) Задание 9
(рис 3.45) Задание 10
(рис 3.46) Задание 11
(рис 3.47) Задание 12
(рис 3.48) Задание 13
(рис 3.49) Задание 14
(рис 3.50) Задание 15
(рис 3.51) Задание 16
(рис 3.52) Задание 17
(рис 3.53) Задание 18
(рис 3.54) Задание 19
(рис 3.55) Задание 20
(рис 3.56) Задание 21
(рис 3.57) Задание 22
(рис 3.58) Задание 23
(рис 3.59) Задание 24
(рис 3.60) Задание 25
Разработать программу на языке С++. Даны вещественные числа $$x$$ и $$y$$. Определить, принадлежит ли точка с координатами ($$x; y$$) заштрихованной области. Варианты заданий представлены на рисунках ниже.
(рис 3.61) Задание 1
(рис 3.62) Задание 2
(рис 3.63) Задание 3
(рис 3.64) Задание 4
(рис 3.65) Задание 5
(рис 3.66) Задание 6
(рис 3.67) Задание 7
(рис 3.68) Задание 8
(рис 3.69) Задание 9
(рис 3.70) Задание 10
(рис 3.71) Задание 11
(рис 3.72) Задание 12
(рис 3.73) Задание 13
(рис 3.74) Задание 14
(рис 3.75) Задание 15
(рис 3.76) Задание 16
(рис 3.77) Задание 17
(рис 3.78) Задание 18
(рис 3.79) Задание 19
(рис 3.80) Задание 20
(рис 3.81) Задание 21
(рис 3.82) Задание 22
(рис 3.83) Задание 23
(рис 3.84) Задание 24
(рис 3.85) Задание 25
Разработать программу на языке С++ для следующих заданий:
Разработать программу на языке С++. Для решения задачи использовать операторы for, while, do. Варианты заданий:
Разработать программу на языке С++ для следующих заданий:
Разработать программу на языке С++ для следующих заданий:
Разработать программу на языке С++ для следующих заданий:
Разработать программу на языке С++ для следующих заданий:
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.