В C ++ есть две конструкции цикла. Один из них - цикл while, и я расскажу о нем в отдельной статье. Другая конструкция цикла, которую я хочу обсудить в этой статье, - это цикл for.

for loop используется, когда вы хотите перебрать или перебрать набор операторов определенное количество раз. Если вы обрабатываете элементы контейнера, такие как массив или вектор, вы захотите использовать цикл for. Если вы обрабатываете 10 фрагментов данных, полученных от пользователя программы, вы можете использовать цикл for.

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

для типов петель

Есть два типа for петель. Первый тип я назову управляемым переменным. Это означает, что в цикле for вы инициализируете переменную, и значение этой переменной определяет, сколько раз цикл for повторяется.

Другой тип for цикла - это диапазон for. Этот тип цикла for выполняет итерацию по всем элементам контейнера, таким как вектор или массив. Вы используете этот тип цикла, когда хотите обработать каждый элемент контейнера, начиная с первого элемента и продолжая до последнего элемента. Использование цикла range for предотвращает любые логические ошибки, которые могут возникнуть при попытке доступа к элементу, находящемуся за пределами контейнера.

Цикл for с переменным управлением

Самый распространенный тип for цикла - это for loop с переменным управлением. Переменная инициализируется внутри тела цикла для управления количеством итераций цикла. Я назову это переменной управления циклом. Вы можете инициализировать переменную управления циклом вне тела цикла, но тогда область видимости переменной не будет локальной для цикла, что вам, вероятно, не нужно.

Вот шаблон синтаксиса, который определяет структуру цикла for с переменным управлением:

for (переменная-инициализация; условие; изменение-переменная) {
тело цикла;
}

Цикл for состоит из четырех частей: 1) инициализация переменной, где вы присваиваете значение переменной для управления циклом (переменная управления циклом); 2) условие остановки цикла, которое вы проверяете; 3) модификация переменной, при которой вы изменяете значение переменной управления циклом, чтобы условие в конечном итоге стало истинным; 4) тело петли - где и выполняется работа петли.

Давайте посмотрим на простой пример, демонстрирующий, как работает цикл for с переменным управлением. Следующая программа отображает «Hello, world!» на экран 5 раз:

int main()
{
  for (int i = 1; i <= 5; i++) {
    cout << "Hello, world!" << endl;
  }
  return 0;
}

Переменная управления циклом в этом примере i. Хотя обычно не рекомендуется использовать имена переменных из одного слова, довольно часто это делается с for loops. Причина этого в том, что for циклов обычно достаточно короткие, так что сканирование цикла, чтобы увидеть, где объявлена ​​переменная, сделать легко.

Результат этой программы:

Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!

Я продемонстрирую, как работает цикл, выполнив трассировку переменной для переменной управления циклом — i.

Вывод i: 1: Привет, мир!
Вывод i: 2: Привет, мир!
Вывод i: 3: Привет, мир!
Вывод i: 4: Привет, мир!
Вывод i: 5: Привет, мир!
Вывод i: 6:

Значение i становится равным 6, но поскольку теперь условие ложно, цикл останавливается и больше нет вывода.

Обычно цикл for с переменным управлением используется для доступа к элементам массива или вектора. Я продемонстрирую это, создав массив из 10 элементов и используя цикл for с переменным управлением, чтобы суммировать элементы массива, чтобы найти среднее значение элементов. Вот программа:

int main () {
  const int numElements = 10;
  int grades[numElements] =
    {81, 77, 91, 82, 75, 89, 92, 68, 98, 84};
  int total = 0;
  for (int i = 0; i < numElements; i++) {
    total += grades[i];
  }
  double average = static_cast<double>(total)/numElements;
  cout << "The average value of the grades is: "
       << average << endl;
  return 0;
}

Результат этой программы:

The average value of the grades is: 83.7

Мы также можем использовать этот метод для отображения значений массива в обратном порядке. Вот программа для этого:

int main () {
  const int numElements = 10;
  int grades[numElements] =
    {81, 77, 91, 82, 75, 89, 92, 68, 98, 84};
  for (int i = numElements -1; i >= 0; i--) {
    cout << grades[i] << " ";
  }
  return 0;
}

Результат этой программы:

84 98 68 92 89 75 82 91 77 81

Цикл for с переменным управлением - это обычный способ доступа к элементам массива или вектора, который в большинстве случаев является вполне функциональным. Однако с появлением в C ++ 11 цикла range for этот новый тип цикла for стал предпочтительным средством доступа к массиву, когда необходимо получить доступ ко всем элементам. В следующем разделе я расскажу, как работает цикл range for.

Диапазон для петли

Цикл range for, представленный в C ++ 11, обеспечивает более простой способ доступа ко всем элементам массива или вектора, а также к некоторым другим типам контейнеров C ++. Цикл range for использует итераторы для доступа к элементам контейнера от первого до последнего элемента. Обзор итераторов можно найти в моей статье об итераторах здесь.

Вот шаблон синтаксиса для диапазона цикла:

for (тип данных имя-переменной: контейнер) {
тело цикла;
}

Цикл range for работает путем инициализации переменной того же типа данных, что и тип элементов в целевом контейнере. Затем итератор посещает каждый элемент контейнера, помещая значение элемента в переменную.

Давайте посмотрим, как цикл range for работает с массивом, который мы использовали в последнем примере:

int main () {
  const int numElements = 10;
  int grades[numElements] =
    {81, 77, 91, 82, 75, 89, 92, 68, 98, 84};
  for (int grade : grades) {
    cout << grade << " ";
  }
  return 0;
}

Результат этой программы:

81 77 91 82 75 89 92 68 98 84

Теперь перейдем от массива к вектору:

#include <iostream>
#include <vector>
using namespace std;
int main () {
  vector<int> grades = {81, 77, 91, 82, 75, 89, 92, 68, 98, 84};
  for (int grade : grades) {
    cout << grade << " ";
  }
  return 0;
}

Этот код дает тот же результат, что и предыдущий пример.

Позвольте мне еще раз изложить пример цикла range for. Всякий раз, когда вам нужно получить доступ ко всем элементам совместимого контейнера, вы должны использовать диапазон for loop над циклом for с переменным управлением. Петля range for более безопасна и столь же эффективна. Это действительно так просто.

за злоупотребление петлей

Иногда вы увидите следующий пример использования цикла for:

int main () {
  const int numElements = 10;
  int grades[numElements] =
    {81, 77, 91, 82, 75, 89, 92, 68, 98, 84};
  int i;
  for (i = 0; i < numElements; i++) {
    cout << grades[i] << " ";
  }
  return 0;
}

Если вы не видите разницы, переменная управления циклом объявляется вне цикла for и инициализируется внутри цикла. Это делает переменную i локальной для main функции, которая в большинстве случаев не нужна и может привести к проблемам.

Практически в каждой ситуации переменная управления циклом должна быть объявлена ​​и инициализирована внутри цикла, чтобы переменная локально относилась к циклу for, а не к функции main. Если вы объявите это локально таким образом, вы можете использовать эту же переменную где-нибудь еще в программе без каких-либо конфликтов.

Иногда вы даже можете увидеть это:

int main () {
  const int numElements = 10;
  int grades[numElements] =
    {81, 77, 91, 82, 75, 89, 92, 68, 98, 84};
  int i = 0;
  for (; i < numElements; i++) {
    cout << grades[i] << " ";
  }
  return 0;
}

Запись первой части for loop как нулевого оператора синтаксически корректна, но еще более запутанна, чем последний пример, где она объявлена ​​вне цикла. Никогда не пишите цикл for, подобный этому, и не следует помещать оператор модификации внутри тела цикла, как в этом примере:

int main () {
  const int numElements = 10;
  int grades[numElements] =
    {81, 77, 91, 82, 75, 89, 92, 68, 98, 84};
  int i;
  for (i = 0; i < numElements;) {
    cout << grades[i] << " ";
    i++;
  }
  return 0;
}

Опять же, синтаксис хороший, но его использование нестандартно, и его следует избегать.

Используйте для петель всякий раз, когда можете

Я хочу закончить эту статью предложением - по возможности используйте for петли. Их легче читать, чем другие типы циклов, и их обычно легче отлаживать. Конечно, бывают ситуации, когда необходимо выбрать другой тип цикла, но это, вероятно, не так часто, как вы думаете. В языке программирования Go даже нет while циклов. Вы должны использовать цикл for для любого цикла, который вы хотите выполнить в Go. Я склонен прислушиваться к их советам в C ++ и по возможности использовать for циклы.

Спасибо, что прочитали эту статью, и пишите мне с комментариями и предложениями.