Урок 6: «Циклы – это повторяющийся участок кода»

Это последний простой урок, который вы изучите в рамках данной рубрики. Дальше пойдут уже более сложные моменты. Скажите, не хотелось бы вам хоть что-то указать компилятору, чтобы он автоматически делал сам? Вспомните наш список сотрудников. Мы вручную вводили каждый раз операторы: cout<<”Введите ФИО сотрудника”<<endl; cin>>a[1]; Двадцать сотрудников и двадцать таких строчек. Опять же, сотрудников может быть и десять тысяч, тогда можно просто сойти с ума, набивая эта строчки. К счастью, С++ позволяет нам автоматизировать подобные действия. Для этого нужно использовать циклы. Цикл – это участок кода, который будет повторяться до достижения условия выхода из цикла. Кстати, вместе с темой циклов я введу и понятие блок-схема. Блок-схема – эта графическое отображение алгоритма вашей программы. Имела место в процедурном программировании, с приходом ООП практически потеряла актуальность. Тем не менее, некоторые аспекты удобно отображать именно с помощью блок-схемы. Эти мои каракули (чертежник из меня никудышный) обозначают цикл с предусловием. Поясню, как работает этот цикл. Программа доходит до ключевого слова while, обозначающего цикл и проверяет условие, указываемое в скобках. Если оно несовпадает с нужным нам, программа проигнорирует цикл. В другом случае она будет выполнять цикл до достижения нужного условия выхода из цикла. Запомните, цикл с предусловием может не выполниться ни разу! Это его главная особенность. Объявляется цикл с предусловием так: while (условие) { действия; } Давайте теперь рассмотрим на примере, как он действует. Пусть нам нужно будет вывести список чисел, допустим до 20. Итак, наш цикл будет выглядеть таким образом: intn=0; while(n<=20) { cout<<n<<endl; n++; } Итак, что мы сделали. Вначале инициализировали переменную n нулем. Я мог дать ей единицу, суть не в этом (кстати, попробуйте присвоить n любое другое значение, в том числе и больше 20). Теперь для вывода списка я использовал цикл с предусловием, в котором указал, что цикл будет выполняться до тех пор, пока n меньше или равен 20. Если переменная достигает 21, то цикл заканчивает свою работу. Ну а в цикле я выводил на консоль значение n, а потом прибавлял ее значение инкрементом (++). Данный цикл применяется только тогда, когла мы точно не знаем, будет ли выполняться цикл вообще. Я мог присвоить n значение 100 и цикл бы не сработал. Это очень удобно. Компилятор встретил цикл, проверил условие и понял, что ему дальше нужно делать. В противовес этому цикл, существует цикл с постусловием. Его отличительной чертой является тот факт, что данный цикл выполнится хотя бы один раз, пускай даже, если условие и не будет соответствовать нужному. В итоге это замедляет работу программы. Объявляется цикл с постусловием так: do { действия; } while(условие) Ну а графически это будет выглядеть так: Как видите, сначала действия выполнются, а уже потом проверяется условие. Чтобы не запутаться, скажу вам сразу – цикл с постусловием следует использовать только тогда, когда необходимо, чтобы цикл сработал хотя бы один раз. В остальных случаях следует использовать цикл с предусловием или цикл с параметром. Давайте нашу задачу реализуем с помощью цикла с постусловием: intn=0; do { cout<<n<<endl; n++; } while(n<=20) Если вы читали урок внимательно, то должны понять разницу между этими двумя циклами. Ради эксперимента вновь поменяйте значение n на больше 20. Условием цикла может быть и логическое значение: boolflag=true; while(flag){ действия; } или же while(!flag) { действия; } Обратите внимание, что в этом случае будет выполняться бесконечный цикл (цикл, который не может найти условие для выхода). В этом случае его нужно будет явно прервать, например присвоив в первом случае переменной flag значение false: boolflag=true; intn=1,k=5; while(flag) { if(++n>k)flag=false; } Теперь что за восклицательный знак я поставил перед flag? Это отрицание. Если логическое true, то в следствие знака ! оно будет false. Думаю, что с этим понятно. Просто запомните, что если вдруг вам захотелось проверить условие способом if (flag!=true), то лучше использовать if (!flag). Думаю, что с этими двумя циклами у вас проблем возникнуть не должно. На практике я знаю, что новички сыплются на следующем виде циклов – цикле с параметром. Что же это за цикл? В предыдущих циклах мы не знали, сколько раз выполнится цикл. Мы ставили условие циклу и компилятор гонял этот цикл. Цикл мог выполниться миллион раз, а мог и не разу. В отличие от низ, цикл с параметром четко знает, сколько раз он должен выполниться. Ведь мы сами указываем в параметре это значение. Объявляется данный цикл таким образом: for(нижняя граница цикла; верхняя граница цикла; шаг приращения/ уменьшения) { действия } На нашем, компьютерном языке C++ он будет записан следующим образом. Кстати, запомните важную вещь – благодаря различным уровням видимости переменных в С (мы об этом поговорим позже), рекомендуется нижнюю границу цикла объявлять в параметре. Кроме того, считается признаком хорошего программирования называть переменную цикла именем I (от iterator). В качестве примера возьмем уже наш многострадальный список сотрудников, который мы рассматривали в прошлом уроке. К слову могу сказать, что для массив и цикл с параметром – это хороший союз. Фактически, этот цикл применяется, в основном, для обхода массива. Хотя им можно решать и другие задачи. Но просто в массиве он очень удобен: #pragma warning (disable:4786)//отключимперудпреждения #include «stdafx.h» #include <iostream> //содержит объекты ввода-вывода #include <locale.h> //настройуивремени #include <string> usingnamespacestd; int_tmain(intargc,_TCHAR*argv[]) { setlocale(0,«»);//установим язык по-умолчанию (русский) constintsize=20;//размермассива stringsotr[size]; for(inti=0;i<size;i++) { cout<<«Ввеедите имя сотрудника»<<endl; getline(cin,sotr[i]); } system(«pause«);//чтобы окно не закрылось return0; } Скомпилируйте и запустите. У вас должно получиться нечто вроде: Теперь давайте пробежимся по коду. Вначале директивой #pragma warning (disable:4786) я отключил предупреждения компилятора. В принципе, вы его можете оставить, вот только при компиляции будут доставать «возможные ошибки» (так уж устроен этот компилятор). Важно очень подключить заголовочный файл <string>, в котором находится нужная нам функция getline. Внимание, ввести строку типа string в C++ можно только этой функцией. Объект cin, которым мы раньше пользовались, здесь бесполезен. Обратите внимание на конструкцию for. Это и есть наш цикл с параметром. Мы объявили итератор, указали, что нижняя граница цикла равна 0 ( а можем любое число использовать, в зависимости от задачи), верхней границе указали, что она меньше константы size (т.к. отчет с 0 для массива, вы же помните?), ну и шаг массива указали равным 1 (использовали для этого инкремент). О функции getline я уже рассказывал. Попробуйте, модифицируйте программу таким способом, чтобы она выводила список записанных сотрудников из уже введенного массива. Для этого используйте еще один цикл for. Только уже будете выводить таким образом: cout<<sort[i]<<endl; Думаю, что вы обратили внимание на то обстоятельство, что вместо индекса массива я использовал значение итератора i. Это тоже самое, как если бы я писан не текущее i, а явно указывал sort [1] и т.д. В этом одно из достоинств массива. К слову, и в двух других циклах вы вольны ввести итератор и сами его приращивать в цикле, давая его значение своему массиву, это хотя и не рекомендуется, но не возбраняется. Блок-схему рисовать, я считаю, бессмысленно, так как код нагляден. Вместо этого давайте еще немного расскажу о цикле for. C допускает делать с ним различные безобразия. Вот, например, один из способов вывода ряда фибоначчи: for (i=0, j=1, k=0, fib =0; i<50; i++, fib=j+k, j=k, k=fib) Причем, здесь вычисление приводится в самом параметре. Хотя этот способ может показать о вашей крутизне, он гораздо хуже читается. Но знайте, что так можно поступать. Кроме этого стоит поговорить о шаге приращения. Его можно задать произвольно. Допустим, нам нужен каждый второй элемент нашего массива. Тогда мы укажем не i++, а i+=2. И так по аналогии. Кроме того, часто нужен будет делать цикл на уменьшение. Тогда нижней границей будет ваше верхнее число, верхней – нижнее, а использовать нужно будет декремент (i—). В алгоритмических приемах вы сами вскоре все увидите. Как видите, циклы очень удобная штука. Однако в циклы еще включены некоторые управляющие операторы, делающие их гораздо удобнее. Особенно это помогает при использовании вложенных циклов. Да-да, как и любая другая конструкция, циклы могут быть вложенными друг в друга: while(true) { for(inti=0;i<100;i++) { ;} } При реализации многих алгоритмов этот подход очень важен. Но не менее важно прервать выполнение цикла по какому-либо условию. В C и C++ это позволяют сделать операторы continue и break. При встрече со словом continue, компилятор тут же бросает выполнение всей текущей итерации цикла и заходит на новую итерацию. Цикл все равно будет продолжен. А вот с break ситуация несколько иная – встретив это слово, C++ прервет работу цикла и выйдет из него. Ему будет абсолютно все равно, что после этого слова стоит еще целый блок действий. Мы указали C++, что хотим прервать цикл по нашему условию. Давайте продемонстрируем работу break в примере, когда нам нужно будет осуществить линейный (последовательный) поиск в массиве. Хотя и обещал рассмотреть алгоритмы в специальном уроке, но программирование на то и программирование. Без алгоритмов никуда. Линейный поиск – это последовательный перебор элементов с сравнением каждого из них с поисковым запросом. Считается одним из самых медленных алгоритмов. Однако при работе с неупорядоченным массивом (не отсортированным), линейный поиск дает максимальный результат. А так как у нас этот массив некому сортировать, то последовательный поиск – то, что доктор прописал: for(inti=0;i<size;i++) { if(sotr[i]=«Иванов») { cout<<«Искомая личность найдена»<<endl; break; } } } Мы нашли в массиве нашу фамилию (точнее, ее первое вхождение). Дальнейшее выполнение перебора в нашем варианте бессмысленно (мы не учитываем, что могут быть однофамильцы). Поэтому сразу же прерываем цикл. Если условие ни разу не выполнилось, цикл проработает до конца. Думаю, что с этим понятно. Поэкспериментируйте с оператором continue. Придумайте задачку и реализуйте ее сами. На этом урок о циклах я заканчиваю. <<Предыдущий урок                                                 Следующий урок>>

Яндекс.Метрика