Общие сведения
К циклическим программам приводят задачи, в которых часть действий выполняется многократно.
Пусть необходимо протабулировать функцию F(x) на интервале [a,b] c шагом h (где, F(x)=xsin(x), a<b, h>0) и вывести полученные значения функции и аргумента.
Протабулировать функцию - значит вычислить значения функции -F(х) на отрезке [a, b] в точках а, a + h, a + 2h и т.д.
Графическая схема алгоритма приведена на рис.12, программа – в примере pr13.
// Пример pr13
#include <stdio.h>
#include <conio.h>
#include <math.h>
void main()
{ float x,y,a,b,h;
printf("\nBведите a,b,h:");
scanf("%f %f %f,&a,&b,&h);
x=a;
43
{
y=x*sin(x);
printf("\nx=%7.2f, y=%7.2f ",x,y);
x=x+h; // К "старому" значению х добавляется h
// и результат пересылается снова в х
} while (x ≤ b);
getch();
}
Рис. 12
В этой программе оператор цикла используется для многократного выполнения группы операторов, расположенных между словами do while. Каждый раз в цикле вычисляется значение у, выводятся х и у, задается новое значение х и проверяется, не выходит ли х за пределы интервала. В результате работы этой программы будут напечатаны в два столбика значения х и у.
Оператор цикла с постусловием
В
44
do <оператор> while(<условие>)
Здесь do, while - ключевые слова (перев. с англ.: выполнять и пока);
<оператор> - любой оператор C++ в том числе и составной (его называют телом цикла);
<условие>,- выражение типа сравнения, используемое для выхода из цикла. Оператор работает следующим образом: сначала выполняются, операторы, расположенные в теле цикла, затем вычисляется условие и, если получается ложное значение, осуществляется выход из цикла. Если значение выражения истинно, то выполнение операторов тела цикла повторяется, а затем снова проверяется условие. Итак, операторы тела цикла выполняются хотя бы раз, а потом все зависит от условия выхода из цикла. Очевидно, один из операторов тела цикла должен влиять на значение условного выражения, поскольку иначе цикл будет повторяться бесконечно.
Проиллюстрируем использование оператора цикла с постусловием на примере, в котором выводятся нечетные числа, меньшие 10. Схема алгоритма приведена на рис.13, программа в примере - рr14.
// Пример pr14
#include <stdio.h>
#include <conio.h>
void main()
{
int i;
i=l;
do
{
printf("\n%d",i);
i=i+2;
}
while (i<=10);
getch();
}
В результате работы этой программы будут напечатаны в столбик все нечетные числа от 1 до 9.
Оператор цикла с предусловием
В отличие от оператора цикла с постусловием оператор цикла с предусловием вычисляет и проверяет условие до выполнения операторов, составляющих тело цикла. Синтаксис этого оператора следующий:
while (<условие>) <оператор>;
Здесь while - ключевое слово (перев. с англ.: пока);
<
45
Рис. 13
<условие> - выражение типа сравнения, используемое для выхода из цикла.
Оператор работает следующим образом: сначала вычисляется условие и, если получается истинное значение, выполняется оператор, являющийся телом цикла, а затем снова проверяется условие. Если значение условного выражения ложно, то осуществляется выход из цикла. Таким образом, если условие было ложно при первом входе в цикл, то операторы тела цикла не выполнятся ни разу. Очевидно, один из операторов тела цикла должен влиять на значение условного выражения, поскольку иначе цикл будет повторяться бесконечно. Например, следующий фрагмент программы будет печатать сообщение бесконечное число раз, так как отсутствуют в цикле конструкции, изменяющие величину i:
i=1;
while(i<5)
printf("Доброе утро!");
Чтобы получить работающий фрагмент программы, добавим в тело цикла оператор, увеличивающий значение i;
i=1;
while(i<5)
{ printf(" Доброе утро! ");
i=i+1;
46
Рис. 14
// Пример pr15
#include <stdio.h>
#include <conio.h>
void main()
{
float number, //вводимое число
sum; //сумма вводимых чисел
int c; //количество вводимых чисел
const float stopcod=-1;
sum=0;
с=0;
pririif("Bведите первое число последовательности:");
scanf("%f,&number);
while (number!=stopcod)
{
47
c=c+1;
printf("Bвeдитe следующее число последовательности:");
scanf("%f ",&number);
} if (c==0) printf("Среднее значение равно нулю");
else printf("Cpeднee значение равно = %f ",sum/c);
getch(); }
Необходимо отметить, что перед первым, вхождением в цикл while значение number должно быть прочитано, иначе number'не будет определено при первой проверке условия while. Если первым вводимым числом оказался стоп-код, то тело цикла не выполнится ни cразу, счетчик с останется равным нулю, и чтобы не произошло деление на нуль, используется условный оператор.
Кроме того, в этой программе впервые появилась константа stopcod, в отличие от переменной она не может получить новое значение в программе.
Следующий пример иллюстрирует работу оператора цикла с предусловием на задаче, вычисляющей с точностью е сумму следующего ряда: s=1+1/2+1/3+1/4+ ... .
Вычислить сумму ряда с точностью е значит завершить суммирование членов ряда тогда, когда очередной член ряда окажется меньше е по абсолютной величине. Схема алгоритма приведена на рис.15, программа – в примере pr16
// Пример рr16
#include <stdio.h>
#include <conio.h>
void main()
{ int i;
float е,// точность
k // очередной член ряда
sum; // суммаa ряда
sum=0;
i=1;
printf("Bведите точность:");
scanf("%f ",&e);
k=1/ i;
while (k>e) // пока очередной член ряда больше точности
{
sum=sum+k;
i=i+1;
k=1/ i;
}
48
getch();
}
Рис. 15
Оператор цикла со счетчиком
В циклах со счетчиком выполнение тела цикла должно повторяться заранее определенное число раз. Хотя такой цикл можно организовать с помощью оператора цикла с постусловием или предусловием (они универсальны), в языке C++ имеется специальная конструкция для организации циклов со счетчиком. Синтаксис оператора цикла со счетчиком в общем случае следующий:
for(<п.ц.>=<н.з.> ; <условие> ; <коррекция п.ц.>)
<
49
Здесь for - ключевое слово (перев. с англ, для);
<п.ц.> - переменная цикла, которая может быть только простого типа;
<н.з.> - начальное значение - выражение такого же простого типа, как и переменная цикла;
<условие> - выражение типа сравнения, используемое для выхода из цикла.
<коррекция п.ц.> - оператор присваивания, задающий изменение переменной цикла;
<оператор> - любой оператор C++, в том числе и составной, являющийся телом цикла.
Оператор работает следующим образом: сначала вычисляется выражение, соответствующее начальному значению, и присваивается переменной цикла, потом проверяется условие выхода из цикла и, если получается истинное значение, выполняется оператор, являющийся телом цикла. Затем изменяется переменная цикла и снова проверяется условие и т. д. Если значение выражения ложно, то осуществляется выход из цикла.
Если начальное значение переменной цикла больше конечного значения, то операторы тела цикла не выполняются. Можно сказать, что оператор цикла со счетчиком - это оператор цикла с предусловием. Таким образом, следующий оператор не приведет к выполнению каких-либо операций: for(i=l; i<0; i++) printf("i=%d \n",i);
Следующий оператор распечатает целые числа от 1 до 10:
for(i=l; i<10; i++) printf("i=%d\n",i);
Если нужно выполнить несколько операторов в теле цикла, то пользуются составным оператором:
for(i=5; i<= 10; i++)
{
k=i*i;
printf("k=%d\n",k);
}
Теперь следует подчеркнуть гибкость оператора цикла со счетчиком [3]:
Можно применять операцию уменьшения для счета в порядке убывания
for(i=10; i>0; i--)
printf("%d ceкунд! \n",i);
printf("Пуск!\n");
Можно вести счет двойками, десятками и т. д.
for(i=5; i<100; i+=15) printf("i=%d\n",i);
В этом примере будут напечатаны 5,20,35,50,65,80,95.
Можно вести подсчет с помощью символов, а не только чисел
for(ch='a'; 'ch<'z'; ch++)
p
50
При выполнении этого оператора будут выведены все буквы от а до z вместе с их кодами ASCII. Символы в памяти размещаются в виде чисел, поэтому в данном фрагменте на самом деле счет ведется с использованием целых чисел.
Можно проверить выполнение некоторого произвольного условия, отличного от условия, налагаемого на число итераций
for(i=2; i*i*i<100; i++) printf("i*i*i=%d\n",i*i*i);
Можно сделать так, чтобы значение некоторой величины возрастало в геометрической, а не в арифметической прогрессии
for(debt=100.0; debt<150; debt=debt*1.1)
printf("Ваш долг теперь $%.2f\n",debt);
В качестве оператора, корректирующего переменную цикла, можно использовать любой правильно составленный оператор. Он будет выполняться при каждой итерации цикла.
у=0;
for(x=1;y<=75;y=5 *x++ + 50)
printf("x=%d y=%d\n",x,y);
Результат будет выглядеть так:
х =1 у =0
х = 2 у = 55
х = 3 у = 60
х = 4 у = 65
х = 5 у = 70
х = 6 у = 75
В приведенном примере продемонстрирован плохой стиль программирования, так как в управлении оператором цикла участвуют две переменные х и у.
Можно опустить любое из трех выражений в круглых скобках, но при этом нельзя пропустить точку с запятой. у=2; for(x=3;y<=25;) у=у*х;
При выполнении цикла х остается равной 3. Значение у вначале будет равно 2, потом увеличится до 6, 18, а затем будет получена окончательная величина 54. Можно опустить все три выражения в круглых скобках:
for(;;)
printf("Хочу учиться! \n");
Данный оператор будет выполняться бесконечное число раз, поскольку пустое выражение всегда истинно.
Первое выражение не обязательно должно инициализировать переменную. Вместо этого, например, там мог бы стоять оператор printf().
for(printf("Bведите числа! \n");num==6;)
s
51
В этом фрагменте первое сообщение будет выведено на печать один раз, затем осуществляется прием чисел, пока не будет введено число 6.
В круглых скобках первое и третье выражение могут содержать не по одному оператору, а несколько операторов разделенных запятой (говорят: использовать операцию запятая).
for(i=1, f=1; i<=10; f=f*i, i++);
В этом случае i=1, f=1 выполняется один раз, а f=f*i, i++ в каждой итерации цикла, пока i<=10.
Большая свобода выбора вида выражений, управляющих работой оператора цикла for, позволяет с помощью этой конструкции делать гораздо больше, чем просто выполнить фиксированное число итераций.
Пример полной программы рассмотрим на решении задачи нахождения суммы n первых членов ряда:
10 102 103
s = — + —— + ——— + ...
1 1*2. 1*2*3
Схема алгоритма приведена на рис. 16, а программа представлена в примере рr17.
// Пример рr 17
#include <stdio.h>
#include <conio.h>
void main()
{
int i,n;
float sum, // сумма ряда
k; // очередной член ряда
sum=0;
printf("Bведите число членов ряда:");
scanf("%d",&n);
k=1;
for(i=1; i<=n; i++)
{
k=k*10.0/ i;
sum=sum+k;
}
printf("Cyмма ряда =%f ",sum);
getch();
}
Г
52
Рис. 16
for(i=1; i<=n; i++)
if(a[i]) k++;
else break;
В данном примере выход из цикла произойдет, когда i станет больше n или когда встретится нулевое a[i].
Другим оператором, изменяющим обычный ход выполнения оператора цикла, является оператор continue. Этот оператор приводит к пропусканию той части тела цикла, которая расположена после оператора continue, и перехода на новую итерацию цикла:
for(i=1; i<=1000; i++)
{
if(i%13) continue;
printf("i=%d\n",i);
53
Контрольные вопросы
1. Определить значение переменной s после выполнения следующих операторов:
float s=0;
int i=0;
while(i<5) i++; s+=1/ i;
2. Определить значение переменной s после выполнения следующих операторов:
float s=0;
int i=0;
while(i<5) { i++; s+=1./ i; }
3. Определить значение переменной s после выполнения следующих операторов:
float s=0;
int i=0;
do
{ i++; s+=1./ i; }
while(i<5)
4. Чем отличается оператор цикла с предусловием от оператора цикла с постусловием?
5. Какие возможности предоставляет оператор цикла со счетчиком?
6. Для чего используются в операторах цикла операторы break, continue.
7. Можно ли изменять переменную цикла в операторе цикла со счетчиком с шагом 0.1?
8. Составьте фрагмент схемы алгоритма, соответствующий следующему фрагменту программы: for (i=0; i<n; i=i+2) k=k*i;
9. Какие ошибки допущены в следующем фрагменте программы:
for (i=0; i<n) {k=k*i; ; i=i+2}
10. Напишите программу, вычисляющую s = 1!+2!+...+n! (n>1).
Варианты заданий
1. Не используя стандартные функции (за исключением abs), вычислить сумму следующего ряда с заданной точностью Е > 0 (Е вводится с клавиатуры):
.
2. Не используя стандартные функции (за исключением abs), вычислить сумму n первых членов следующего ряда (n вводится с клавиатуры):
54
3. Дано действительное число x. Не используя стандартные функции (за исключением abs),вычислить сумму следующего ряда с заданной точностью Е>0 (Е, х вводятся с клавиатуры):
.
4. Дано действительное число x. Не используя стандартные функции (за исключением abs), вычислить сумму n первых членов следующего ряда (n, x вводятся с клавиатуры):
.
5. Дано действительное число х. Не используя стандартные функции, вычислить сумму следующего ряда с заданной точностью Е>0 (Е, х вводятся с клавиатуры):
.
6. Дано действительное число х. Не используя стандартные функции (за исключением abs), вычислить сумму n первых членов следующего ряда (n, х вводятся с клавиатуры):
.
7. Дано действительное число x. Не используя стандартные функции (за исключением abs), вычислить сумму следующего ряда с заданной точностью Е>0 (Е, х вводятся с клавиатуры):
.
8. Дано действительное число х. Не используя стандартные функции (за исключением abs), вычислить сумму n первых членов следующего ряда (n, х вводятся с клавиатуры):
.
9. Не используя стандартные функции (за исключением abs), вычислить сумму n первых членов следующего ряда (n вводится с клавиатуры):
.
10. Дано натуральное число n и действительное числo а. Вычислить n первых членов следующего ряда (n, а вводятся с клавиатуры):
.
11. Дано действительное число a. Вычислить сумму следующего ряда с заданной точностью Е > 0 (Е, а вводятся с клавиатуры):
55
12. Не используя стандартные функции (за исключением abs), вычислить сумму следующего ряда с заданной точностью Е > 0 (Е вводится с клавиатуры):
.
13. Не используя стандартные функции (за исключением abs), вычислить сумму n первых членов следующего ряда (n вводится с клавиатуры):
.
14. Не используя стандартные функции (за исключением abs), вычислить сумму следующего ряда с заданной точностью Е>0 (Е вводится с клавиатуры):
.
15. Не используя стандартные функции (за исключением abs), вычислить сумму n первых членов следующего ряда (n вводится c клавиатуры):
.
16. Не используя стандартные функции (за исключением abs), вычислить сумму следующего ряда с заданной точностью Е > 0 (Е вводится с клавиатуры):
.
17. Не используя стандартные функции (за исключением abs), вычислить сумму следующего ряда с заданной точностью Е > 0 (Е вводится с клавиатуры):
.
18. Вычислить сумму следующего ряда с заданной точностью Е > 0 (Е вводится с клавиатуры):
.
19. Не используя стандартные функции (за исключением abs), вычислить сумму следующего ряда с заданной точностью Е > 0 (Е вводится с клавиатуры):
.
20. Не используя стандартные функции (за исключением abs), вычислить сумму следующего ряда с заданной точностью Е > 0 (E вводится с клавиaтуры):
56
21. Дано действительное число х. Не используя стандартные функции (за исключением abs и sin), вычислить сумму следующего ряда с заданной точностью Е > 0 (Е, х вводятся с клавиатуры):
.
22. Дано действительное число х. Не используя стандартные функции (за исключением abs и sin), вычислить сумму n первых слагаемых следующего ряда (х вводится с клавиатуры):
.
23. Дано действительное число х. Не используя стандартные функции (за исключением abs и cos), вычислить сумму следующего ряда с заданной точностью Е > 0 (Е, х вводятся с клавиатуры):
.
24. Дано действительное число х. Не используя стандартные функции (за исключением abs и cos), вычислить сумму n первых слагаемых следующего ряда (х, n вводятся с клавиатуры):
.
25. Не используя стандартные функции, вычислить сумму n первых членов следующего ряда (n вводится с клавиатуры):
.
57
ЛАБОРАТОРНАЯ РАБОТА №4
ОБРАБОТКА ОДНОМЕРНЫХ МАССИВОВ
Цель работы:
ознакомиться с обработкой одномерных массивов с использованием индексов и с использованием указателей, операторами цикла;
Порядок выполнения работы:
В соответствии с поставленной задачей необходимо разработать графическую схему алгоритма, составить два варианта программы (один с индексами, другой с указателями) и отладить их в среде C++, продемонстрировать преподавателю, как изменяются основные переменные в отладочном окне при выполнении программы по шагам, подготовить отчет, ответить на кон контрольные вопросы и защитить лабораторную работу перед преподавателем.
