Прежде, чем изучать циклы, следует познакомиться с часто используемым в языке C способом увеличения/уменьшения значений переменных на единицу. Конечно, в Си работают такие формы изменения значений как, например, a += 1 или a -= 1 . Однако чаще используют операции инкрементирования (оператор инкремента ++ ) и декрементирования (оператор декремента — ): i++ или ++i , i— или —i . В результате этих операций переменные увеличиваются или уменьшаются на единицу.
Запомните, когда вы видите выражения типа ++i или i++ , то в результате их выполнения значение i меняется. Не надо делать вот так: i = ++i . Это совершенно лишнее.
Когда знак инкремента или декремента стоит перед переменной, то перед нами префиксная форма операции ( ++i , —i ), а когда после переменной, то постфиксная форма ( i++ , i— ). Когда эти выражения не участвуют в построении более сложных выражений, то между префиксной и постфиксной формами никакой разницы нет: что i++ , что ++i — без разницы, в результате мы получим значение i на единицу больше.
Однако когда эти выражения участвуют в построении более сложных, то разница между префиксной и постфиксной формами появляется и заключается в следующем: переменная над которой производится операция инкрементирования или декрементирования в постфиксной форме сначала используется в сложном выражении как есть, и только потом увеличивается на единицу; если мы имеем дело с префиксной формой, то переменная сначала изменяется, а затем используется. Например, код:
int a, b, c, d; /* выражение означает, что всем переменным присваивается 0 */ a = b = c = d = 0; printf(«a=%d, b=%d, c=%d, d=%dn», a, b, c, d); c = ++a; d = b++; printf(«a=%d, b=%d, c=%d, d=%dn», a, b, c, d);
, выведет на экране:
a=0, b=0, c=0, d=0 a=1, b=1, c=1, d=0
Объясняется такой результат так:
- значение переменной a было увеличено на единицу, после чего это значение было присвоено переменной c ;
- значение переменной b было сначала присвоено переменной d и только потом увеличено на единицу.
Еще один пример:
int x, y; x = y = 0; printf(«%dn», x++ > 0); printf(«%dn», ++y > 0);
На экране будет выведено:
Это результат логических выражений, где 0 означает ложь, а 1 — истину. В данном случае, когда x сравнивается с нулем, то его значение еще не увеличено, а когда сравнивается у , то его значение уже больше нуля.
Применять операторы инкремента и декремента можно также к переменным вещественного типа.
Цикл while
Цикл while в языке программирования C работает также как и в других языках программирования. По аналогии с условным выражением в инструкции if , условное выражение при while заключается в круглые скобки. Если тело цикла включает несколько выражений разделяемых точкой с запятой, то все тело заключается в фигурные скобки.
ИНФОРМАТИКА 8 класс: Цикл с предусловием на языке Паскаль | Видеоурок
- Присвойте переменной star значение 0. Пока значение star не достигнет 55 выводите на экран в строку по одной звездочке ( * ).
- С помощью цикла while запрограммируйте вывод на экран цифровых кодов и значений таблицы символов ASCII от 31 до 127 включительно. При этом после каждого десятого символа осуществляйте переход на новую строку. (Подсказка: чтобы переходить на новую строку, в цикле while надо использовать инструкцию if , в условии которой остаток 1 от деления на 10 сравнивается с нулем.)
- Используя внешний и вложенный циклы while организуйте вывод таблицы умножения на экран.
1 Операция нахождения остатка от деления в языке C обозначается знаком процента % .
Цикл с предусловием (while)
Цикл с предусловием реализует структурную схему , приведенную на рис. 3.3 (а), и имеет вид:
while ( выражение ) оператор;
Выражение определяет условие повторения тела цикла , представленного простым или составным оператором. Если выражение не равно 0 (истинно), выполняется оператор цикла, после чего опять вычисляется выражение. Если при первой проверке выражение равно 0, цикл не выполнится ни разу. Тип выражения должен быть арифметическим или приводимым к нему.
Пример (программа печатает таблицу значений функции y=x 2 +1 во введенном диапазоне):
#include using namespace std; int main() < float Xn, Xk, Dx; printf(«Введите диапазон и шаг изменения аргумента: «); scanf(«%f%f%f», Xk, printf(«| X | Y |n»); //шапка таблицы int X = Xn; //начальные установки цикла while (X<=Xk) < //проверка условия выхода printf(«| %5.2f | %5.2f |n», X, X*X + 1); //тело X += Dx; //модификация >>
Цикл с постусловием (do while)
Цикл с постусловием реализует структурную схему , приведенную на рис. 3.3 (б), и имеет вид:
do оператор while выражение;
Сначала выполняется простой или составной оператор , составляющий тело цикла, а затем вычисляется выражение. Если оно не равно 0 (истинно), тело цикла выполняется еще раз, и так далее, пока выражение не станет равным нулю или в теле цикла не будет выполнен какой-либо оператор передачи управления . Тип выражения должен быть арифметическим или приводимым к нему.
Пример (программа осуществляет проверку ввода):
#include using namespace std; int main()< char answer; do< cout > answer; >while (answer != ‘y’);>
Цикл с постусловием (do while)
Если проверка условия продолжения цикла выполняется после тела цикла, то такая конструкция называется цикл с постусловием (смотрите структурную схему на рис.1, б).
В отличие от циклов for и while , в которых проверка условия происходит при входе, цикл do-while проверяет условие при выходе. Поэтому тело такого цикла всегда выполняется хотя бы один раз.
Общая форма цикла do while имеет следующий вид:
- do инструкция while (выражение);
Цикл do-while выполняется до тех пор, пока остается истинным элемент выражение . Если выражение станет равным false , то происходит передача управления инструкциям, следующим за циклом.
В следующей примере, осуществляется ввод последовательности целых чисел и определение ее суммы до тех пор, пока на вход не поступит число 0.
Цикл с предусловием в с
#include
void main()
char s1[80];
long xin, xout; /* xin — покупки; xout — сумма покупок */
clrscr();
xout=0; xin=0;
while (xout scanf(«%d», /* Вводим стоимость очередной покупки */
xout += xin; /* Наращиваем сумму покупок */
>
/* Проверяем сумму покупок и если она превысила 1000 рублей то вычитаем стоимость последней покупки */
if (xout > 1000) xout = xout — xin;
printf(«Summa=%d»,xout);
>
Цикл while удобен для работы с символами и строками. Напишем программу по выделению первого слова из введённой с клавиатуры строки. Признаком разделения слов в строке служит пробел (код 32).
#include
#include
void main()
char c, s1[80], s2[80];
int z;
clrscr();
puts(«Input string:»);
gets(s1); /* Считываем строку с клавиатуры */
printf(«S1=%s n»,s1);
z=0; c=0; /* Задаём начальные значения переменным */
/* Организуем цикл, который завершится если символом с будет «пробел» */
while (c != 32)
/* Присваиваем переменной с значение очередного символа из строки S1 */
c = s1[z];
/* Создаём слово в S2 */
s2[z] = c;
z++; /* */
>
printf(«Slowo=%s»,s2); /* Печатаем полученное слово */
>
Цикл с постусловием do . while |
Для того, чтобы цикл выполнился хотя бы один раз (а именно в действии цикла может быть заложен алгоритм изменения условия), то следует воспользоваться циклом с постусловием do . while. Цикл оформляется следующим образом: do оператор цикла while (логическое условие); или do оператор1; оператор2; . Оператор N; > while (логическое условие); Цикл do : while удобно использовать когда число итераций цикла заранее неизвестно, а цикл нужно прервать по какому нибудь признаку, например при нажатии определённой клавиши. Напишем программу вычисления суммы ряда чисел. Число элементов ряда заранее неизвестно. Цикл будет прерываться при нажатии клавиши «y». |
#include
void main()
char c;
float z, rez;
clrscr();
z=0; c=0; rez=0;
do
printf(«Inrut z:»);
scanf(«%f», /* Считываем значение очередного члена ряда */
rez = rez + z; /* Вычисляем сумму ряда */
puts(«End — y, else other char»);
c = getch(); /* Вводим символ признак */
>
while (c != ‘y’); /* Завершаем цикл если с = ‘y’ */
printf(«nRez= %2f»,rez); /* Выводим сумму ряда на экран */
>
Результат работы программы будет такой:
Цикл 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() < double sum = 0.0; double a = 0.0; double b = 1.0; double h = 0.01; double x; for (x = a; x < b; x += h) < sum += x*x * h; >printf(«%.3f», sum); getch(); >
Давайте рассмотрим кусок кода
double x ; for (x = a; x
Его можно изменить так
double x = a; for (; x
Более того, используя оператор break, можно убрать условие и написать
double x; for (x = a;; x += h)< if (x>b) < break; >sum += x*x*h; >
double x = a; for (;;) < if (x >b) < break; >sum += x*x*h; x += h; >
кроме того, используя оператор «,», можно часть действий перенести
double x ; for (x = a; x < b; x += h, sum += x*x*h) ;
ЗАМЕЧАНИЕ: несмотря на то, что так можно делать, пожалуйста, не делайте так! Это ухудшает читаемость кода и приводит к трудноуловимым ошибкам.
Давайте решим какую-нибудь практическую задачу посложнее. Пусть у нас имеется функция f(x). Найдём максимум её производной на отрезке. Как найти производную функции численно? Очевидно, по определению). Производная функции в точке — это тангенс угла наклона касательной.
f x ′ = d x d y
Возьмём точку на кривой с координатами (x; f(x)), сдвинемся на шаг h вперёд, получим точку (x+h, f(x+h)), тогда производная будет
d x d y = f ( x + h ) — f x ( x + h — x ) = tg α
То есть, отношение малого приращения функции к малому приращению аргумента. Внимательный читатель может задать вопрос, почему мы двигаемся вперёд по функции, а не назад. Ну пойдёмте назад
Возьмём среднее от этих двух значений, получим
В общем-то теперь задача становится тривиальной: идём от точки a до точки b и находим минимальное значение производной, а также точку, в которой производная принимает это значение. Для решения нам понадобятся, как и в задаче с интегралом, переменные для границ области поиска a и b, текущее значение x и шаг h. Кроме того, необходимо максимальное значение maxVal и координата maxX этого максимального значения. Для работы возьмём функцию x • sin x
#include #include #include int main() < double a = 0; double b = 3.0; double h = 0.001; double h2 = h * 2.0; double maxVal = a*sin(a); double maxX = a; double curVal; double x; // Проходим по всей области от a до b // и ищем максимум первой производной // Используем функцию x*sin(x) for (x = a; x < b; x += h) < curVal = ( (x+h)*sin(x+h)-(x-h)*sin(x-h) )/h2; if (curVal >maxVal) < maxVal = curVal; maxX = x; >> printf(«max value = %.3f at %.3f», maxVal, maxX); getch(); >
На выходе программа выдаёт max value = 1.391 at 1.077
Численное решение даёт такие же (с точностью до погрешности) результаты, что и наша программа.
Вложенные циклы
Рассмотрим пример, где циклы вложены друг в друга. Выведем таблицу умножения.
#include #include #include int main() < int i, j; // Для каждого i for (i = 1; i < 11; i++) < // Выводим строку из произведения i на j for (j = 1; j < 11; j++) < printf(«%4d», i*j); >// После чего переходим на новую строку printf(«n»); > getch(); >
В этом примере в первый цикл по переменной i вложен второй цикл по переменной j. Последовательность действий такая: сначала мы входим в цикл по i, после этого для текущего i 10 раз подряд осуществляется вывод чисел. После этого необходимо перейти на новую строку. Теперь давайте выведем только элементы под главной диагональю
for (i = 1; i < 11; i++) < for (j = 1; j < 11; j++) < if (j >i) < break; >printf(«%4d», i*j); > printf(«n»); >
Как вы видите, оператор break позволяет выйти только из текущего цикла. Этот пример может быть переписан следующим образом
for (i = 1; i < 11; i++) < for (j = 1; j printf(«n»); >
В данном случае мы используем во вложенном цикле счётчик первого цикла.
Всё ещё не понятно? – пиши вопросы на ящик
Продолжить заявление на языке C
Если вы хотите перейти к следующей итерации, но остаться в цикле, вам следует использовать оператор continue.
Например:
#include int main() < int nb = 7; while (nb >0) < nb—; if (nb == 5) continue; printf(«%dn», nb); >>
Вывод:
6 4 3 2 1
Таким образом, значение 5 пропускается.
Какой шлейф выбрать?
Выбор цикла — всегда непростая задача для программиста, чтобы выбрать цикл, сделайте следующее:wing действия:
- Проанализируйте проблему и проверьте, требует ли она цикла предварительного тестирования или цикла после тестирования.
- Если требуется предварительное тестирование, используйте while или for цикл.
- Если требуется пост-тест, используйте цикл do- while.
Цикл с предусловием while
while (условие) оператор;
- Программа встречает ключевое слово while , значит дальше идёт циклическая конструкция;
- Проверяется условие. Вычисляется логическое выражение, записанное в скобках;
- Если значение условия ИСТИНА , то выполняется тело цикла. Переходим к пункту 2;
- Если значение условия ЛОЖЬ , то цикл завершается. Управление передаётся на оператор, следующий за телом цикла.
Под оператором понимается один оператор. Если нужно выполнить в цикле несколько команд, то необходимо использовать составной оператор <> .
Давайте перепишем нашу программу с использованием данного цикла.
#include #include #include int main(void) < srand(time(NULL)); printf(«########### Devil’s bones ###########n»); printf(«# #n»); printf(«# Commands: #n»); printf(«# #n»); printf(«# 1 — new game #n»); printf(«# 0 — exit #n»); printf(«# #n»); printf(«########################################nn»); int control; int value = 0; printf(«Enter command: «); scanf(«%d», while(control != 0)< switch(control)< case 1: value = 1 + rand()%6; printf(«Result: %dn», value); break; default: printf(«Error! Try again. n»); break; >printf(«Enter command: «); scanf(«%d», > printf(«Good bye!n»); return 0; >
Опишем словами алгоритм работы данной программы:
- Выводим меню пользователя и предложение ввести команду;
- Считываем код команды в переменную control ;
- Запускаем цикл while . Проверяем условие;
- Если пользователь ввёл 0 , то условие выполнения цикла принимает значение ЛОЖЬ . Тело цикла не выполняется. Управление передаётся на следующий за циклом оператор. Выводится строка Good bye! . Программа завершается;
- Оператор выбора:
- Если пользователь ввёл 1 , то генерируем случайное число от 1 до 6 и выводим его на экран. Выходим из оператора выбора;
- Если пользователь ввёл что-то иное, выводим сообщение об ошибке. Выходим из оператора выбора.
Цикл while называют циклом с предусловием, т.к. прежде, чем выполнить тело цикла, проверяется условие. Это значит, например, что возможна такая ситуация, что тело цикла не выполнится вообще ни один раз. Другое название цикла while – цикла ПОКА . Дословный перевод с английского. Это название отображает саму суть цикла.
ПОКА условие ИСТИНА, выполняй тело цикла.
Цикл с постусловием do-while
И последняя, третья циклическая конструкция – цикл do-while .
Данный цикл отличается от цикла while тем, что условие проверяется не перед выполнением тела цикла, а после выполнения тела цикла. Это значит, что тело цикла do-while выполнится хотя бы один раз обязательно.
Синтаксис данной циклической конструкции таков:
do оператор; while (условие);
Работает эта конструкция следующим образом:
- Программа встречает ключевое слово do . Значит перед ней цикл do-while ;
- Выполняется тело цикла;
- Проверяется условие;
- Если условие ИСТИНА ,то снова выполняется тело цикла;
- Если условие ЛОЖЬ , то работа циклической конструкции прекращается. Программы выполняет оператор, следующий за циклом do-while .
Давайте перепишем нашу программу с использованием данного типа циклической конструкции.
#include #include #include int main(void) < srand(time(NULL)); printf(«########### Devil’s bones ###########n»); printf(«# #n»); printf(«# Commands: #n»); printf(«# #n»); printf(«# 1 — new game #n»); printf(«# 0 — exit #n»); printf(«# #n»); printf(«########################################nn»); int ch_control; int value = 0; do < printf(«Input command: «); scanf(«%d», switch(ch_control)< case 0: break; case 1: value = 1 + rand()%6; printf(«Result: %dn», value); break; default: printf(«Error! Try again. n»); break; >>while(ch_control != 0); printf(«Good bye!n»); return 0; >
В общем-то очень похоже на предыдущий код. Правда, пришлось немножко поменять оператор выбора: добавить туда ветку case 0: . Иначе из-за того, что проверка производится после выполнения тела цикла, программа работала некорректно. При вводе нуля появлялось сообщение об ошибке. В прошлой программе (с циклом while ) подобной ситуации быть не могло, т.к. равенство нулю проверялось в условии цикла. При вводе нуля условие стало бы ложью, а значит цикл завершился бы и тело цикла не выполнилось.
Сохрани в закладки или поддержи проект.