Операторы цикла
Операторы цикла задают многократное исполнение операторов тела цикла. В языке С++ определены три оператора цикла:
· цикл с предусловием:
while (выражение-условие)
тело_цикла
· цикл с постусловием:
do
тело_цикла
while (выражение-условие);
· цикл с параметром:
for (выражение-инициализатор;
выражение-условие; выражение-модификатор)
тело_цикла
Тело_цикла не может быть описанием или определением. Это либо отдельный (в том числе пустой) оператор, который всегда завершается точкой с запятой, либо составной оператор, либо блок (заключаются в фигурные скобки). Выражение-условие – это во всех операторах скалярное выражение (чаще всего логическое или арифметическое выражение), определяющее условие продолжения выполнения итераций цикла (если значение выражения-условия true, т.е. не равно нулю). Выражение-инициализ атор задаёт начальные значения необходимым параметрам; выполняется один раз перед первой итерации цикла; может содержать несколько выражений, разделённых запятой «,». Выражение-м одификатор задаёт изменение параметров цикла; выполняется после каждой итерации цикла; может содержать несколько выражений, разделённых запятой «,».
|
|
Прекращение выполнения цикла возможно в следующих случаях:
- ложное (false или 0) значение проверяемого выражения-условия;
- выполнение в теле цикла оператора передачи управления (break, goto, return) за пределы цикла.
Оператор while
Оператор while ("повторять, пока истинно условие") называется оператором цикла с предусловием. Он имеет следующий вид:
while (выражение-условие)
Тело_цикла
При входе в цикл вычисляется выражение-условие. Если его значение отлично от нуля (true), то выполняется тело_цикла. Затем вычисление выражения-условия и выполнение операторов тела_цикла повторяются последовательно, пока значение выражения-условия не станет ложным, т.е. равным false или 0.
Используя оператор цикла с предусловием, необходимо следить за тем, чтобы операторы тела_цикла воздействовали на выражение-условие (оно каким-то образом должно изменяться во время вычислений). В противном случае тело цикла будет выполняться бесконечно. Например, следующий оператор обеспечивает бесконечное выполнение пустого оператора в теле цикла:
// Бесконечный цикл с пустым оператором
while (1); // в качестве тела
Такой цикл может быть прекращен только за счёт событий, происходящих вне потока операций, явно предусмотренных в программе.
Оператор do…while
Оператор do ("повторять") называется оператором цикла с постусловием. Он имеет следующий вид:
|
|
do тело_цикла
while (выражение-условие);
При входе в цикл do обязательно выполняется тело_цикла. Затем вычисляется выражение-условие и, если его значение равно true (¹0), вновь выполняется тело_цикла.
К выражению-условию в цикле do требования те же, что и для цикла while – его значение должно изменяться при итерациях либо за счёт операторов тела цикла, либо при вычислениях. Пример бесконечного цикла с пустым оператором в теле_цикла:
do; while(1);
Оператор for
Оператор цикла с параметром имеет формат:
for (выражение-инициализатор;
Выражение-условие; выражение-модификатор)
Тело_цикла
Выражение-инициализатор – это выражение или определение объектов одного типа. Обычно здесь определяются и инициализируются некие параметры цикла. Определяемые параметры должны быть только одного типа, их область видимости – тело цикла. Если в качестве выражения-инициализатораиспользуется не определение, а выражение, то чаще всего его операнды разделены запятыми. Все выражения, входящие в выражение-инициализатор, вычисляются только один раз при входе в цикл. Выражение-инициализатор в цикле forвсегда отделяется "точкой с запятой" от выражения-условия, которое также завершается точкой с запятой. Даже при отсутствии выражения-инициализатора, выражения-условия и выражения-модификатора разделяющие их 2 символа "точка с запятой" всегда присутствуют.
Выражение-условие такое же, как и в циклах while и do. Если оно равно true (отлично от нуля), выполняются операторы тела_цикла. Если оно равно false (нулю), то выполнение цикла прекращается. В случае отсутствия выражения-условия следующий за ним разделитель "точка с запятой" сохраняется и предполагается, что значение выражения-условия всегда истинно.
Выражение-модификатор часто представляет собой выражение (последовательность скалярных выражений, разделённых запятыми; запятая – это операция перечисления). Это выражение вычисляется на каждой итерации после выполнения операторов тела цикла и до следующей проверки выражения-условия. Его назвают завершающим выражением цикла.
Тело_цикла может быть блоком, отдельным оператором, составным оператором и пустым оператором. Определённые в выражении-инициализаторе цикла объекты существуют только в заголовке и в теле цикла. Если результаты выполнения цикла нужны после его окончания, то их нужно сохранять во внешних относительно цикла объектах.
Рассмотрим программу, в которой приведены три формы оператора for, в каждом из которых суммируются квадраты первых k членов натурального ряда:
// Листинг 5.1. Разные формы цикла for
#include <iostream>
using namespace std;
int main() {
int k = 3, s = 0, i = 1;
for (; i <= k; ++i)
s += i*i; // Первый цикл
cout << "s(3) = " << s << endl;
s = 0; //Восстанавливаем начальное значение s
for (int i = 0, k = 4; i < k;)
s += ++i*i; // Второй цикл
cout << "s(4) = " << s << endl;
for (i = 1, s = 0, k = 5; i <= k; s += i*i, ++i)
; // Третий цикл
cout << "s(5) = " << s << endl;
return 0;
}
Результат выполнения программы:
s(3) = 14
s(4) = 30
s(5) = 55
Все переменные в первом цикле внешние, отсутствует выражение-инициализатор, в выражении-модификаторе заго-ловка изменяется параметр цикла i. После выполнения цикла результат сохраняется в переменной s. Перед вторым циклом значение s обнуляется. Выражение-инициализатор второго цикла определяет локализованные в цикле переменные i и k. В заголовке отсутствует завершающее выражение, а параметр цикла изменяется в его теле (вне заголовка). Выражение-инициализатор третьего цикла – выражение, операнды которого разделены запятыми. В этом выражении подготавливается выполнение цикла (обнуляются значения i и s) и присваивается значение переменной k. Необходимая сумма вычисляется в выражении-модификаторе, а тело третьего цикла – пустой оператор.
|
|
Последовательность выполнения цикла for следующая. Определяются и инициализируются объекты или вычисляется выражение из выражения-инициализатора. Вычисляется значение выражения-условия. Если оно равно true (отлично от нуля), выполняются операторы тела_цикла. Затем вычисляется выражение-модификатор, вновь вычисляется выражение-условие и проверяется его значение. Далее цепочка действий повторяется.
При выполнении цикла for выражение-условие может изменяться либо при вычислении его значений, либо под действием операторов тела цикла, либо под действием завершающего выражения. Если выражение-условие не изменяется либо отсутствует, то цикл бесконечен. Следующие операторы обеспечивают бесконечное выполнение циклов:
for (;;);//Бесконечный цикл, тело – пустой оператор
for (;0.5;) cout << "Hello!\n"; // Бесконечный цикл
Разрешено и широко используется вложение любых циклов в любые циклы.
Операторы передачи управления
Оператор break
Оператор break служит для принудительного выхода из цикла или оператора-переключателя.
В случае цикла не проверяются и не учитываются условия дальнейшего продолжения итераций. Оператор break прекращает выполнение оператора цикла или оператора-переключателя и осуществляет передачу управления (переход) к следующему за циклом или переключателем оператору. Оператор break нельзя использовать нигде, кроме циклов, условных операторов и операторов-переключателей.
Необходимость в использовании оператора break в теле цикла возникает, когда условия продолжения итераций нужно проверять не в начале итерации (циклы for, while), не в конце итерации (цикл do), а в середине тела цикла. В этом случае тело цикла может иметь такую структуру:
{ // операторы
if (условие) break;
// операторы
}
Циклы и операторы-переключатели могут быть многократно вложенными. Однако следует помнить, что оператор break позволяет выйти только из самого внутреннего цикла или переключателя в область, его объемлющую. При многократном вложении циклов и переключателей оператор break не может организовать передачу управления из самого внутреннего уровня непосредственно на самый внешний.
|
|
Рассмотрим программу, в которой вычисляется произведение чисел последовательности 2, 7, 12,..., 152 до тех пор, пока произведение не станет больше 200.
// Листинг 5.2
#include <iostream>
using namespace std;
int main() {
int p = 1, mn = 2;
while (mn <= 152) {
p *= mn;
// Выход из цикла, если произведение
if (p > 200) break; // стало больше 200
cout << p << endl;
mn += 5;
}
cout << "p = " << p << endl;
return 0;
}
Результат выполнения программы:
p = 2856
Оператор continue
Оператор continue применяется только в операторах цикла. С его помощью завершается текущая итерация и начинается проверка условия дальнейшего продолжения цикла, т.е. условий начала следующей итерации цикла.
Рассмотрим программу, вычисляющую сумму натуральных чисел, не больших 150, которые делятся нацело на 17 и на 4.
// Листинг 5.3
#include <iostream>
using namespace std;
int main() {
int sum = 0, i = 0;
do {
i += 17;
// Если очередное слагаемое не делится
// на 4,переходим к следующей итерации
if (i%4!= 0) continue;
sum += i;
} while (i <= 150);
cout << "sum = " << sum << endl;
return 0;
}
Результат выполнения программы:
sum = 204
Рассмотрим задачу вычисления при значении x с точностью ε значения функции ch(x) (гиперболический косинус) с помощью бесконечного ряда Тейлора по формуле:
и при этом же значении x вычислить гиперболический косинус с помощью функции cosh(x) из стандартной библиотеки.
Решение:
Этот ряд сходится при . Для достижения заданной точности требуется суммировать члены ряда, абсолютная величина которых больше ε. Для сходящегося ряда модуль члена ряда Cn при увеличении n стремится к нулю. При некотором n неравенство перестает выполняться и вычисления прекращаются.
Для уменьшения количества выполняемых действий следует воспользоваться рекуррентной формулой получения последующего члена ряда через предыдущий Cn +1 = T*Cn, где T – некоторый множитель. Подставив в эту формулу Cn и Cn +1, получим выражение для вычисления T:
Рассмотрим программу для решения данной задачи.
//Листинг 5.4
#include<iostream>
#include<cmath>
using namespace std;
int main() {
//Установка поддержки русского языка
//в Visual Studio
setlocale(LC_CTYPE,"Russian");
//именованная константа
const int MAXITER = 500;
double x, eps;
int n;
// признак достижения точности
bool done = true;
// первый член ряда и нач. значение суммы
double ch = 1, y = ch;
// ввод с клавиатуры значения x
cout<<"x= ";
cin>>x;
// ввод с клавиатуры значения eps
cout<<"eps= ";
cin>>eps;
for (n = 0; fabs(ch) > eps; n++)
{
// очередной член ряда
ch *= x*x/(2*n+1)/(2*n+2);
// добавление члена ряда к сумме
y += ch;
if (n > MAXITER)
{
cout<<"Ряд расходится\n";
done = false; break;
}
}
if (done)
{
cout<<"Результаты:\n";
//вывод вычислений
cout<<"x = "<<'\t'<<"y = "<<y<<'\t'
<<"n = "<<n
<<'\t'<<"Ch = "<<cosh(x)<<'\n';
}
return 0;
}
Задание. Создать программу на языке С++ для вычисления с точностью ε и вывода на экран в виде таблицы значений функции, заданной с помощью ряда Тейлора, на интервале от x нач до x кон c шагом dx. Таблицу снабдить заголовком и шапкой. Каждая строка таблицы должна содержать значение аргумента x, значение функции (вычисленное как сумма членов ряда), количество просуммированных членов ряда для обеспечения заданной точности, значение функции (вычисленное с помощью вызова функции стандартной библиотеки).
Вариант 1
Вариант 2
Вариант 3
Вариант 4
Вариант 5
Вариант 6
Вариант 7
Вариант 8
Вариант 9
Вариант 10
Вариант 11
Вариант 12
Вариант 13
Вариант 14
Вариант 15
;
(Ареа-тангенс )
Вариант 16
Вариант 17
Вариант 18
(Ареа-котангенс )
Вариант 19
Вариант 20
Практическое занятие 6. Указатели. Одномерные массивы в языке С++
Указатели
Указатель – это переменная, в которой хранится адрес другого объекта (другой переменной или начало области памяти).
Значениями указателей служат адреса участков памяти, выделенных для объектов конкретных типов. Указатели делятся на три категории – указатели на объекты, указатели на void и указатели на функции. Выделение этих категорий связано с отличиями в свойствах и правилах использования указателей. Указатели на функции будут рассмотрены позже. Рассмотрим указатели на объекты.
Простейшее объявление указателя на объект имеет вид:
тип_указателя * имя_указателя;
где тип_указателя – обозначение типа, символ «*» в этом контексте используется для объявления переменной-указателя на объект указанного типа, имя_указателя – идентификатор. Тип указателя может быть любым, кроме ссылки и битового поля, причём тип может быть к этому моменту только объявлен, но еще не определён (в структуре, например, может присутствовать указатель на структуру того же типа).
Для того чтобы определить несколько указателей на объекты одного и того же типа, символ * помещают перед каждым именем. Например, определение
int *p1, *p2, k;
вводит два указателя на объекты целого типа с именами p1, p2 и переменную k целого типа.