Теоретический материал (Д.Кириенко, С++)

Сайт: Информатикс
Курс: Операторы цикла
Книга: Теоретический материал (Д.Кириенко, С++)
Напечатано:: Гость
Дата: Пятница, 27 Июнь 2025, 22:25

Цикл for

Очень часто возникает необходимость выполнить одну и ту же последовательность действий несколько раз: например, для вычисления выражения an необходимо выполнить умножение на величину a n-1 раз. Для этого используются циклы. В данном листочке речь пойдет о цикле for.

Рассмотрим задачу вычисления суммы всех натуральных чисел от 1 до n. Для этого заведем переменную s, и к ней будем прибавлять значение переменной i, где i будет принимать все значения от 1 до n. На языке C++ это можно сделать при помощи цикла for следующим образом:

     int n, s=0, i;
     cin>>n;
     for (i=1; i<=n; ++i)
     {
         s=s+i;
     }
     cout<<s<<endl;

В этом примере последовательность инструкций в блоке, то есть инструкция s=s+i будет выполнена многократно для всех значений переменной i от 1 до n, то есть в результате переменная s будет равна сумме всех натуральных чисел от 1 до n.

При использовании цикла for необходимо задать три параметра (в круглых скобках через точку с запятой).

Первый параметр – начальное значение переменной, задается в виде присваивания переменной значения, в нашем случае i=1.

Второй параметр – конечное значение переменной, задается в виде условия на значение переменной. Цикл будет исполняться, пока условие истинно, в нашем случае условие i<=n означает, что переменная i будет принимать значения до n включительно.

Третий параметр – шаг изменения переменной. Запись ++i означает, что переменная i будет увеличиваться на 1 с каждым новым исполнением цикла, запись --i – уменьшаться.

В нашем примере мы могли бы сделать цикл, в котором переменная i принимала бы все значения от n до 1, уменьшаясь при этом: for(i=n; i>0; --i).

Если хочется, чтобы значение переменной в цикле менялось не на 1, а на большую величину, то это можно сделать, например, так: i=i+2.

Упражнения

  1. (A) По данному натуральному n вычислите сумму 12+22+...+n2.
  2. (B) По данному натуральном n вычислите сумму 13+23+...+n3.
  3. (C) По данному натуральном n вычислите сумму 1×2+2×3+...+(n-1)×n.
  4. (D) По данным числам a и b выведите на экран все четные числа от a до b включительно. Например, при вводе 1 и 10 программа должна вывести 2 4 6 8 10.
  5. (E) По данному числу n вычислите значение n!.
  6. (F) По данным натуральным n и k вычислите значение Cnk=n!/(k!(n-k)!) (число сочетаний из n элементов по k).
  7. (G) По данному действительному числу a и натуральному n вычислите величину an. Программа считывает значение a и n и выводит an.
  8. (H) По данному натуральному n вычислите сумму 1+(1+2)+(1+2+3)+...+(1+2+...+n).
  9. (I) По данному числу n вычислите сумму 1+1/22+1/32+...+1/n2. Как вы думаете, к чему приближается эта сумма с увеличением n?
  10. (J) По данному числу n вычислите сумму 4(1-1/3+1/5-1/7+...+(-1)n/(2n+1)). Как вы думаете, к чему будет приближаться эта сумма с увеличением n?
  11. (K) По данному действительному числу a и натуральному n вычислите сумму 1+a+a2+...+an не используя формулу суммы геометрической прогрессии. Время работы программы должно быть пропорционально n. Затем решите эту задачу по формуле суммы геометрической прогрессии и сдайте ее в тестирующую систему.
  12. (L) Дано 10 целых чисел. Вычислите их сумму. Например, при вводе чисел 1 2 3 4 5 6 7 8 9 10 программа должна вывести 55.
  13. (M) Дано несколько чисел. Вычислите их сумму.

    Сначала вводится количество чисел N. Затем вводится N целых чисел, программа должна вывести их сумму.

    Например, при вводе 3 1 20 300 программа должна вывести 321.

  14. (без тестирующей системы) Найдите все двузначные числа, которые равны удвоенному произведению своих цифр. Указание: организуйте цикл, в котором переменная i принимает значения от 10 до 99, проверьте, равна ли i удвоенному произведению своих цифр.
  15. (без тестирующей системы) Квадрат трехзначного числа оканчивается тремя цифрами, равными этому числу. Найдите все такие числа.

Цикл 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;

Последовательность действий такова:

  1. Выполняется инициализация i=0.
  2. Проверяется условие i<3.
  3. Выполняется тело цикла: значение переменной i выводится на экран.
  4. Вычисляется итератор ++i. Теперь i равно 1.
  5. Проверяется условие i<3.
  6. Выполняется тело цикла: значение переменной i выводится на экран.
  7. Вычисляется итератор ++i. Теперь i равно 2.
  8. Проверяется условие i<3.
  9. Выполняется тело цикла: значение переменной i выводится на экран.
  10. Вычисляется итератор ++i. Теперь i равно 3.
  11. Проверяется условие 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 класса)

  1. Не используя компьютер, определите значения переменных после выполнения данных фрагментов программ:

              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;
              }

    Что будет выведено на экран в трех последних примерах?

  2. По данным числам a и n вычислите a^n.
  3. По данному числу n вычислите сумму ряда 1/0!+1/1!+1/2!+...+1/n! .
  4. По данному натуральному числу n определите количество делителей числа n.
  5. По данному натуральному числу n найдите натуральное число, не превосходящее n, имеющее наибольшее число натуральных делителей.
  6. По данному числу n определите, является ли оно простым.
  7. Найдите разложение данного числа n на простые множители.
  8. Число называется совершенным, если оно равно сумме своих делителей, не превосходящих его самого. Например, 6=1+2+3, 28=1+2+4+7+14. Найдите первые 5 совершенных чисел.
  9. Теорема Лагранжа утверждает, что любое натуральное число можно представить в виде суммы четырех точных квадратов. По данному числу n найдите такое представление. Найдите наименьшее натуральное число, которое нельзя представить в виде суммы трех точных квадратов.

Упражнения (для 10 класса)

  1. Не используя компьютер, определите значения переменных после выполнения данных фрагментов программ:

              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;
              }

    Что будет выведено на экран в трех последних примерах?

  2. В трехзначном числе зачеркнули первую цифру, полученное число умножили на 7 и получили исходное число. Найдите его.
  3. По данному натуральному d найдите наименьшее решение в натуральных числах уравнения Пелля x^2-dy^2=1.
  4. Для данного натурального числа n выведите на экран все его натуральные делители.
  5. Число называется совершенным, если оно равно сумме своих делителей, не превосходящих его самого. Например, 6=1+2+3, 28=1+2+4+7+14. Найдите первые 5 совершенных чисел.
  6. Быстрое возведение в степень По данному действительному a и натуральному n вычислите an за время порядка log(n).

    Указание воспользуйтесь представлением числа n в двоичном виде, или свойством: an=(a2)n/2

    при четном n, an=a×an-1

    при нечетном n.

  7. Бинарный алгоритм Евклида Найдите наибольший общий делитель двух чисел не используя медленного оператора деления. Можно использовать деление на 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 – нечетные.

  8. Найдите число, оканчивающееся на цифру d, при умножении которого на d получается число, которое также можно получить перестановкой последней цифры d в начало числа.
    1. Решите эту задачу для d=4.
    2. Аналитически (без использования компьютера) решите задачу для d=8.
    3. Решите эту задачу для всех оставшихся цифр.
    4. Подумайте над обобщением этой задачи на случай нескольких последних цифр.