· Для корректного входа в цикл необходимо до начала цикла сделать начальные установки переменных, управляющих условием выполнения цикла. В цикле for такая установка может быть сделана в заголовке цикла.
· Необходимо позаботиться об инициализации переменной, в которой накапливается результат.
· Для выполнения в теле цикла нескольких операторов необходимо использовать составной оператор.
· В теле цикла должны присутствовать операторы, изменяющие значение переменной цикла так, чтобы цикл через некоторое число итераций завершился. В цикле for изменение значения параметра цикла выполняется в заголовке цикла.
· Условие завершения цикла должно состоять из корректных выражений и значений, определенных еще до первого выполнения тела цикла.
· Оператор break обеспечивает досрочное завершение выполнения действий в цикле. Оператор сontinue обеспечивает переход на следующую итерацию цикла, причем операторы в теле цикла, записанные после сontinue, игнорируются. Оператор return завершает выполнение функции. Нормальный ход выполнения действий в цикле может быть нарушен и оператором goto.
-------------------------------------------------------------------------------------------------
Контексты смысловых интерпретаций переменных в цикле
Многие алгоритмы используются такие решения, как подсчет количества, суммирование, определение минимального и т.п. Каждому из них соответствует свой контекст. Следующие контексты определяют наиболее распространенные смысловые интерпретации переменных.
Переменная-счетчик
Переменная-счетчик считает количество появлений в программе того или иного события, количество элементов, удовлетворяющих тому или иному условию. Ключевая фраза, определяющая смысл переменной-счетчика:
for (m = 0;...) { if (выполняется условие) m++; }
Логика данного фрагмента очевидна: переменная-счетчик m увеличивает свое значение на 1 при каждом выполнении проверяемого условия. Остается только сформулировать смысл самого условия.
В следующем примере переменная m подсчитывает количество положительных элементов в массиве размера n.
for (i = 0, m = 0; i < n; i++) if (A[i] > 0) m ++;
Необходимо также обратить внимание на то, когда «сбрасывается» сам счетчик. Если это делается однократно, то процесс подсчета происходит однократно во всем фрагменте. Если же счетчик сбрасывается при каком-то условии, то такой процесс подсчета сам является повторяющимся. В следующем примере переменная-счетчик последовательно нумерует (считает) символы в каждом слове строки с, «сбрасываясь по пробелу» (обнуляясь) между словами:
for(m = 0,i = 0; c[i]!= 0; i++)
if (c[i] == ' ') m = 0;
else m++;
Проанализируйте назначение переменных-счетчиков в примерах:
// в переменной-счетчике S считается количество положительных элементов массива А
int i, S;
int A[10]; //A[0], A[1],..., A[i],..., A[9]
for (i=0, S =0; i<10; i++)
if (A[i] > 0) S ++;
// переменная -счетчик S считает количество перемен знаков у элементов массива А
int i, S;
int A[10];
for (i = 1, S =0; i<10; i++)
if (A[i]>0 && A[i-1]<0) S++;
//предыдущий и последующий элементы имеют разные знаки
// в переменной-счетчике max считается количество расположенных подряд
// элементов массива А с возрастающими значениями, а в переменной S
// запоминается это значение
int i,S, max;
int A[10];
for (i = 1, S = 0, max = 0; i < 10; i++)
{
if (A[ i-1 ]< A[ i ]) max ++;
else { if (max > S) S = max;
max = 0;
}
}
// проверяем, является ли число а простым (переменная-счетчик S считает
// количество делителей числа)
int n, S, a;
int A[10];
for (S = 0,n = 2; n*n < a; n++) // цикл по n от 2 до √a
{ if (a % n == 0) S ++;
}
if (S == 0) printf("Good\n");
// массив in размера n сортируется по убыванию, счетчик cnt используется для подсчета // элементов, превышающих текущий, выбираемый во внешнем цикле, определяя тем самым // позицию текущего элемента в отсортированном массиве out [ cnt ]
void sort (int in[],int out[],int n)
{
int i,j, cnt;
for (i = 0; i < n; i++)
{
for (cnt = 0,j = 0; j < n; j++)
if (in[i] < in[j]) /* сколько элементов массива > текущего*/
cnt ++;
else
if (in[j]==in[i] && j>i) cnt ++;
out[ cnt ] = in[i];
}
}
-----------------------------------------------------------------------------------------
Переменная-накопитель
Смысл этой переменной – накапливать в себе полученный результат работы. Например, записанное на псевдокоде выражение for (S = 0,.. .;...;...) { вычислить k; S = S+k; } указывает, что в переменной S накапливается сумма значений k: на каждом шаге к значению переменной S добавляется новое k, и результат запоминается в том же самом S. Переменная S после вьшолнения оператора S= S+k будет содержать сумму уже с учетом текущего шага.
Для подсчета суммы элементов массива требуется обнуление переменной-накопителя S:
for (S = 0,i = 0; i<10; i++) S = S +A[i]; // сумма элементов массива
Для подсчета произведения элементов массива требуется установка переменной-накопителя P в 1:
for (P = 1,i = 0; i<10; i++) P = P*A[i]; // произведение элементов массива
В приведенных ниже примерах накапливается сумма значений, полученных разными способами и от разных источников:
for (S = 0,i = 0; i < n; i++)
S += A[i]; // сумма элементов массива A
for (S = 0,i = 0; i < n && A[i] >= 0; i++)
S += A[i]; // сумма элементов массива до первого отрицательного
for (S = 0,i = 0; i < n; i++)
if (A[i] > 0) S += A[i]; // сумма положительных элементов массива
for (S = 0,x = 0; x <= 1; x += 0.1)
S += sin(x); // сумма значений функции sin() на отрезке [0,1] с шагом 0.1
Проанализируйте работу фрагмента программы и сформулируйте назначение переменной – накопителя:
// 1
for (P = 1, i = 1; i < 10; i++)
P = P * i;
// 2
for (P = 1, i = 0; i < 10; i++)
P = P * 2;
// 3
for (i = 0, P = 1; P < n; i++)
P = P * 2;
printf("%d",i);
// 4
for ( S = 0, i = 0; i < n && A[i] >= 0; i++ )
S += A[i];
// 5
for (S = 0,i = 0; i < n; i++)
if ( A[i]>0 ) S += A[i];
// 6
for (S = 0, i = 0, k = 0; i < 10 && k == 0; i++) {
S = S + A[i];
if (A[i] <= 0) k = 1;
}
-----------------------------------------------------------------------------------------






