Цикл while
В цикле for начальное значение, условие работы и приращение связаны с номерами итераций; однако, если количество итераций не определено или не имеет важного значения, то лучше использовать цикл while. При использовании цикла while необходимо просто задать условие, при котором он должен работать:
while (<условие работы>) {
<тело цикла>;
}
Для иллюстрации работы цикла while рассмотрим следующую задачу. Предположим, что кому-то нужно накопить 300 000 рублей на покупку машины, и он периодически кладет деньги в копилку; когда будет накоплено 300 000 рублей или больше, «говорящая» копилка должна сообщить, что денег на покупку достаточно. Описанную ситуацию моделирует код, использующий цикл while:
//Цена автомобиля
const float price = 300000;
printf("Машина стоит %g рублей.\n", price);
//Накопленная сумма
float total = 0;
//Принимем деньги, пока их меньше 300000
while (total < price) {
printf("\nВ копилке %g рублей.\n", total);
printf("Сколько еще положить?\n");
float money;
scanf("%f", &money);
total += money;
}
//Требуемая сумма накоплена
printf("\nВ копилке %g рублей\n",total);
printf("Вы накопили на машину.\n");
Работа программы «Копилка» выглядит так:
Цикл do-while
Цикл do-while отличается от while только тем, что проверка условия работы производится не в начале итерации, а после нее. Это гарантирует, что do-while в любом случае выполнится хотя бы один раз, в то время как цикл while может не выполниться ни разу.
Рассмотрим усовершенствование игры «Угадай число!», разработанной на предыдущем занятии. Напомним, что компьютер не предлагал попробовать еще раз, если с первого раза число не было угадано. Для решения этой проблемы можно поместить игру внутрь цикла, который работает до тех пор, пока число не будет угадано; поскольку первая попытка должна быть произведена в любом случае, то уместно использовать именно do-while.
srand(time(0));
int number = rand() % 10;
int your_number;
//Счетчик количества попыток
int trials = 0;
printf("Угадай число:\n");
do {
trials++;
scanf("%d",&your_number);
if (number != your_number) {
printf("Не угадали!\n\n");
printf("Попробуйте еще раз:\n");
}
} while (number != your_number);
printf("Вы угадали с %d попыток\n", trials);
Программа работает до тех пор, пока условие работы цикла number!=your_number истинно, т.е. введенное число не совпадет с загаданным.
Обработка данных в циклах
Циклические конструкции – это очень мощный инструмент, который предназначен не просто для повторения какого-то действия заданное число раз. Существует масса алгоритмов, созданных для обработки большого количества данных, причем, алгоритмы эти могут быть как элементарными, так и довольно изощренными. Начнем с алгоритма, который встречается повсюду: вычисление суммы элементов какой-то последовательности. Рассмотрим самый простой случай:
1 + 2 + 3 + … + (N-1) + N.
Конечно, человек, знакомый со школьным курсом математики, знает понятие арифметической прогрессии и быстро вычислит сумму по формуле
1 + 2 + 3 + … + (N-1) + N = N*(N+1)/2.
Однако для того, чтобы уловить алгоритм, представим, что данную формулу не знаем ни мы, ни компьютер. Компьютер просто выполняет команды одну за другой, поэтому наша задача заключается в том, чтобы разбить рассмотренное выражение на элементарные операции, после выполнения которых будет вычислена сумма. Существует стандартный подход, позволяющий это сделать. Более того, этот подход используется при решении и других задач, некоторые из которых рассматриваются в следующих темах.
Итак, для подсчета требуемой суммы нужно объявить переменную (назовем ее sum) и инициализировать ее нулем, а затем на каждой итерации цикла прибавлять очередной элемент к этой переменной. После обработки всей последовательности переменная sum будет равна сумме всех элементов. Например, при N=7 переменная sum последовательно примет следующие значения: 0, 1, 3, 6, 10, 15, 21 и 28. Последнее значение, равное 28, является суммой чисел от 1 до 7.
int N;
printf("Введите число N:\n");
scanf("%d", &N);
int sum = 0;
for (int i=1; i<=N; i++) {
//Напомним, что эта запись
//эквивалентна sum = sum+i;
sum += i;
}
printf("Сумма чисел от 1 до %d\n", N);
printf("равна %d\n", sum);
Подумайте теперь, как вычислить другую сумму:
1 + 1/2 + 1/3 + … + 1/(N-1) + 1/N.
На первый взгляд, сложностей нет никаких, и нужно просто изменить тип переменной sum на float, заменить выражение sum+=i на sum+=1/i и поставить спецификатор %f в последнем printf(). Однако после запуска на экране появится число 1. Почему? Данная проблема затрагивалась в теме «Операции и выражения» в разделе «Приведение типов». Дело в том, что оператор деления в некотором смысле интеллектуальный: он возвращает значение целого типа, если оба аргумента целые, а вещественным значение является только в том случае, когда хотя бы одно из значений вещественное. Поэтому решить данную проблему можно двумя способами:
float_sum += (float) 1/i;
float_sum += 1.0/i;