246071-Либерти-Освой-самостоятельно-С-за-21-день (852741), страница 32
Текст из файла (страница 32)
Для нахождения этого значения используется функция fib(), в качестве параметракоторой передается введенный порядковый номер. Если он меньше трех, функция возвращаетзначение 1. Для вычисления значений, порядковый номер которых превышает 2, используетсяприведенныйнижеалгоритм.1. Пpиcвaивaютcянaчaльныeзнaчeнияпepeмeнным:minusTwo=1, minus0ne=1, answer=2.Значение переменной, содержащей номер искомой позиции, уменьшается на 3, поскольку двепервыепозицииобрабатываютсявыше.2.
Для каждого значения n вычисляем значение очередного члена последовательности.Делаетсяэтоследующимобразом:•переменнойminusTwoприсваиваетсязначениепеременнойminusOne;•переменнойminusOneприсваиваетсязначениепеременнойanswer;•значенияпеременныхminusOneиminusTwoсуммируютсяизаписываютсявanswer;•значениеnуменьшаетсянаединицу.3.Кактолькоnдостигнетнуля,возвращаетсязначениепеременнойanswer.Следуя описанному алгоритму, можно воспроизвести на листе бумаги ход выполненияпрограммы. Для нахождения, к примеру, пяти первых членов последовательности на первомшагезаписываем1,1,2,Остается определить еще два члена ряда. Следующий член будет равен (2+1=3), а длявычисления искомого члена теперь нужно сложить значения только что полученного члена ипредыдущего — числа 2 и 3, в результате чего получаем 5. В сущности, на каждом шаге мысмещаемсянаодинчленвправоиуменьшаемколичествоискомыхзначений.Особоевниманиеследуетуделитьвыражениюусловияпродолженияциклаfor,записанномукак n.
Это одна из особенностей синтаксиса языка C++. По-другому это выражение можнопредставитьввидеn'=0.ПосколькувC++число0соответствуетзначениюfalse,придостижениипеременной n нуля условие продолжения цикла не будет выполняться. Исходя из сказанного,описаниецикламожетбытьпереписановвидеfor(n-=3;n!=0;n--)Подобнаязаписьзначительнооблегчитеговосприятие.Сдругойстороны,первоначальныйвариант программы иллюстрирует общепринятую для C++ форму записи условия, поэтому нестоитумышленноееизбегать.Скомпилируйте и запустите полученную программу. Сравните время, затрачиваемое навычисление 25-го числа рекурсивным (см.
занятие 5) и циклическим методами. Несомненно,рекурсивный вариант программы более компактный, однако многократный вызов функции,использующийся в любом рекурсивном алгоритме, заметно снижает его быстродействие.Поэтому использование цикла более приемлемо с точки зрения скорости выполнения. Крометого, благодаря оптимизации арифметических операций в большинстве современныхмикропроцессоров превосходство не рекурсивных алгоритмов в скорости становится все болееочевидным.Испытывая программу, не вводите слишком большие номера членов ряда Фибоначчи.Значениячленоврядавозрастаютдовольнобыстроивводбольшогопорядковогономераможетпривестикпереполнениюрегистрапамяти.ОператорswitchНа занятии 4 вы познакомились с операторами if и if/else. Однако в некоторых ситуацияхприменение оператора if может привести к возникновению конструкций с большим числомвложений, значительно усложняющих как написание, так и восприятие программы.
ДлярешенияэтойпроблемывязыкеC++предусмотреноператорswitch.Основнымегоотличиемотоператораifявляетсято,чтоонпозволяетпроверятьсразунесколькоусловий,врезультатечеговетвлениепрограммыорганизуетсяболееэффективно.Синтаксисоператораswitchследующий:switch(выражение){caseПервоеЗначение:оператор;break;caseВтороеЗначение:оператор;break;....caseЗначение_N:оператор:break;default:оператор;}В скобках за оператором switch может использоваться любое выражение, корректное сточки зрения синтаксиса языка.
Вместо идентификатора оператор допускается использованиелюбого оператора или выражения, а также последовательности операторов или выражений,результатом выполнения которых является целочисленное значение (или значение, котороеможетбытьоднозначноприведенокцелочисленномутипу).Поэтомуиспользованиелогическихоперацийиливыраженийсравненияздесьнедопускается.ОператорswitchСинтаксисиспользованияоператораswitchследующий:switch(выражение){caseПервоеЗначение:оператор;break;caseВтороеЗначение:оператор;break;....caseЗначение_N:оператор:break;default:оператор;}Оператор switch позволяет осуществлять ветвление программы по результатам выражения,возвращающего несколько возможных значений. Значение, возвращенное выражением,заданнымвскобкахоператораswitch,сравниваетсясозначениями,указаннымизаоператорамиcase, и в случае совпадения значений выполняется выражение в строке соответствующегооператора case.
Будут выполняться все строки программы после выбранного оператора до техпор,поканезакончитсятелоблокаоператораswitch,илинеповстречаетсяоператорbreak.Если ни одно из значений операторов case не совпадет с возвращенным значением, товыполняютсястрокипрограммы,стоящиепослеоператораdefault,вслучаежеотсутствияэтогооператора в теле блока switch. управление будет передано следующей за этим блоком строкепрограммы.Пример1:switch(choice){case0:cout<<"Zero!"<<endl;break;case1:cout<<"One!"<<endl;break;case2:cout<<"Two!"<<endl;break;default:cout<<"Default!"<<endl;break;}Пример2:switch(choice){case0:case1:case2:cout<<"Lessthan3!"<<endl;break;case3:cout<<"Equals3!"<<endl;break;default:cout<<"Greaterthat3!"<<endl;}Приотсутствииоператораbreakпослеоператораиливыражения,следующегозаcase,будетвыполняться выражение очередного блока case.
В большинстве случаев такая ситуациявозникает, когда оператор break пропущен по ошибке. Поэтому, если break опускаетсяумышленно, рекомендуем вставлять в соответствующую строку комментарий. Примериспользованияоператораswitchприведенвлистинге7.16.Листинг7.16.Использованиеоператораswitch1://Листинг7.16.2://Использованиеоператораswitch3:4:#include<iostream.h>5:6:intmain()7:{8:unsignedshortintnumber;9:cout<<"Enterаnumberbetween1and5:";10:cin>>number;11:switch(number)12:{13:case0:cout<<"Toosmall,sorry!";14:break;15:case5:cout<<"Goodjob!\n";//fallthrough16:case4:cout<<"NicePick!\n";//fallthrough17:case3:cout<<"Excellent!\n";//fallthrough18:case2:cout<<"Masterful!\n";//fallthrough19:case1:cout<<"Incredible!\n";20:break;21:default:cout<<"Toolarge!\n";22:break;23:}24:cout<<"\n\n";25:return0;26:}Результат:Enteranumberbetween1and5:3Excellent!Masterful!Incredible!Enteranumberbetween1and5:8Toolarge!Анализ: Сначала программа предлагает ввести число.
Затем введенное числообрабатывается оператором switch. Если вводится 0, то это соответствует значению оператораcaseизстроки13инаэкранвыводитсясообщениеToosmall,sorry!,послечегооператорbreakзавершает выполнение конструкции switch. Если вводится число 5, управление передается встроку 15 и выводится соответствующее сообщение. Затем выполняется строка 16, в которойтакже выводится сообщение, и так до строки 20. В этой строке оператор break завершаетвыполнениеблокасоператоромswitch.Такимобразом,привводечиселот1до5наэкранбудетвыводитьсярядсообщений.Еслиже вводится число, превышающее 5, выполняется строка 21 с оператором default, в которойвыводитсясообщениеToolarge!.ОбработкакоммандменбспомощьюоператораswitchВернемся к теме циклов с оператором for(;;).
Такие конструкции называют бесконечнымициклами, поскольку, если выполнение такого цикла не прервать оператором break, он будетработать бесконечно. Циклы подобного типа удобно использовать для обработки команд меню(листинг 7.17). Пользователь выбирает одну из предложенных команд, затем выполняетсяопределенное действие и осуществляется возврат в меню. Так продолжается до тех пор, покапользовательневыбереткомандувыхода.Вбесконечныхциклахнесуществуетусловия,принарушениикоторогоциклпрерывается.Поэтомувыйтиизтакогоцикламожнотолькопосредствомоператораbreak.Листинг7.17.Примербесконечногоцикла1://Листинг7.17.2://Обработкадиалогаспользователем3://посредствомбесконечногоцикла4:#include<lostream,h>5:6://прототипыфункций7:intmenu();8:voidDoTaskOne();9:voidDoTaskMany(int);10:11:intmain()12:{13:14:boolexit=false;15:for(;;)16:{17:intchoice=menu();18:switch(choice)19:{20:case(1):21:DoTaskOne();22:break;23:case(2):24:DoTaskOne(2);25:break;26:case(3):27:DoTaskOne(3);28:break;29:case(4):30:continue;31:break;32:case(5):33:exit=true;34:break;35:default:36:cout<<"Pleaseselectagain!\n";37:break;38:}//конецблокаswitch39:40:if(exit)41:break;42:}//итакдобесконечности43:return0;44:}//конецфункцииmain()45:46:intmenu()47:{48:intchoice;49:50:cout<<"****Menu****\n\n";51:cout<<"(1)Choiceone\n";52:cout<<"(2)Choicetwo\n";53:cout<<"(3)Choicethree\n";54:cout<<"(4)Redisplaymenu.\n";55:cout<<"(5)Quit.\n\n";56:cout<<":";57:cin>>choice;58:returnchoice;59:}60:61:voidDoTaskOne()62:{63:cout<<"TaskOne!\n";64:}65:66:voidDoTaskMany(intwhich)67:{68:if(which==2)69:cout<<"TaskTwo!\n";70:else71:cout<<"TaskThree!\n";72:}Результат:****Menu****(1)Choiceone.(2)Choicetwo.(3)Choicethree.(4)Redisplaymenu.(5)Quit.:1TaskOne!****Menu****(1)Choiceone.(2)Choicetwo.(3)Choicethree.(4)Redisplaymenu.(5)Quit.:3TaskThree!****Menu****(1)Choiceone.(2)Choicetwo.(3)Choicethree.(4)Redisplaymenu.(5)Quit.:5Анализ: В данной программе используются многие средства программирования,рассмотренные на этом и предыдущих занятиях.
Тут же вы найдете пример использованияконструкцииswitch.Работабесконечногоцикланачинаетсявстроке15.Функцияmenu()обеспечиваетвыводнаэкран команд меню и возвращает номер выбранной пользователем команды. Обработкавведенногономераосуществляетсявконструкцииswitchвстроках18—38.При выборе первой команды управление передается следующему после строки case (1):оператору(строка21).Далее,встроке21,вызываетсяфункцияDoTaskOne(),котораявыводитнаэкран сообщение о выборе пользователя. После завершения работы функции осуществляетсявозврат в точку вызова и выполняется оператор break (строка 22). Оператор break прерываетработу блока switch и управление передается в строку 39. Далее, в строке 40, проверяетсязначениепеременнойexit.Еслионоистинно,бесконечныйциклпрерываетсяоператоромbreakвстроке41.Впротивномслучаевыполняетсяследующаяитерацияцикла(строка15).Особое внимание следует уделить оператору continue в строке 30.
Внимательнопроанализировавструктурупрограммы,вызаметите,чтоэтотоператорможноопустить,причемработа программы не изменится. Если бы строки с этим оператором не было, выполнялся быоператор break, затем оператор if и, так как переменная exit содержала бы значение false,запускалась следующая итерация цикла. Использование оператора continue просто позволяетперейтинановуюитерациюбезпроверкизначенияexit.РезюмеВ языке C++ существует множество способов организации циклических процессов.Оператор while проверяет условие и, если оно истинно, передает управление телу цикла. Вконструкции do...while условие проверяется уже после выполнения тела цикла. Оператор forпозволяет инициализировать переменные цикла, после чего проверяется выполнение условия.Если оно истинно, выполняется тело цикла, а затем операция, являющаяся третьей частьюзаголовка конструкции for.
Перед началом каждой следующей итерации условие проверяетсязаново.Оператора goto следует по возможности избегать, поскольку он позволяет осуществитьпереход в любую точку программы, что значительно усложняет ее восприятие и анализ. Спомощьюоператораcontinueможноосуществитьпереходнаследующуюитерациюциклаwhile,do...whileилиfor,аbreakпозволяетмгновеннозавершитьработуцикла.ВопросыиответыКак определить, какой из операторов, if/else или switch, лучше использовать в конкретнойситуации?Еслиприходитсяиспользоватьболеедвухвложенийоператоровif,толучшевоспользоватьсяконструкциейсоператоромswitch.Каквыбратьмеждуоператорамиwhileиdo...while?Еслителоцикладолжновыполнятьсяхотябыодинраз,используйтециклdo...while.Вовсехостальныхслучаяхиспользуйтеоператорwhile.Каквыбратьмеждуоператорамиwhileиfor?В тех случаях, когда переменная счетчика еще не инициализирована и ее значениеизменяетсяпослекаждойитерациицикланапостояннуювеличину,используйтеоператорfor.Востальныхслучаяхпредпочтительнееwhile.Вкакихслучаяхлучшеиспользоватьрекурсию,авкакихитерацию?Несомненно, в большинстве случаев итеративный метод предпочтительнее, однако, еслиодин и тот же цикл приходится повторять в разных частях программы, удобнее использоватьрекурсию.Какойизоператоров,for(;;)илиwhile(true)работаетэффективнее?Существенногоразличиямеждуниминет.КоллоквиумВэтомразделепредлагаютсявопросыдлясамоконтроляиукрепленияполученныхзнанийи приводится несколько упражнений, которые помогут закрепить ваши практические навыки.Попытайтесьсамостоятельноответитьнавопросытестаивыполнитьзадания,апотомсверьтеполученные результаты с ответами в приложении Г.