246071-Либерти-Освой-самостоятельно-С-за-21-день (852741), страница 39
Текст из файла (страница 39)
Строка считываетсяфункцией GetWord(), параметрами которой является буферизированная переменная дляхранения первого слова и целочисленная переменная WordOffset. В строке 11 переменнойWordOffset присваивается значение 0. По мере ввода строки (до тех пор пока GetWord() невозвратитзначение0)введенныесловаотображаютсянаэкране.ПрикаждомвызовефункцииGetWord()управлениепередаетсявстроку27.Далее,встроке30, значение string[wordOffset ] проверяется на равенство нулю. Выполнение условия означает,чтомынаходимсязапределамистроки.ФункцияGetWord()возвращаетзначениеfalse.Встроке33объявляютсядвауказателянапеременнуюсимвольноготипа.Встроке34обауказателя устанавливаются на начало следующего слова, заданное значением переменнойWordOffset.ИсходнозначениеWordOffsetравно0,чтосоответствуетначалустроки.С помощью цикла в строках 37 и 38 указатель р1 перемещается на первый символ,являющийся буквой или цифрой.
Если такой символ не найден, функция возвращает false(строки41и42).Такимобразом,указательp1соответствуетначалуочередногослова.Строка46присваиваетуказателюp2тожезначение.В строках 49 и 50 осуществляется поиск в строке первого символа, не являющегося ницифрой, ни буквой. Указатель p2 перемещается на этот символ. Теперь p1 и p2 указывают наначало и конец слова соответственно. Вычтем из значения указателя p2 значение р1 ипреобразуем результат к целочисленному типу. Результатом выполнения такой операции будетдлина очередного слова (строка 55). Затем на основании данных о начале и длине полученноесловокопируетсявбуфернуюпеременную.Строкой 61 в конец слова добавляется концевой нулевой символ, служащий сигналомразрыва строки.
Далее указатель p2 перемещается на начало следующего слова, а переменнойWordOffset присваивается значение смещения начала очередного слова относительно началастроки.Возвращаязначениеtrue,мысигнализируемотом,чтословонайдено.Чтобыкакможнолучшеразобратьсявработепрограммы,запуститеееврежимеотладкиипоследовательно,шагзашагом,проконтролируйтевыполнениекаждойстроки.РезюмеУказатели являются мощным средством непрямого доступа к данным. Каждая переменнаяимеет адрес, получить который можно с помощью оператора адреса (t). Для хранения адресаиспользуютсяуказатели.Для объявления указателя достаточно установить тип объекта, адрес которого он будетсодержать, а затем ввести символ "*" и имя указателя.
После объявления указатель следуетинициализировать.Еслиадресобъектанеизвестен,указательинициализируетсязначением0.Для доступа к значению, записанному по адресу в указателе, используется операторразыменования (*). Указатель можно объявлять константным. В этом случае не допускаетсяприсвоениеданномууказателюновогоадреса.Указатель,хранящийадресконстантногообъекта,неможетиспользоватьсядляизмененияэтогообъекта.Чтобы выделить память для хранения какого-либо объекта, используется оператор new, азатем полученный адрес присваивается указателю. Для освобождения зарезервированнойпамятииспользуетсяоператорdelete.Самуказательприосвобождениипамятинеуничтожается,поэтому освобожденному указателю необходимо присвоить нулевое значение, чтобыобезопаситьего.ВопросыиответыВчемсостоитпреимуществоработысуказателями?Наэтомзанятиивыузнали,насколькоудобноиспользоватьдоступкобъектупоегоадресуи передавать параметры как ссылки.
На занятии 13 будет рассмотрена роль указателей вполиморфизмеклассов.Чемудобноразмещениеобъектоввдинамическойобластипамяти?Объекты, сохраненные в области динамического обмена, не уничтожаются при выходе изфункции, в которой они были объявлены. Кроме того, это дает возможность уже в процессевыполненияпрограммырешать,какоеколичествообъектовтребуетсяобъявить.Болееподробноэтотвопрособсуждаетсянаследующемзанятии.Зачемограничиватьправадоступакобъекту,объявляяегоконстантным?Следует использовать все средства, позволяющие предотвратить появление ошибок.
Напрактике достаточно сложно отследить, в какой момент и какой функцией изменяется объект.Использованиеспецификатораconstпозволяетрешитьэтупроблему.КоллоквиумВэтомразделепредлагаютсявопросыдлясамоконтроляиукрепленияполученныхзнаний,а также рассматривается ряд упражнений, которые помогут закрепить ваши практическиенавыки.Попытайтесьсамостоятельноответитьнавопросытестаивыполнитьзадания,апотомсверьте полученные результаты с ответами в приложении Г.
Не приступайте к изучениюматериала следующей главы, если для вас остались неясными хотя бы некоторые изпредложенныхнижевопросов.Контрольныевопросы1.Какойоператориспользуетсядляполученияадресапеременной?2. Какой оператор позволяет получить значение, записанное по адресу, содержащемуся вуказателе?3.Чтотакоеуказатель?4.Вчемразличиемеждуадресом,которыйхранитсявуказателе,изначением,записаннымпоэтомуадресу?5.Вчемразличиемеждуоператоромразыменованияиоператоромполученияадреса?6.Вчемразличиемеждуследующимиобъявлениями:constint*ptrOneиint*constptrTwo?Упражнения1.Объяснитесмыслследующихобъявленийпеременных:•int*pOne•intvTwo•int*pThree=&vTwo2.Допустим,впрограммеобъявленапеременнаяyourAgeтипаunsignedshort.Какобъявитьуказатель,позволяющийманипулироватьэтойпеременной?3.СпомошьюуказателяприсвойтепеременнойyourAgeзначение50.4.
Напишите небольшую программу и объявите в ней переменную типа int и указатель наэтоттип.Сохранитеадреспеременнойвуказателе.Используяуказатель,присвойтепеременнойкакое-либозначение,5.Жучки:найдитеошибкувследующемфрагментепрограммы.#include<iostream,h>intmain(){int*pInt;*pInt=9;cout<<"ThevalueatpInt:"<<*pInt;return0;}6.Жучки:найдитеошибкувследующемфрагментепрограммы.intmain(){intSomeVariable=5;cout<<"SomeVariable:"<<SomeVariable<<"\n";int*pVar=&SomeVariable;pVar=9;cout<<"SomeVariable:"<<*pVar<<"\n";return0;}День9-й.СсылкиНа предыдущем занятии вы узнали, как пользоваться указателями для управленияобъектами в свободной памяти и как ссылаться на эти объекты косвенным образом.
Ссылки,которые обсуждаются на этом занятии, обладают почти теми же возможностями, что иуказатели,ноприболеепростомсинтаксисе.Сегоднявыузнаете:•Чтопредставляютсобойссылки•Чемссылкиотличаютсяогуказателей•Каксоздатьссылкиииспользоватьих•Какиеограниченияестьуссылок•КакпоссылкепередаютсязначенияиобъектывфункциииизфункцийЧтотакоессылка Ссылка — это то же, что и псевдоним. При создании ссылки мы инициализируем ее спомощью имени другого объекта, адресата. С этого момента ссылка действует какальтернативноеимяданногообъекта,поэтомувсе,чтоделаетсясоссылкой,вдействительностипроисходитсэтимобъектом.Дляобъявленияссылкинужноуказатьтипаобъектаадресата,закоторымследуетоператорссылки (&), а за ним — имя ссылки.
Для ссылок можно использовать любое легальное имяпеременной, но многие программисты предпочитают со всеми именами ссылок использоватьпрефикс "г". Так, если у вас есть целочисленная переменная с именем someInt, вы можетесоздатьссылкунаэтупеременную,написавint&rSomeRef=someInt;Это читается следующим образом: rSomeRef — это ссылка на целочисленное значение,инициализированнаяадресомпеременнойsomeInt.Созданиеииспользованиессылокпоказановлистинге9.1.Примечание:Обратитевниманиенато,чтооператорссылки(&)выглядиттакже,какоператор адреса, который используется для возвращения адреса при работе с указателями.Однакоэтонеодинаковыеоператоры,хотяочевидно,чтоониродственны.Листинг9.1.Созданиеииспользованиессылок1://Листинг9.1.2://Примериспользованияссылок3:4:#include<iostream.h>5:6:intmain()7:{8:intintOne;9:int&rSomeRef=intOne;10:11:intOne=5;12:cout<<"intOne:"<<intOne<<endl;13:cout<<"rSomeRef:"<<rSomeRef<<endl;14:15:rSomeRef=7;16:cout<<"intOne:"<<intOne<<endl;17:cout<<"rSomeRef:"<<rSomeRef<<endl;18:return0;19:}Результат:intOne:5rSomeRef:5intOne:7rSomeRef:7Анализ:Встроке8объявляетсялокальнаяцелочисленнаяпеременнаяintOne,австроке9— ссылка rSomeRef на некоторое целое значение, инициализируемая адресом переменнойintOne.
Если объявить ссылку, но не инициализировать ее, будет сгенерирована ошибкакомпиляции.Ссылки,вотличиеотуказателя,необходимоинициализироватьприобъявлении.В строке 11 переменной intOne присваивается значение 5. В строках 12 и 13 выводятся наэкран значения переменной intOne и ссылки rSomeRef - они, конечно же, оказываютсяодинаковыми.В строке 15 ссылке rSomeRef присваивается значение 7. Поскольку мы имеем дело соссылкой, а она является псевдонимом для переменной intOne, то число 7 в действительностиприсваиваетсяпеременнойintOne,чтоиподтверждаетсявыводомнаэкранвстроках16и17.Использованиеоператораадреса(&)приработесоссылкамиЕслииспользоватьссылкудляполученияадреса,онавернетадрессвоегоадресата.Вэтоми состоит природа ссылок.
Они являются псевдонимами для своих адресатов. Именно этосвойствоидемонстрируетлистинг9.2.Листинг9.2.Взятиеадресассылки1://Листинг9.2.2://Примериспользованияссылок3:4:#include<iostream.h>5:6:intmain()7:{8:intintOne;9:int&rSomeRef=intOne;10:11:intOne=5;12:cout<<"intOne:"<<intOne<<endl;13:cout<<"rSomeRef:"<<rSomeRef<<endl;14:15:cout<<"&intOne:"<<&mtOne<<endl;16:cout<<"&rSomeRef:"<<&rSomeRef<<endl;17:18:return0;19:}Результат:intOne:5rSomeRef:5&intOne:0x3500&rSomeRef:0x3500Примечание:Результаты работы программы на вашем компьютере могут отличатьсяотприведенныхвпоследнихдвухстроках.Анализ:Ивновь-такиссылкаrSomeRefинициализируетсяадресомпеременнойintOno.Наэтотразвыводятсяадресадвухпеременных,иониоказываютсяидентичными.ВязыкеC++непредусмотренопредоставлениедоступакадресусамойссылки,посколькувэтомнетсмысла.Стаким же успехом для этого можно было бы использовать указатель или другую переменную.Ссылки инициализируются при создании, и они всегда действуют как синонимы для своихадресатов,дажевтомслучае,когдаприменяетсяоператорадреса.Например,еслиувасестькласссименемCity,вымоглибыобъявитьобъектэтогоклассаследующимобразом:Cityboston;Затем можно объявить ссылку на некоторый объект класса City и инициализировать ее,используяданныйконкретныйобъект:City&beanTown=boston;СуществуеттолькоодинклассCity;обаидентификаторассылаютсянаодинитотжеобъектодного и того же класса.
Любое действие, которое вы предпримите относительно ссылкиbeanTown,будетвыполненотакжеинадобъектомboston.Обратите внимание на различие между символом & в строке 9 листинга 9.2, которыйобъявляет ссылку rSomeRef на значение типа int, и символами & в строках 15 и 16, которыевозвращаютадресацелочисленнойпеременнойintOneиссылкиrSomeRef.Обычнодляссылкиоператорадресанеиспользуется.Мыпростоиспользуемссылкувместосвязаннойснейпеременной,какпоказановстроке13.Ссылкинельзяпереназначать Даже опытных программистов, которые хорошо знают правило о том, что ссылки нельзяпереназначать и что они всегда являются псевдонимами для своих адресатов, может ввести взаблуждение происходящее при попытке переназначить ссылку.
То, что кажетсяпереназначением, оказывается присвоением нового значения адресату. Этот фактиллюстрируетсявлистинге9.3.Листинг9.3.Присвоениезначенияссылке1://Листинг9.32://Присвоениезначенияссылке3:4:#include<iostream.h>5:6:intmain()7:{8:intintOne;9:int&rSomeRef=intOne;10:11:intOne:512:cout<<"intOne:\t"<<intOne<<endl;13:cout<<"rSomeRef:\t"<<rSomeRef<<endl;14:cout<<"&intOne:\t"<<&intOne<<endl;15:cout<<"&rSomeRef:\t"<<&rSomeRef<<endl;16:17:intintTwo=8;18:rSomeRef=intTwo;//неточтовыдумаете19:cout<<"\nintOne:\t"<<intOne<<endl;20:cout<<"intTwo:\t"<<intTwo<<endl;21:cout<<"rSomeRef:\t"<<rSomeRef<<endl;22:cout<<"&intOne:\t"<<&intOne<<endl;23:cout<<"&intTwo:\t"<<&intTwo<<endl;24:cout<<"&rSomeRef:\t"<<&rSomeRef<<endl;25:return0;26:}Результат:intOne:5rSomeRef:5&intOne:0x213e&rSomeRef:0x213eintOne:8int:Two:8rSomeRef:8&intOne:0x213e&intTwo:0x2130&rSomeRef:0x213eАнализ:Вновьвстроках8и9объявляютсяцелочисленнаяпеременнаяиссылканацелоезначение.Встроке11целочисленнойпеременнойприсваиваетсязначение5,австроках12-15выводятсязначенияпеременнойиссылки,атакжеихадреса.В строке 17 создается новая переменная intTwo, которая тут же инициализируетсязначением8.Встроке18программистпытаетсяпереназначитьссылкуrSomeRefтак,чтобыонастала псевдонимом переменной intTwo, но этого не происходит.