Перейти к содержимому

Что такое циклические конструкции

  • автор:

Циклические конструкции в языке Си

Основное преимущество компьютера перед человеком заключается в том, что он может очень быстро выполнять операции и хранить большие объёмы информации. При этом он не устаёт и не ошибается. Но данными преимуществами ещё нужно научиться грамотно пользоваться. Например, какая польза от того, что компьютер может выполнить миллион операций в секунду, если нам нужно предварительно записать каждую из этого миллиона операций? Сколько времени на это уйдёт? Очевидно, что нам требуется способ записывать много простых операций малыми усилиями, желательно в 2-3 строчки кода. И, конечно, такой способ есть – это циклические конструкции (циклы) .

Цикл – конструкция, которая позволяет указать компьютеру выполнить некоторую последовательность операций много раз.

В этом уроке мы обсудим, как устроены циклические конструкции в языке Си, и научимся ими пользоваться.

В языке Си используются три основных вида циклов:

    цикл со счётчиком for while do-while

Сохрани в закладки или поддержи проект.

Что такое циклические конструкции

Циклические конструкции

Циклические конструкции применяют для повторения некоторого блока кода на основании условия цикла. В языке С используются циклические конструкции while , for и do — while .

Конструкция while

Цикл while имеет следующий синтаксис.

// Выполнение тела цикла, если выражение истинно

Другими словами, циклы while имеет смысл использовать в тех случаях, ко­гда соответствующий оператор или блок операторов необходимо выполнять до тех пор, пока условное выражение истинно. Пример формирования строки, со­стоящей из нечетных цифр:

const char str [] = «0123456789»;

char OddNums [5]; //Строка для хранения нечетных цифр

с = 0; //Счетчик циклов

i = 0; //Индекс массива OddNums

//Если остаток от деления с на 2 = 1, то записываем в i — ю позицию массива OddNums с-й

//элемент строки str , после чего значение i автоматически инкрементируется

if (( с % 2) == 1) OddNums[i++] = str[c];

Конструкция for

Цикл for имеет следующий синтаксис.

for (выражение1; выражение2; выражение3)

// Выполнение тела цикла

Выражение 1 выполняется только один раз при входе в цикл, и обычно пред­ставляет собой оператор присваивания некоторого начального значения счетчику цикла. Выражение2 — это условное выражение, определяющее момент выхода из цикла (цикл выполняется до тех пор, пока оно равно TRUE или 1).

Выражение3 — еще один оператор присваивания, в котором обычно изменяется счетчик цикла или некоторая переменная, влияющая на выполнение условия в выражении2. Вы­ражения могут быть представлены любыми операторами, включая пустые (то есть, вместо выражения можно поставить только символ точки с запятой).

Циклы while и for в большинстве случаев взаимозаменяемы. Так, представ­ленный выше пример для цикла while , можно переписать в следующем виде:

const char str[] = «0123456789»;

char OddNums [5]; //Строка для хранения нечетных цифр

i = 0; //Индекс массива OddNums

if (( с % 2) == 1) OddNums[i++] = str[c];

В одних ситуациях удобнее применять циклы for , в других — while . Досто­инством циклов for является более наглядная инициализация и организация из­менения счетчика цикла, С другой стороны, циклы while более гибкие и обеспе­чивают больше возможностей для реализации нестандартных программных реше­ний при организации повторяющихся вычислений.

Конструкция do — while

Кроме циклов while и for , в которых вначале выполняется проверка истин­ности условия цикла, и только потом управление передается блоку операторов цикла, в языке C имеется также конструкция do — while . Она отличается от первых двух тем, что в ней вначале выполняется блок операторов, и только потом прове­ряется выполнение условия. Другими словами, цикл do — while всегда выполняет­ся как минимум один раз, вне зависимости от условия цикла.Цикл do — while имеет следующий синтаксис:

// Выполнение блока операторов цикла

Организация бесконечных циклов

Для организации бесконечного цикла в качестве условного выражения в кон­струкции while или do — while можно просто указать значение TRUE или 1:

while (1) блок_операторов ;

В случае циклов for это будет выглядеть следующим образом:

Операторы break и continue

Если в теле любого цикла встречается оператор break , управление тут же пе­редается на оператор, следующий за оператором цикла, вне зависимости от ис­тинности или неистинности условного выражения. При этом во вложенных цик­лах выход осуществляется не на самый верхний уровень вложенности, а лишь на один уровень вверх.

При выполнении оператора continue все находящиеся после него операторы блока пропускаются, а управление передается в начало цикла для следующей ите­рации. На практике операторы continue используются гораздо реже, чем опера­торы break , однако в сложных циклах, требующих принятия решений на основа­нии многих факторов, использование операторов continue может быть весьма удобным.

Циклические конструкции

В Less нет стандартных циклов for или while . Однако, текущих возможностей формирования циклических конструкций хватает для всего круга задач, связанного с вёрсткой.

Как я уже говорил ранее, циклы строятся на принципе защиты примесей с помощью условного оператора ( when ). Таким образом, нужно понимать, что все циклы в Less построены на принципе рекурсий или, как напоминает нам JavaScript, цикле с предусловием while (выполнение условия проверяется перед тем, как войти в тело цикла).

Давайте подробно разберём пример, код которого формирует некоторое количество классов, жутко напоминающих простую сетку. Вот код с небольшими комментариями очевидных вещей:

@column-name: col; // Префикс класса сетки @column-count: 4; // Количество классов .generate-column(@i: 1) when (@i =< @column-count) < .@ -@ < width: @i * (100% / @column-count); > .generate-column(@i + 1); > .generate-column(); 

Основную работу выполняет примесь generate-column , принимающая на вход параметр i и защищённая с помощью ключевого слова when . Отсюда следует, что вся магия циклов в Less заключается в условной конструкции и рекурсивном вызове.

Так как примесь принимает на вход параметр i, который по сути является итерационной переменной, а также у примеси указано условие, при котором она будет работать, получается, что мы создаём простой вариант рекурсии. Она будет существовать до тех пор, пока значение переменной @i не сравняется с таковым у @column-count или не будет больше него.

Заглянем внутрь примеси. Здесь формируется имя селектора по правилу: префикс + номер итерации. Уже затем для этого селектора вычисляется значение ширины, как: 100% ширины, делённое на количество колонок и умноженное на шаг итерации. Обратите внимание на строку .generate-column(@i + 1) . Эта команда просит компилятор вызвать эту же примесь, но с увеличенным на единицу шагом итерации. Весь процесс повторяется вновь, но уже с увеличенным на единицу значением переменной @i . В этом и заключается магия.

Для наглядности процесса попробуем вместе с компилятором пройтись пару итераций:

/* Итерация 1 | @i: 1 | Новое значение @i: 2 */ .col-1 < width: 25%; > /* Итерация 2 | @i: 2 | Новое значение @i: 3 */ .col-1 < width: 25%; > .col-2 < width: 50%; > /* Итерация 3 | @i: 3 | Новое значение @i: 4 */ .col-1 < width: 25%; > .col-2 < width: 50%; > .col-3 < width: 75%; > /* Итерация 4 | @i: 4 | Новое значение @i: 5 */ .col-1 < width: 25%; > .col-2 < width: 50%; > .col-3 < width: 75%; > .col-4 < width: 100%; > 

После того, как шаг итерации достигает максимально допустимого значения, происходит выход из рекурсии и компилятор продолжает бороздить красоты нашего кода. В нашем случае этот момент наступает на четвёртом шаге рекурсии, когда новое значение переменной @i равно 5, а максимальное число шагов итераций, заданное переменной @column-count , определено как 4.

Таким образом строятся и более сложные циклы, в которых участвуют несколько счётчиков, примесей или даже списков.

Обработка списка

Рассмотрим ещё один пример, где в цикле генерируются вспомогательные классы на основе списка. Этот пример вы уже встречали в главе 4, когда речь шла про списки (массивы).

Напомню его устрашающий код, который тогда мог повергнуть неподготовленного читателя в ужас:

// Настройки @column-name: col; @column-count: 4; @column-prefix: xs, sm, md, lg; // Генератор селекторов .generate-class(@indexCount, @indexPrefix: 1) when (@indexPrefix =< length(@column-prefix)) < // Получаем элемент списка @prefix: extract(@column-prefix, @indexPrefix); // Формируем селектор .@ -@ -@ < width: @indexCount * (100% / @column-count); > // Порождаем следующую итерацию .generate-class(@indexCount, @indexPrefix + 1); > // Генератор сетки .make-grid(@indexCount: 1) when (@indexCount =< @column-count) < // Вызываем генератор селекторов .generate-class(@indexCount); // Порождаем следующую итерацию .make-grid(@indexCount + 1); > // Вызываем генератор сетки .make-grid(); 

Теперь будем разбираться с ним вплоть до мелочей. Начнём с того, что перепишем весь этот код с Less на JavaScript. Зачем? — скоро все поймёте.

Понимание деталей

Если абстрагироваться от Less к JavaScript, то здесь объявлены две функции, которые, как кирпичики лего, позволяют строить лего-замок. Каждая функция выполняет свою простейшую задачу и, на практике, все функции можно было бы объединить в одну, конечно, при условии, что вам нравится запутанный код.

Для понимания происходящего, проведём параллель между обычным JavaScript-кодом и примесями в Less.

Настройки

В коде, приведённом ниже, объявляется объект columnOptions , хранящий настройки генератора сетки, такие как:

  • Name — Имя столбца
  • Count — Количество столбцов
  • Prefix — Массив префиксов
// Настройки var columnOptions = < name: 'col', count: 4, prefix: ['xs', 'sm', 'md', 'lg'] >; 

Если сравнивать с Less, то там настройки хранятся в переменных. Так, например, в JavaScript свойство объекта Prefix соответствует переменной @column-prefix в Less.

// Настройки @column-name: col; @column-count: 4; @column-prefix: xs, sm, md, lg; 
Вызов

Так как генерировать сетку на JavaScript никто не будет, то и вывод результатов будет осуществляться в консоль:

// Вызываем генератор сетки console.log(makeGrid(columnOptions)); 

Разумеется, что в Less примесь вызывается стандартным образом:

// Вызываем генератор сетки .make-grid(); 

Итак, переходим вместе с кодом в примесь make-grid и отслеживаем работу дальше.

Генератор сетки

Код ниже представляет собой полный эквивалент примеси make-grid, переписанной на классический ванильный JavaScript.

Переменная consoleReturn представляет собой массив объектов, содержащих в себе пары ключей:

  • Name — Имя текущего префикса (xs, sm..).
  • Selector — Объект, содержащий информацию о колонке (имя и ширина), который возвращает функция generateSelector .

Далее в цикле производится проход по всем, указанным в настройках префиксам и на каждой итерации инициируется вызов функции, генерирующей информацию о селекторе.

Соответственно, вся полученная информация возвращается пользователю в консоль для анализа.

// Генератор сетки var makeGrid = function(o) < var consoleReturn = []; for (var index = 0; index < o.count; index++) < consoleReturn.push(< name: o.prefix[index], selector: generateSelector(o, index) >); > return consoleReturn; >; 

Теперь снова посмотрим на нашу оригинальную примесь make-grid и разберёмся с тем, что там происходит:

// Генератор сетки .make-grid(@indexCount: 1) when (@indexCount =< @column-count) < // Вызываем генератор селекторов .generate-class(@indexCount); // Порождаем следующую итерацию .make-grid(@indexCount + 1); > 

Если исключить тот факт, что в Less данные возвращаются автоматически и в рекурсивно вызываемой примеси generate-class , то можно с уверенностью сказать, что эта примесь работает так же, как и функция, написанная на JavaScript.

Вместо цикла for здесь используется рекурсия, которая работает до тех пор, пока итерационная переменная @indexCount меньше, либо равна количеству колонок, указанному в настройках.

На каждой итерации вызывается примесь генератора классов сетки, в которую передаётся переменная, указывающая номер итерации. Далее вызывается текущая примесь со значением итерационной переменной, увеличенной на единицу, чтобы породить рекурсию. То есть принцип действия полностью соответствует примеру, рассмотренному в начале этой части.

Проводя аналогию с функцией на JavaScript, можно выделить следующие наблюдения:

  • Аналогом цикла for в Less является строка .make-grid(@indexCount + 1)
  • Аналогом выражения цикла for в Less является условие when или, как его принято называть — выражение защиты примесей.

Перейдём к рассмотрению примеси, генерирующей селекторы.

Генератор селекторов

Ниже представлен эквивалент примеси generate-class на языке JavaScript, с той лишь разницей, что создавать рекурсию в JavaScript — кощунство, поэтому тут применяется стандартный цикл for .

// Функция генерации селекторов var generateSelector = function(o, indexCount) < var selectors = []; for (var index = 0; index < o.prefix.length; index++) < var name = o.name + '-' + o.prefix[indexCount] + '-' + index; var width = index * (100 / o.count) + '%'; selectors.push(< name: name, width: width >); > return selectors; >; 

Эта функция принимает на вход объект настроек и номер текущей итерации. Массив selectors будет содержать имя и ширину селектора для всех префиксов из массива. Получается, что в нём будет храниться эквивалент CSS-кода:

.col-xs-1 < width: 25%; > .col-sm-1 < width: 25%; > 

Углубляться в то, как он будет представлен не имеет смысла, так как главное здесь — понимать суть. В итоге, из этой функции будет возвращаться массив колонок одного префикса.

Снова обратим внимание на оригинальную less-примесь и проанализируем её действие:

// Генератор селекторов .generate-class(@indexCount, @indexPrefix: 1) when (@indexPrefix =< length(@column-prefix)) < // Получаем элемент списка @prefix: extract(@column-prefix, @indexPrefix); // Формируем селектор .@ -@ -@ < width: @indexCount * (100% / @column-count); > // Порождаем следующую итерацию .generate-class(@indexCount, @indexPrefix + 1); > 

Как уже отмечалось выше, when играет роль выражения цикла, а последняя в примеси строка порождает новую итерацию этой же примеси, что эквивалентно новой итерации стандартного цикла for .

В отличии от JavaScript кода, примесь генерирует селектор и его свойства, а также возвращает их в виде CSS-кода по правилу:

Имя колонки + текущий префикс + номер итерации 

Ширина колонки вычисляется тем же методом, что и в первом примере, описанном в этой части.

Таким образом, примесь будет рекурсивно выполняться до тех пор, пока не будут созданы селекторы для всех префиксов, указанных в переменной @column-prefix .

Результаты

После того, как компилятор пройдёт все итерации для каждой примеси, он вернёт сгенерированные селекторы на то место, где была вызвана управляющая примесь make-grid.

Если не изменять определённые ранее настройки, результат будет следующим:

.col-xs-1 < width: 25%; > .col-sm-1 < width: 25%; > .col-md-1 < width: 25%; > .col-lg-1 < width: 25%; > . .col-xs-4 < width: 100%; > .col-sm-4 < width: 100%; > .col-md-4 < width: 100%; > .col-lg-4 < width: 100%; > 

Вывод JavaScript функций имеет приблизительно такой же вид с поправкой на то, что там данные не предоставляют ценности для CSS.

Выводы

Полностью рассмотрев два примера оценить всю природу циклических конструкций в Less нельзя. Зато можно понять их базовую сущность. Со временем вы научитесь составлять и более сложные конструкции, если это потребует поставленная задача. Да, циклы в Less имеют слегка непривычный вид для JavaScript-разработчиков, но разобравшись с ними раз и навсегда, проблем в дальнейшем не предвидится.

results matching » «

No results matching » «

Циклические конструкции

Для организации циклического выполнения программных блоков в языке Object Pascal используют циклические конструкции трех типов: for-do, while-do и repeat-until. Они отличаются характером начала и завершения цикла.

Читайте также

Циклические ссылки

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

Управляющие конструкции

Управляющие конструкции Введение В четырех первых главах этой серии мы сконцентрировали свое внимание на синтаксическом анализе математических выражений и операций присваивания. В этой главе мы остановимся на новой и захватывающей теме: синтаксическом анализе и

20.3. Проблемы в конструкции Unix

20.3. Проблемы в конструкции Unix Операционная система Plan 9 «очищает» Unix, но добавляет лишь одну новую концепцию (частное пространство имен) к ее основному набору конструктивных идей. Однако есть ли серьезные проблемы в этих базовых идеях? В главе 1 рассматривалось несколько

20.3. Проблемы в конструкции Unix

20.3. Проблемы в конструкции Unix Операционная система Plan 9 «очищает» Unix, но добавляет лишь одну новую концепцию (частное пространство имен) к ее основному набору конструктивных идей. Однако есть ли серьезные проблемы в этих базовых идеях? В главе 1 рассматривалось несколько

Конструкции ветвления

Конструкции ветвления Конструкции ветвления осуществляют переход к одному из блоков программного кода на основании проверки некоторого условия. К ним относятся операторы if и

Итерационные конструкции

Итерационные конструкции Все языки программирования предлагают конструкции обеспечивающие возможность повторения блоков программного кода, пока не выполнено условие завершения повторений. Если у вас есть опыт программирования, то операторы цикла в C# будут для вас

Конструкции while и do/while

Конструкции while и do/while Цикл while оказывается полезным тогда, когда блок операторов должен выполняться до тех пор, пока не будет достигнуто заданное условие. Конечно, при этом требуется, чтобы в области видимости цикла while было определено условие окончания цикла, иначе вы

Программные конструкции

Программные конструкции В следующих разделах рассматриваются программные конструкции, распознаваемые в PSQL. Блоки BEGIN . END PSQL является структурированным языком. После объявления переменных процедурные операторы заключаются в операторные скобки BEGIN и END. В процессе

Циклические сэмплы

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

Конструкции XML

Конструкции XML Помимо элементов, атрибутов и текста, документы могут также содержать другие конструкции, такие как комментарии, инструкции по обработке и секции символьных данных. Эти базовые составляющие используются для того, чтобы гибко, но в четком соответствии со

18.2. Управляющие конструкции

18.2. Управляющие конструкции Почти все сценарии, за редким исключением, обладают свойством самоуправляемости. В чем состоит управление ходом выполнения сценария? Предположим, что в состав сценария включено несколько команд:#!/bin/sh# создание каталогаmkdir /home/dave/mydocs#

18.2.2. Циклические операторы

18.2.2. Циклические операторы Цикл, или итерация, — это процесс повторного выполнения наборов команд. В распоряжении пользователя имеется три вида операторов цикла: for loop Последовательная обработка значений до тех пор, пока не встретится окончание списка until

Циклические ссылки между модулями

Циклические ссылки между модулями Циклические ссылки модулей в интерфейсных частях запрещены. Например, следующая ситуация ошибочна: unit A; interface uses B; implementation end. unit B; interface uses A; implementation end. Таким образом, невозможно определить два общедоступных класса в разных модулях с

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Luxury Car Rental in Miami | Reserve a Premium Vehicle with RealCar