Теоретический материал (Д.Кириенко, С++)
Цикл for в общем виде
Операторы присваивания
В языке C++ помимо стандартного оператора присваивания =
существует еще несколько операторов присваивания: +=, -=, *=, /=, %=,
&=, |=, ^=, <<=, >>=. Запись x+=a эквивалентна записи x=x+a,
то есть значение x увеличивается на a. Аналогично работают и остальные операторы:
x=a- присвоить
xзначениеa x+=a- увеличить значение
xнаa x-=a- уменьшить значение
xнаa x*=a- умножить
xнаa x/=a- поделить
xнаa(не забудьте про то, что бывает деление целочисленное и с плавающей точкой!) x%=a- заменить
xна остаток от деленияxнаa
Все эти операции возвращают ссылку на переменную, стоящую слева от оператора присваивания.
При этом если в арифметической инструкции есть несколько операторов присваивания,
то они выполняются справа налево. Операторы присваивания имеют более низкий приоритет,
чем операторы +, -, *, /, %, то есть выполняются после этих операторов (если нет скобок).
Пример:
int n=2,m=3;
n+=m*=2;
cout<<n<<" "<<m;
Во второй строке стоит два оператора присваивания. Сначала выполнится оператор m*=2,
поскольку он стоит правее. Этот оператор присвоит m значение 6 и вернет это значение.
Следующим выполнится оператор n+=6, где 6 — это значение, которое вернул предыдущий
оператор присваивания. Таким образом, переменной n будет присвоено значение 8
и на экран будут напечатаны числа 8 и 6.
Операторы инкремента и декремента
Унарный оператор инкремента ++ увеличивает значение переменной на 1.
Существует две формы оператора инкремента: префиксная форма ++n и постфиксная форма n++.
Постфиксный оператор инкремента возвращает старое значение переменной, а префиксный оператор — новое,
то есть увеличенное на 1. Пример:
int a=0,b=0,c=0,d=0;
a=++b;
c=d++;
Переменные a, b, d в этом примере будут иметь значение, равное 1, а переменная c будет равна 0.
Унарный оператор декремента -- уменьшает значение переменной на 1 и также существует в префиксной и постфиксной формах.
Операторы инкремента и декремента имеют более высокий приоритет, нежели операторы арифметических операций и присваиваний,
то есть выполняются раньше их (в выражении --d%=c сначала будет выполнен декремент переменной d,
а затем оператор взятия остатка и присваивания %=).
Цикл for
Цикл for является универсальным циклом, который может использоваться и вместо цикла while.
Однако в большинстве случаев цикл for используется для того, чтобы некоторая переменная
изменялась в заданном диапазоне с заданным шагом.
Синтаксис оператора for такой:
for (инициализация ; условие ; итератор )
инструкция
где инициализация, условие, итератор — арифметические выражения, инструкция — одна инструкция языка C++.
Работает цикл for следующим образом. Сначала вычисляется выражение "инициализация".
Затем вычисляется значение "условия". Если оно истинно, то выполняется
"инструкция" тела цикла, а затем вычисляется "итератор".
Если же "условие" ложно, то цикл не выполняется и управление передается на следующую инструкцию после цикла.
Если цикл был выполнен, то после вычисления "итератора" снова проверяется "условие", и если оно истинно, то снова выполняется "инструкция",
а затем вычисляется "итератор" и так далее, пока условие не станет ложно.
Таким образом, "инициализация" выполняется один раз до выполнения цикла и, как правило,
используется для присвоения начальных значений переменным, изменяющимся в цикле.
"Условие" проверяется всякий раз перед очередным выполнением блока цикла и обычно используется
для задания границы изменения переменной в цикле. "Итератор" вычисляется после выполнения блока
цикла и в большинстве случаев содержит оператор присваивания, инкремента или декремента, изменяющий
значение переменной.
Рассмотрим следующий пример, в котором на экран выводится 3 числа: 0, 1 и 2:
for(i=0;i<3;++i)
cout<<i<<endl;
Последовательность действий такова:
- Выполняется инициализация
i=0. - Проверяется условие
i<3. - Выполняется тело цикла: значение переменной
iвыводится на экран. - Вычисляется итератор
++i. Теперьiравно 1. - Проверяется условие
i<3. - Выполняется тело цикла: значение переменной
iвыводится на экран. - Вычисляется итератор
++i. Теперьiравно 2. - Проверяется условие
i<3. - Выполняется тело цикла: значение переменной
iвыводится на экран. - Вычисляется итератор
++i. Теперьiравно 3. - Проверяется условие
i<3. Поскольку условие ложно, то цикл завершает работу, управление передается на следующую после цикла инструкцию, значениеiпри выходе из цикла равно 3.
Если в теле цикла нужно использовать не одну инструкцию, а несколько, то их надо объединить в блок при помощи фигурных скобок.
Тело цикла может и вообще отсутствовать, тогда в качестве тела цикла следует использовать пустую инструкцию,
которая ничего не делает и имеет синтаксис ";" (точка с запятой). Пример:
for( cout>>n ; n%2==0 ; n/=2) ;
В этом примере инициализация состоит из считывания значения n с клавиатуры,
условие состоит в проверке, делится ли число n на 2, итератор — в делении числа n на 2,
а тело самого цикла — пустое, так как сразу после закрывающей круглой скобки стоит пустая инструкция ";".
Данный цикл будет уменьшать значение введенного числа в 2 раза до тех пор, пока число делится на 2.
В цикле for можно не указывать выражения инициализации, условия и итератора, но обязательно нужно
проставить точки с запятой даже между отсутствующими выражениями. Если в инструкции for пропущено условие,
то считается, что оно всегда истинно. Таким образом, бесконечный цикл можно задать следующим образом:
for(;;)
Инструкции управления циклом
Внутри циклов while и for могут встречаться инструкции управления циклом.
Инструкция break; прерывает выполнение цикла, управление при этом немедленно
передается на следующую после цикла инструкцию. Инструкция continue; продолжает
выполнение цикла со следующей итерации: все входящие в блок цикла инструкции не выполняются,
в цикле for выполняется итератор, после чего проверяется условие (во всех видах циклов)
и в зависимости от его значения выполняется или не выполняется тело цикла.
Как правило, инструкции break; и continue; используются вместе с инструкцией if.
Пример:
for(i=0;i<100;++i)
{
if(i%3==0)
continue;
cout<<i<<endl;
// Выполнить еще какие-нибудь действия
}
В этом примере переменная i в цикле принимает значения от 0 до 99.
Внутри цикла проверяется условие и если i делится на 3, то оставшаяся часть цикла пропускается,
и на экран будут напечатаны только те значения i, которые не делятся на 3.
Извлечение квадратного корня
Для извлечения квадратного корня (из величин типа double, целочисленные величины
необходимо преобразовать к типу double) используется стандартная функция
sqrt, определененная в файле cmath. Для ее использования необходимо в начале файла
с программой добавить строку #include <cmath>.
Пример использования функции: d=sqrt(e);.
Упражнения (для 9 класса)
- Не используя компьютер, определите значения переменных после выполнения данных фрагментов программ:
int a=5,b=4,c=17,d=3;
a-=b=c%=d;
int e=2, f=3;
++e+=f--;
int g,h=2;
g=(h++)+(--h);
for(int i=0; i<10; i+=3)
cout<<i<<endl;
for(int j=0; j<100; ++j)
{
j*=2;
cout<<j<<endl;
}
for(int k=0;k<100;)
{
if(k%2==0)
++k;
else
k=3*k+1;
cout<<k<<endl;
}
Что будет выведено на экран в трех последних примерах?
- По данным числам a и n вычислите a^n.
- По данному числу n вычислите сумму ряда 1/0!+1/1!+1/2!+...+1/n! .
- По данному натуральному числу
nопределите количество делителей числаn. - По данному натуральному числу
nнайдите натуральное число, не превосходящееn, имеющее наибольшее число натуральных делителей. - По данному числу
nопределите, является ли оно простым. - Найдите разложение данного числа
nна простые множители. - Число называется совершенным, если оно равно сумме своих делителей, не превосходящих его самого. Например, 6=1+2+3, 28=1+2+4+7+14. Найдите первые 5 совершенных чисел.
- Теорема Лагранжа утверждает, что любое натуральное число можно представить в виде суммы четырех точных
квадратов. По данному числу
nнайдите такое представление. Найдите наименьшее натуральное число, которое нельзя представить в виде суммы трех точных квадратов.
Упражнения (для 10 класса)
- Не используя компьютер, определите значения переменных после выполнения данных фрагментов программ:
int a=5,b=4,c=17,d=3;
a-=b=c%=d;
int e=2, f=3;
++e+=f--;
int g,h=2;
g=(h++)+(--h);
for(int i=0; i<10; i+=3)
cout<<i<<endl;
for(int j=0; j<100; ++j)
{
j*=2;
cout<<j<<endl;
}
for(int k=0;k<100;)
{
if(k%2==0)
++k;
else
k*=2;
cout<<k<<endl;
}
Что будет выведено на экран в трех последних примерах?
- В трехзначном числе зачеркнули первую цифру, полученное число умножили на 7 и получили исходное число. Найдите его.
- По данному натуральному d найдите наименьшее решение в натуральных числах уравнения Пелля x^2-dy^2=1.
- Для данного натурального числа n выведите на экран все его натуральные делители.
- Число называется совершенным, если оно равно сумме своих делителей, не превосходящих его самого. Например, 6=1+2+3, 28=1+2+4+7+14. Найдите первые 5 совершенных чисел.
- Быстрое возведение в степень
По данному действительному a и натуральному n вычислите
an за время порядка log(n).
Указание воспользуйтесь представлением числа n в двоичном виде, или свойством: an=(a2)n/2
при четном n, an=a×an-1
при нечетном n.
- Бинарный алгоритм Евклида
Найдите наибольший общий делитель двух чисел не используя медленного оператора деления.
Можно использовать деление на 2 и взятие остатка от деления на 2, поскольку они
выполняются при помощи битовых операций быстро.
Указание: НОД(a,b)=2НОД(a/2,b/2),если a и b – четные, НОД(a,b)=НОД(a/2,b),если a – четное, b – нечетное, НОД(a,b)=НОД(a-b,b),если a и b – нечетные.
- Найдите число, оканчивающееся на цифру d, при умножении которого на
d получается число, которое также можно получить перестановкой последней цифры d
в начало числа.
- Решите эту задачу для d=4.
- Аналитически (без использования компьютера) решите задачу для d=8.
- Решите эту задачу для всех оставшихся цифр.
- Подумайте над обобщением этой задачи на случай нескольких последних цифр.