Цикл do.while предпочтителен, если необходимо выполнить хотя бы одну итерацию или если инициализация объектов, участвующих в управлении состоянием, происходит в теле цикла.
Циклы
Вам может потребоваться повторить действие определенное количество раз или выполнить его до выполнения условия. Для этого в Си используются три типа циклов: с предусловием, с постусловием и цикл for со счетчиком (хотя это условное название, поскольку счетчика может и не быть).
Цикл состоит из тела и проверки условия для завершения цикла. Тело цикла состоит из серии повторяющихся утверждений. Каждая итерация цикла называется итерацией.
Рассмотрим цикл с условием.
int i = 0; while (i
Этот цикл выполняется до тех пор, пока выполняется условие, указанное после ключевого слова while. Основная часть цикла состоит из двух строк, одна из которых выводит число, а другая изменяет его. Очевидно, что этот цикл выполняется 10 раз и выводит 0 1 2 3 и т.д. до 9.
Очень важно, чтобы условие выхода из цикла никогда не выполнялось, иначе произойдет зацикливание и программа не завершится. Например
int i = 0; while (i
В этом цикле переменная i, которая используется для задания условия остановки, не изменяется, поэтому цикл не завершается.
int i = 0; while (i>0)
В этой программе цикл, конечно, завершится, но из-за недопустимого действия он выполнится гораздо больше 10 раз. Поскольку c не отслеживает переполнение переменной, мы должны подождать, пока переменная не переполнится и не станет меньше нуля.
int i; while (i
Этот пример имеет неопределенное поведение. Поскольку переменная i не инициализирована заранее, в ней хранится мусор — неизвестное значение. При различном содержании переменной i ее поведение меняется.
Если тело цикла while содержит оператор, квадратные скобки можно опустить.
int i = 0; while (i<10) printf("%d\n", i++);
Здесь переменная i увеличивается при вызове функции printf. Такого типа кодирования следует избегать. Пропуск фигурных скобок, особенно в начале обучения, может привести к ошибкам. Кроме того, код читается хуже, а лишние скобки не сильно раздувают запись.
Циклы с постусловием.
Цикл с постусловиями отличается от цикла while тем, что условие проверяется после выполнения цикла, что означает, что цикл повторяется как минимум один раз (в отличие от цикла while, который может вообще не выполняться). Синтаксис цикла
сделать<тело цикла>while(condition),
Предыдущий пример с циклом do будет выглядеть следующим образом.
int i = 0; doпока(i<10);
Рассмотрим пример использования цикла с метаусловием и предусловием. Предположим, нам нужно завершить функцию.
Интеграл представляет собой сумму бесконечно малых. Мы можем представить интеграл в виде суммы и просто заменить бесконечно малые значения на малые.
∫ a b f &ApplicationFunction; x d x = ∑ i = a b f &ApplicationFunction; i h
Из формулы мы разделили площадь под графиком на ряд прямоугольников, где высота прямоугольника - значение функции в точке, а ширина - наш шаг. Суммируя площади всех прямоугольников, мы получаем значение интеграла с некоторой погрешностью.
Предположим, что искомая функция - x 2. Нам нужны следующие переменные. Во-первых, накопительная сумма для хранения интеграла. Во-вторых, левая и правая границы a и b и, в-третьих, шаг h. Нам также необходимо текущее значение определяющего члена x функции.
Чтобы найти интеграл, перейдите от a к b с шагом h и прибавьте к сумме площадь прямоугольника со сторонами f(x) и h.
#include #include int main()printf("%.3f", sum); getch();>
Программа выдает 0,328.
∫ 0 1 x 2 d x = x 3 3 | 0 1 = 1 3 ≈ 0,333
Если мы посмотрим на график, то увидим, что каждый раз мы находим значение функции в левой точке. Поэтому этот метод численного интегрирования называется методом левого прямоугольника. Аналогичным образом мы можем найти нужное значение. Тогда это будет метод прямоугольника.
Сумма в этом случае равна 0,338. Лево- и правоортогональные методы не очень точны. Мы аппроксимировали (приблизили) гладкий график монотонно возрастающей функции гистограммой. Если немного подумать, то аппроксимация может быть выполнена не только добавлением прямоугольников, но и трапеций.
Аппроксимация с помощью трапеций на самом деле является кусочной аппроксимацией с помощью кривых первого порядка (ax+b). Мы соединяем точки на графе отрезками. Его можно усложнить, соединяя точки не с отрезками, а с частями параболы, тогда он становится методом Симпсона. Если усложнить его еще больше, можно получить сплайн-интерполяцию, но это еще одна очень долгая дискуссия.
Давайте вернемся к нашим барашкам. Рассмотрим четыре петли.
int i = 0; while ( i++
int i = 0; while ( ++i
int i = 0; dowhile(i++<3);
int i = 0; dowhile(++i<3);
Если вы запустите эти примеры, то заметите, что циклы выполняются от двух до четырех раз. Вы должны обратить на это внимание, потому что неправильное изменение счетчика цикла часто приводит к ошибкам.
Часто бывает необходимо выйти из цикла, не дожидаясь появления флага или изменения значения переменной. По этой причине мы используем оператор break для прерывания цикла.
Цикл for
Одним из наиболее часто используемых является цикл for со счетчиком. Его синтаксис таков
Например, выведем квадраты первых ста чисел.
int i; for (i = 1; i
Одна из приятных особенностей цикла for заключается в том, что он работает не только с целыми числами.
float num; for (num = 5.3f; num>0f; num -= 0.2)
Этот цикл печатает числа от 5.3 до 0.1. В цикле for могут отсутствовать некоторые блоки кода, например, инициализация, проверка (тогда цикл становится бесконечным) или изменение счетчика. Ниже приведен пример интеграла, реализованного с помощью счетчика for
#include #include int main()printf("%.3f", sum); getch();>
Давайте посмотрим на красивый фрагмент кода
double x ; for (x = a; x
Его можно изменить следующим образом
double x = a; for (; x
Кроме того, оператор break может быть использован для разрыва условия и выполнения условия
double x; for (x = a;; x += h)b) sum += x*x*h;>
double x = a; for (;;;;)b) sum += x*x*h; x += h;>
Кроме того, вы можете использовать оператор "," для передачи части энергии
double x ; for (x = a;; xПРИМЕЧАНИЕ: Хотя вы можете сделать это таким образом, пожалуйста, не делайте этого так! Это делает код нечитаемым и приводит к ошибкам, которые трудно заметить.
Давайте решим более сложную практическую задачу. Предположим, у нас есть функция f(x). Найдите максимум его производной на отрезке. Как можно численно определить производную функции? Очевидно, по определению). Производная функции в точке является тангенсом угла наклона касательной.
Возьмем точку на кривой с координатами (x; f(x)), переместим ее вперед на шаг h и получим точку (x+h, f(x+h)), тогда производная имеет вид
d x d y = f &ApplicationFunction- ( x + h ) - f &ApplicationFunction- x ( x + h - x ) = tg &ApplicationFunction- a
То есть, отношение между малым приращением функции и малым приращением члена. Внимательный читатель может задаться вопросом, почему мы движемся вперед в этой функции, а не назад. Давайте двигаться в обратном направлении.
Если мы возьмем среднее значение этих двух величин, то получим
В общем, задача становится тривиальной: перейдите из точки a в точку b и найдите минимальное значение производной и точку, в которой производная принимает это значение. Для решения задачи нам, как и в интегральной задаче, необходимы переменные для границ области поиска a и b, текущее значение x и шаг h. Нам также нужно максимальное значение maxVal и координата maxX этого максимального значения. Для работы возьмем функцию x - sin ⁡ x
#include #include int main()maxVal) >printf("max value = %.3f at %.3f", maxVal, maxX); getch();> Программа выводит max = 1,391 - 1,077.
Численное решение дает те же результаты, что и наша программа (с погрешностью).
Необязательные элементы в цикле for
Все три выражения в цикле for в скобках являются необязательными и могут быть опущены.
Пример №3
пусть n = 0; for (; nЭтот код ведет себя точно так же, как и код, в котором переменная n объявлена в первом операторе for, а не перед циклом.
Пример №4
пусть n = 0; for (; nВ этом случае шаг перемещается в тело цикла.
Пример №5
Здесь все три выражения отсутствуют, и это не является неправильным, хотя и делает цикл бесконечным. В этом случае мы можем использовать директиву break для завершения цикла.
Прерывание цикла - break
Вы можете использовать директиву break, чтобы прервать цикл на любое время
Пример №6
пусть n = 0; for ( ; )
10) break;> При каждой итерации в теле цикла происходит проверка if (n>10) и цикл будет прерван, если n больше 10.
Пример №7
for (var n = 0; n<8; n++)
alert(n), Здесь принцип прерывания становится более понятным. Когда n достигает пяти, цикл прерывается, и результат отображается в модальном окне. В свою очередь, условие n игнорируется.
Метки для continue и break
Когда циклы застревают, операторы continue и interrupt могут не решить проблему; в этом случае могут помочь метки. Предположим, что в какой-то момент нам нужно выйти из всех уровней цикла.
Пример №9
let n, i; cancelLoops: for (n = 0; n<4; n++)
console.log('n = ' + n + ', i = ' + i);>> Метка cancelLoops идентифицирует верхний цикл, и когда достигается условие (n === 3 && i === 3), он завершается оператором break cancelLoops.
Пример №10
passLoop: for (n = 0; n<4; n++)
console.log('n = ' + n + ', i = ' + i);>> При выполнении условия (n === 2 && i === 2) инструкция continue passLoop завершает текущий цикл и перемещает поток выполнения кода в начало верхнего цикла.