Правила использования оператора цикла с параметром

1. Параметр цикла i, а также его значения ml и m2 могут быть любого типа.

2. Параметр i, а также значения ml и m2 не должны пере­определяться (менять значения) в теле цикла.

3. При завершении работы оператора for па­раметр i становится неопределенным и переменную i можно использовать в других целях.

4. Тело цикла может не выполниться ни разу, если m1>m2 для цикла for... с положительным шагом, или m1<m2 для отрицательного шага.

Пример 3.Решить предыдущую задачу табулирования функции с использованием оператора цикла for.

Схема алгоритма Программа

начало
a,b
Заголовок таблицы
x=-0.5; 2.5; 0.1  
y= Правила использования оператора цикла с параметром - student2.ru
x, y
конец

#include "stdafx.h"

#include<math.h>

int main()

{

float a, b, x, y;

printf("введите а и b ");

scanf("%f%f",&a,&b);

printf(" x y(x)\n");

for( х=-0.5; x<=2.5; x=x+0.1)

{

y=log(fabs(x))/(a*a+b*b);

printf("%8.1f %8.1f\n",x,y);

}

return 0;

}

Замечание 2.Оператор цикла while, как указывалось выше, наиболее универсальный из трех операторов цикла, используе­мых в языке С++. Однако конструкция оператора цикла for является наиболее простой. Поэтому рекомендуется там, где возможно, использовать оператор for.

Базовые алгоритмы

Для реализации циклических вычислительных процессов часто используются следующие базовые алгоритмы:

• табулирование функций;

• организация счетчика;

• накопление суммы или произведения;

• поиск минимального или максимального члена последо­вательности.

Ниже приводятся примеры программирования задач на осно­ве базовых алгоритмов.

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

Дана последовательность:

cos 1, cos 3, cos 5, ..., cos 99.

Определить количество положительных членов последова­тельности.

Решение

Представим последовательность в общем виде:

а = cos(2n -1), где п = Правила использования оператора цикла с параметром - student2.ru .

Для организации счетчика в памяти компьютера выделяется ячейка, содержимое которой должно увеличиваться на 1 каждый раз, когда встречается положительный член последовательности. В программе ячейке (счетчику) соответствует переменная целого типа, например переменная L. Работа счетчика реализуется с по­мощью оператора присваивания L=L+1. В начальный момент содержимое ячейки должно быть равно нулю. С этой целью пред­варительно осуществляется очистка ячейки оператором присваи­вания L=0.

#include "stdafx.h"

#include<math.h>

int main()

{

float a;

int n,L; // описание переменных

L=0; // очистка счетчика

for(n=1;n<=50;n++) //запуск цикла

{

a = cos(2*n – 1.0); // тело цикла

if(a>0) L = L + 1; /*переменная-счетчик увеличивается на единицу, если а>0 */

}

printf("L=%d", L); // вывод значения счетчика

return 0;

}

Задача 2. Алгоритм накопления суммы

Дана последовательность:

sin 2x, sin 4x, sin 6x, ..., sin l6x

x - заданное вещественное число.

Вычислить сумму членов последовательности, которые по модулю больше 0.3.

Решение

Общий член последовательности имеет вид:

а = sin(2nx), где n = Правила использования оператора цикла с параметром - student2.ru .

Для вычисления суммы в памяти компьютера выделяется ячейка S, к содержимому которой прибавляется член последовательности а каждый раз, когда выполняется условие Правила использования оператора цикла с параметром - student2.ru > 0.3. Накопление суммы реализуется оператором присваивания S=S+a;. В начальный момент ячейка для суммирования должна быть очищена оператором S=0;.

#include "stdafx.h"

#include<math.h>

int main()

{

float a, x, S; //описание переменных задачи

int n;

printf("Введите значение х= ");

scanf("%f",&x);

S=0;//очистка суммы

for(n=1;n<=8;n++)// запуск цикла

{

a=sin(2*n*x);

if ( abs(a)>0.3) S = S + a;/* добавление числа а в сумму, если |a|>0.3 */

}

printf("S=%6.2f",S); // вывод значения суммы на экран

return 0;

}

Задача 3. Алгоритм накопления произведения

Дана последовательность:

cos 0.1, cos 0.2, cos 0.3, ..., cos 10.

Вычислить значение: Р Правила использования оператора цикла с параметром - student2.ru где РО - произведение отри­цательных членов последовательности.

Решение

Общий член последовательности имеет вид:

y = cos x, где 0.1 Правила использования оператора цикла с параметром - student2.ru 10; Δх = 0.1.

Для реализации алгоритма накопления произведения выделяется ячейка памяти РО, в которой осуществляется последова­тельное перемножение отрицательных членов последовательно­сти с помощью оператора присваивания РО=РО*у; . В началь­ный момент в ячейку должна быть занесена единица оператором РО=1;.

#include "stdafx.h"

#include<math.h>

int main()

{

float х, у, Р, РО;

РО = 1;// установка нач. значения произведения

for (x=0.1; x<=10; x=x+0.1)//запуск цикла

{

у = cos(x);

if ( y<0) РО = РО*у;

}

Р = fabs(PO);

printf("P=%6.2f",P); //вывод на экран значения P

return 0;

}

Задача 4. Алгоритм поиска минимального члена после­довательности

Дана последовательность:

ak=ektg(2k + l); к= Правила использования оператора цикла с параметром - student2.ru .

Найти минимальный член последовательности.

Решение

Для реализации алгоритма выделяется ячейка памяти min, в которую сначала заносится первый член последовательности. Затем, начиная со второго, производится сравнение очередного вычисленного члена последовательности с содержимым ячейки min. Если текущий член последовательности меньше содержимого ячейки min, то oн переписывается в эту ячейку. В противном случае содержимое ячейки min сохраняет прежнее значение. При завершении сравнения всех членов последовательности в ячейке min остается минимальное значение.

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

Замечание 2. В начальный момент в ячейку min можно занести не первый член последовательности, а достаточно большое число, которое превышало бы область определения сравниваемых чисел (например, min=+1E6;). Тогда при сравнении с содержимым ячейки min первый член последовательности обязательно окажется меньше и перепишется в ячейку min. При поиске максимального члена последовательности в ячейку max в начальный момент заносится, наоборот, достаточно малое число, которое должно быть меньше всех сравниваемых членов последовательности (например, mах= -1Е6;). В этом случае первый из сравниваемых членов последовательности окажется больше содержимого ячейки max и запишется в эту ячейку.

Программа поиска min:

#include "stdafx.h"

#include<math.h>

int main()

{

float a, min;

int k;

min = +1E6; // нач. значение переменной min

for( k=l; k<=10;k++)

{

a = exp(1.0*k)*tan(2*k + 1.0);

if (a<min) min = a; // условие для поиска min

}

printf("min=%6.2f", min);

return 0;

}

Задача 5. Табулирование функции (или кратные циклы)

Тело цикла может содержать любой оператор, в том числе и другой оператор цикла. Структура цикла, содержащая вло­женный цикл, называется кратным циклом. Число вложений может быть произвольным. Если цикл содержит один вложенный цикл, то он называется двойным, если содержит два вложенных цикла, то является тройным и т.д. Цикл, ко­торый содержит вложенный цикл, называется внешним. Вло­женный цикл называется внутренним.

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

Внешний и внутренний циклы могут использовать любой вид операторов цикла (while, do-while, for).

Пример.Алгоритм табулирования функции с двумя пе­ременными

Вычислить значение функции:

z(x, у) = sin x + cos y

при всех х, изменяющихся на интервале [-1, 1] с шагом Δх = 0.2, и у, изменяющихся на интервале [0, 1] с шагом Δу = 0.1.

Данный алгоритм реализуется с использованием двойного цикла, в котором х примем за внешнюю переменную цикла, у - за внутреннюю переменную цикла.

#include "stdafx.h"

#include<math.h>

int main()

{

float х, у, z; // описание переменных

printf("x y z(x,y)\n"); // вывод заголовка

x= -1; // начальное значение параметра внешнего цикла

while (х<=1) // запуск внешнего цикла, если х≤ 1

{

for( y=0; y<=1; y=y+0.1) //запуск внутреннего цикла

{

z=sin(x) + cos(y); // вычисление функции

printf("%6.1f %6.1f z=%6.1f",x, y, z); // вывод

}

x=x + 0.2; // изменение параметра х на шаг

}

return 0;

}

В результате выполнения программы вид таблицы на экране будет следующим:

  x   y   z(x,y)
-1.0 0.0 z=…
-1.0 0.1 z=…
-1.0 1.0 z=…
-0.8 0.0 z=…
-0.8 1.0 z=…

Задача 6. Вычисление сумм последовательностей

Последовательности с заданным числом элементов

Пример 1.Найти сумму первых 20 элементов последовательности

S=1/2 – 2/4 + 3/8 – 4/16+…

Чтобы решить эту задачу, надо определить закономерность в изменении элементов. В данном случае можно заметить:

· Каждый элемент представляет собой дробь.

· Числитель дроби при переходе к следующему элементу возрастает на единицу.

· Знаменатель дроби с каждым шагов увеличивается в 2 раза.

· Знаки перед дробями чередуются (плюс, минус и т.д.).

Любой элемент последовательности можно представить в виде

S=z*c/d

У переменной z меняется знак (эту операцию можно записать в виде z=-z), значение переменной c увеличивается на единицу (c++), а переменная d умножается на 2 (d=d*2).

Алгоритм решения задачи можно записать в виде следующих шагов:

· Записать в переменную S значение 0. В этой ячейке будет накапливаться сумма;

· Записать в переменные z, c и d начальные значения (для первого элемента): z=1, c=1,d=2;

· Сделать 20 раз следующие две операции:

v добавить к сумме значение очередного элемента;

v изменить значения переменных z, c и d для вычисления следующего элемента.

#include "stdafx.h"

int main()

Начальные значения
{

float S, z, c, d;

int i;

S = 0; z = 1; c = 1; d = 2;

добавить элемент к сумме
for ( i = 1; i <= 20; i ++ )

{

S = S + z*c/d;

изменить переменные
z = - z;

c++;

d = d * 2;

}

printf("Сумма S = %f", S);

return 0;

}

Суммы с ограничивающим условием

Рассмотрим более сложную задачу, когда количество элементов заранее неизвестно.

Пример 2.Найти сумму всех элементов последовательности

S=1/2 – 2/4 + 3/8 – 4/16+…

которые по модулю меньше, чем 0.001.

Эта задача имеет решение только тогда, когда элементы последовательности убывают по модулю и стремятся к нулю. Поскольку мы не знаем, сколько элементов войдет в сумму, надо использовать цикл while (или do - while). Один из вариантов решения показан ниже.

#include<math.h>

#include "stdafx.h"

начальные значения
int main()

{

Запустить цикл, если а ≥0.001
float S, z, c, d, a;

S = 0; z = 1; c = 1; d = 2;

a = 1;

while ( a >= 0.001 )

добавить элемент к сумме  
{

a =fabs( c / d);

изменить переменные
S = S + z*a;

z = - z;

c ++;

d = d * 2;

}

printf("Сумма S = %f", S);

return 0;

}

Цикл закончится тогда, когда переменная a (она обозначает модуль очередного элемента последовательности) станет меньше 0.001. Чтобы программа вошла в цикл на первом шаге, в эту переменную надо записать любое значение, большее, чем 0.001.

Очевидно, что если переменная a не будет уменьшаться, то условие в заголовке цикла всегда будет истинно и программа «зациклится».

Указатели и массивы

Указатели

Указатель - это переменная, содержащая адрес области памяти. Указатели широко применяются в языке С++. В некоторых случаях без них просто не обойтись, а в некоторых программы с использованием указателей становится короче и эффективнее.

Начнем с того, что поговорим о структуре памяти любого компьютера. Как известно, память компьютера представляет последовательность 8-битовых байтов. Каждый байт пронумерован, причем нумерация начинается с нуля. Номер байта называется адресом. Иногда говорят, что адрес указывает на определенный байт. Таким образом, указатель является просто адресом байта памяти.

Язык С++ позволяет определять переменные, которые могут хранить адреса памяти. Такие переменные и называются указателями. Значение указателя сообщает о том, где размещен объект, но ничего не говорит о значении самого объекта.

Указатель
Объект     Данные или группа данных

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

Для описания переменной типа указатель используется символ *.

Формат описания:

Тип *имя;

Указатель – адрес переменной какого-то определенного типа. Этот тип сообщается компилятору при объявлении указателя.

int *x;

char *y;

Пример следует понимать так: x – это указатель на ячейку, в которой хранится целое значение, а y – указатель на однобайтовую ячейку, предназначенную для хранения символа.

Двумя наиболее важными операциями, связанными с указателями, являются операция обращения по адресу * и определение адреса &.

Операция обращения по адресу предназначена для записи или считывания значения, размещенного по адресу, содержащемуся в переменной-указателе.

Например:

int *x;

. . .

*x=5;

Операция определения адреса & возвращает адрес памяти своего операнда. Операндом должна быть переменная.

Напимер:

int *x;

int a=5;

x=&a;

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

Если у – указатель на целое, то унарная операция y++ увеличивает значение адреса, хранящегося в переменной-указателе на число равное размеру ячейки целого типа, т.е. на 2 байта; теперь оно является адресом следующей ячейки целого типа. Соответственно, оператор y--; означает, что адрес уменьшается на 2 байта.

Указатели и целые числа можно складывать. Конструкция у + n (у - указатель, n - целое число) задает адрес n-гo объекта, на который указывает у. Это справедливо для любых объектов (int, char, float и др.); транслятор будет масштабировать приращение адреса в соответствии с типом, указанным в определении объекта.

Любой адрес можно проверить на равенство (= =) или неравенство (!=), больше (>) или меньше (<) с любым другим адресом.

Рассмотрим следующий фрагмент программы:

#include "stdafx.h"

int main()

{

int *x, *w;

int y;

*x=16;

y=-15;

w=&y;

. . .

}

Этот текст можно понимать так:

Выделить память под три переменные x, w, y, где x и w –переменные типа указатель. Оператор *x=16; означает, что в ячейку, адрес которой записан в х, помещается значение 16. Затем переменной у присваивается значение -15. После чего в указатель w записывается адрес переменной y. Синтаксически текст записан правильно. Проблема заключается в том, что указатель х не инициализирован. Описание int *x; это лишь указание компилятору резервировать память, необходимую для хранения адреса целой ячейки. Но в этой памяти может оказаться адрес любой ячейки, в том числе и адрес, где хранится полезная информация, например, операционная система. Запись в такую ячейку может привести к сбою в работе компьютера. Поэтому при работе с указателями их надо правильно инициализировать. Существует 4 способа правильного задания начального значения для указателя:

1) Описать указатель глобально, т.е. вне любой функции. При этом указатель будет инициализирован безопасным нулевым адресом. Кроме того любому указателю можно присвоить безопасный нулевой адрес, например:

int *x;

x=NULL;

Гарантируется, что этот адрес не совпадет ни с одним адресом, уже использованным в системе.

2) Присвоить указателю адрес переменной. Например: w=&y;

3) Присвоить указателю значение другого указателя, к этому моменту правильно инициализированного. Например: x=w;

4) Использовать функции выделения динамической памяти malloc() и calloc(). При использовании этих функция необходимо подключать библиотеку <malloc.h>. Рассмотрим пример использования функции malloc():

x=(int*)malloc(sizeof(int));

Приведенный пример означает, что функция выделит область памяти, размер которой определит функция sizeof(). Если вы знаете размер ячейки заданного типа, то можно написать проще: x=(int*)malloc(2);

По окончанию работы программы, память, выделенную функцией malloc() рекомендуется освободить функцией free(x); Вернемся к приведенному ранее фрагменту программы:

#include "stdafx.h"

#include <malloc.h>

int main()

{ int *x, *w;

int y;

x=(int*)malloc(sizeof(int));

*x=16;

y=-15;

w=&y;

. . .

}

Теперь никаких конфликтных ситуаций при работе с указателями не возникнет. В языке С++ существует еще одна пара операторов new и delete для динамического выделения и освобождения памяти. О них мы поговорим чуть позже.

Понятие массива

Массив представляет собой упорядоченное множество однотипных элементов. В языке С++ массив описывается переменной сложной структуры. При описании массива необходимо указать:

• способ объединения элементов в структуру (одномерный, двухмерный и т.д.);

• число элементов;

• тип элементов.

Общий вид описания массива

<тип элементов> имя [число элементов];

Доступ к каждому элементу массива осуществляется с помощью индексов. Индексы задают порядковый номер элемента, к которому осуществляется доступ. В языке С++ первый элемент массива имеет индекс ноль. Число индексов определяет структуру массива: если используется один индекс, то такой массив называется одномерным, если два индекса - двухмерным, и т.д. В общем случае размерность массива может быть произвольной.

Одномерные массивы

В математике одномерному массиву соответствует n-мерный вектор, например:

Правила использования оператора цикла с параметром - student2.ru ; i = 1,…, n ,

где хi - компонента (координата) вектора;

i - номер компоненты;

п - число компонент.

Наши рекомендации