Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 146
Текст из файла (страница 146)
Проект стандартного класса я1г!пд' поощряет создание реализаций, минимизирующих действительное копирование. Это делает использование строк, которые только считываются и задаются в качестве аргумента, гораздо более дешевым, чем кто-то мог по наивности предположить. Однако было бы также наивно со стороны программистов не проверять имеющиеся у них реализации перед написанием кода, который полагается на оптимизацию копирования строк Я 20.6[13]). Глава 20. Строки ббб Иными словами, с(а1а () создает массив символов, в то время как с я1г () создает С-строку. Эти функции предназначены прежде всего для того, чтобы упростить использоваг нне функций, которые требуют С-строк, н следовательно, с я1г () будет применяться чаще, чем Оа1а ().
Например: иоЩ(я1п',пяя) ( !п1 1=п1о( (я.с ягг ()); // по цифрам из строки выдает //целочисленное значение Ц 20яп1! Как правило, пока символы вам не нужны, лучше всего оставлять их в я1г(пп. Однако если вы не можете пользоваться символами непосредственно, вы можете скопировать их в массив, а не оставлять в буфере, выделенном фунцциями с я1г () и с(а1а (). Для этого введена функция сору (). Например; спаг' с я1ггпя (сопяг я1г1пуа я) ( сваг' р = пеш сваг(я1епО(Ь ()ч1); // заметьте: «-1 я.сору (р, я1гтдс про 4, р(я. Еепяг Ь (Ц = О; // заметьте: добавляем завершаю цьш символ ге1и~ и р; Вызовом я.сору (р, и, т) копируется не более чем и символов в р, начиная с я[т].
Если в строке я символов для копирования меньше, чем и, сору () просто копирует все символы, какие есть. Отметим, что я1г(пйможет содержать и символ с кодом О. Функции, манипулирующие с С-строками, воспримут этот О как завершающий символ. Будьте осторожны. Не помешайте в строку нулей, если вы применяете функпин в стиле С (если только вы не используете О именно как завершающий символ). Преобразование в С-строку может быть обеспечено оператором орега1ог сопя1 сваг* (), а нс с я1г (). Это обеспечило бы удобство неявного преобразования, но ценой всякого рода сюрпризов в тех случаях, когда такого преобразования не ожидалось. Если вы обнаружите, что с я1г () появляется в вашей программе чрезвычайно часто, вероятно, вы слишком полагаетесь на интерфейсы в стиле С.
Часто бывает доступен аналогичный интерфейс, опирающийся на я1г(пп, а не на С-строки, и, чтобы избежать преобразований, можно воспользоваться им. Вы можете устранить большинство явных обращений к с ягг() и другим образом — - обеспечив дополнительное определение тех функций, которые заставляют вас писать вызовы с я1г (): ек1егп 'С" 1п1а1ог (сопя1 сдпг*); т1 и 1о1 (со пя1 я1П пуд я) ге1игпа1ог(я.с яг ()); 20.3.8. Сравнения Строки можно сравнивать со строками нх же типа и с массивами символов того же символьного типа: 557 20.3.
Тип Ьаяс злпп0 1етр(аге<с1аии СЬ, с(аяи 7г = сбою 1гасси<СЬ>, с!аииА = а11осагог<СЬ» с!аии Ьаиис и1г!пу( рибйс: // сочетает > и == ш! сотраге (сопи! Ьасис и1гшу& игг) сопя1; лп1сотриге (сопи! Сб*р) сопи1; шссотраге (и!ее 1уре рои, игее 1уре и, сопи1баи!с ибяпу& и1г) сопя1; лп1сотраге (и!ге 1уре роз, сдге 1уре и, солт Ьаи!с и!г1пу&и!г,и!ее !урерои2, и!ге 1уре п2) сопи!; !тсотраге(итие 1уре роз,и(ге 1уре п, сопи1 Сб*р,игее !уре п2= прои)сопи1; //- ); ш1 стр посаие (сопя! я1ппр& и, сопи1 тг!пу& з2) и1г(пдгсопя! Иега1огр = и.бедш (); и1г!пуссопи1 11ега1огр2 = и2.беуш (); шб!1е ф и.епл(() && р2~=и2.еп<1()) ( (/ (го иррег (*р) Л= !о и ррег ('р2)) ге!ига (1оиррег ("р) < 1оиррег (*р2)) 2 — 1 .
'1; "Н.р; .н-р2; //ипге не имеет энанв ге1игп (я2.зисе ()==я.з(ее ()) 3 0: (илгее () <и2 и(ее ()) 2 — 1: 1; ) иоЩ(сопи! и1г!пу& и, сопи! игг!пу& я2) ( ~У (и == и2) ( //.. // сравнение и и и2 с учетом регистра // сравнение и и я2 беи учета регистра (/'(стр поспие (и,и2)== О)( //- //... Для баз(с з1г(пя'введены обычные операторы сравнения ==,!-, >, <, >= и <ес Если для строки со!праге () заданы позллция и размер, используется только указанная подстрока Например, жсотраге (я, роя, п) эквивалентное(лтпй(роя, и, и2) сотраге (я2), В качестве критерия сравнения используется сотраге() из сйа! !га!1з<Сй> Я 20.2.1).
Такллм образом, я.сотраге (з2) возвращает О, если строки имеют одинаковое значение; отрицательное число, если и лексикографически находится перед з2, и положительное число в противном случае. Пользователь не может задать свой критерий сравнения, как это делалось в б 13.4. Когда нужен такой уровень гибкости, мы можем воспользоваться (ех(содгарй(са( сотраге () 8 18.9), определить функцию, как в 9 13.4, или написать явный пикл.
Например, функция 1оиррег () (9 20 4 2) позволяет нам написать сравнение без учета регистра: Глава 20. Строки 1етр1а1е<с1акв СБ, с!азз Тг, с!аякА> Ьоо! орегагог == (сопк1 Ьав!с вгг!пу<СБ, Тг А>&, сопя! Ьав!с вгплу<СБ, Тг А>й), 1етр!аге<с1азз СЬ, с!аяя Тг, с!аяяА> Ьоо1 орега1ог== (соля1СЬ", сопк1 Ьаеяс вгппу<СЬ, Тг, А>й); 1етр1аге<с1аяя СБ, с1аяя Тг, с!аяя А> Ьоо(орега1ог== (сопи!бои!с вгппу<СБ, ТгА>й, сопв1СБ ), гггг аналогинние оаъявления для!=, >, <, >= и <= оо!с!Т (сопя1 я!с!ау& пате) ( гу" (пате == ОЬе!!х (('Ав1епх == пате) ( ,г,г) гггг используется опгтгмизированное == 20.3.9.
Вставка Когда строка создана, ею можно манипулировать по-разному. Среди операций, изме- няющих значение строки, одной из самых распространенных является «приписыва- ние» к ней — то есть добавление символов в конец. Вставка в другие места строки встречается реже; гетр!иге<с!аяк СЬ, с!акз Тг= сБит 1гайя<СЬ>, с!аяв А = а!!оса1ог<СБ» с!акк Ьав!с вЖпд( риЫ!с: 0-. г ! добавление символов после !" 1Б!и) (!егу11Б () - !): Ьав!с в!пну& орега1огя= (солз1 бав!с згг!луй вгг)г Ьав!с к1г!пуй орегагог+= (сопи! Сб*р)г баксе я1ппуйорегагог»= (сопкгСЬ с); оо(<1рикб Ьасб (СБ с); бав!с в!пну& аррепс! (сопя! бав!с и!пну& з1г); Ьав!с я!пну& аррепс! (сопя! баз!с вггшуй з, з!ее гуре роя, в!ие 1уре п); Ьав!с ягппд&аррелд(сопк1СБ'р,в!ее сурен); База я!пад& аррелд (соли! СБ* р); бак!с я!пну& аррепд (в!ее 1уре и, СБ с); гетр1аге<с1аяв 1п>бав!с я!пну& аррепд (!п)ггв1, 1п !аяг) гг! всгпавка символов перед Г*гб!в)(ров)г бав!с ягг!ля& итеП (я(ие гуре роя, сопи! Ьая!с з1ппуй згг); Ьав!с я!пну& шяегг (иске 1уре рок, соля! Ьав!с ягг!луй к, кгее 1уре роз2, к!ее 1уре п); баз!с з1ппуй шзеП (в!ие 1уреров, сопя! СБ'р, яме 1уре л); Ьая!с кгппуй гпяегг (згее 1уре рои, сопи! СБ* р); Ьав!с я!ггпу& шзегг (и!ив гуре роя, в!ее 1уре и, СЬ с); Операторы сравнения — это функции-не-члены, поэтому преобразования оди- наково применимьь к обоим операндам Я 11.2.3).
Для оптимизации сравнений со строковыми литералами прсгдоставлены версии, принимающие С-строки. На- пример: б59 20.3. Тип (заз1с з1ппд (/ вставка символов перед р; !1ега1ог !пяег (11ега1ог р, СЬ с(; ио!г1!пяег1 (!1ега1огр, я!ее 1уре и, СЬ с(, гетр!осе<с!аяя Тп>иоЫ !пяегГ (!1ега1ог р,!паек!, !и !изг) пои!риза Ьасу(СЬс(; 0- В основном, многочисленные операции, введенные для инициализации строк и присваивания, доступны также и для вставки символов перед некоторой позицией и добавления в конец строки. Для наиболее распространенной формьк добавления предоставлен оператор +=, как удобное и понятное обозначение.
Например: я1г!пд сотр!есе пате (сопя1ксг!пуГ (! яг пате, сопя! ясппув,/ат!!у пате( ( //сотр!еуе пате — имя ифагаиия (/3гзг пате — имя //!атду пате — фамилия я1ппу я /1гя1 лите; я+ я+=,~ат!!у пате; ге1игп к; Добавление в конец строки может быть значительно эффективнее, чем вставка в дру- гую позицию. Например: к1г!пд соп1р!есе пате2 (сопз1 я1г(пуР<йге! аате, сопя1 я1г!пуй (атяу пате) // не сли~икомлороыий алгоритм ( ягг!пу я =/ат!!у пате; купзег1 (з.Ьеу(п ((,' '(; ге1игп < тяег1 (О,/1гя1 пате(; Обычно вставка вынуждает реализацию з1г!пд выделять лишнюю память н переписывать символы с места на место. Поскольку я1г!пя имеет операцикз раей Ьасй !9 16.3.5), для строк можно использовать Ьас(е !пзег(ег точно так же, как для общих контейнеров.
20.3.10. Конкатенация Добавление символов — это особая форма конкатенации. Конкатенация — конструирование строки из двух расположением одной после другой — обеспечивается оператором +: 1етр!псе<с!азя СЬ, с1азз Тг, с1аяя А> Ьая!с я1ппу СЬ, Тг,А> орега1ог> (сопягЬаягс я1ппу<СЬ, Тг,А>6, сопя! Ьаясс я1ппу<СБ, Тг,А>Е~; 1етр!а1е<с!акя СЬ, с!азк Тг, с!аяк А> Ьая!с я1г!пу СЬ, Тг, А> орега1ог+ (сопя! СЬ', сопя1 Ьаз!с ясггпу<СЬ, Тг, А>1(; Глава 20.
Строки 660 Гетр!а1е<с!аяк СЬ, с1икз Тг, с!аккА> Ьаис к!пну.СЬ, Тг,А> орегаГогь (СЬ, сопя! Ьпис згг(лу<СЬ, Тг,А>8); Гетр!а1е<с!азк СЬ, с!акк Тг, с!азкА> Ьаыс зггЕпу<СЬ,ТгА прего!ось (сопзЕЬак!с згг(лу<СЬ,ТгА>й,сопкГСЬ'); Еетр1а1е<с!акк СЬ, с1азз Тг, с!аккА Ьпз!с зЕГЕпд<СЬ, Тг, А> орегаГог+ (сопк1 Ьазгс зГГЕлу<СЬ, Тг, А>й, СЬ), ге!игл/егзЕ лите я ' 'я/птуу пате Это удобство записи может достигаться ценой некоторого перерасхода времени по сравнению с сотр1е1е пате (). Для сотр1е1е патеЗ () требуется одна лишняя временная переменная (~ ! К3.2).
На своем опыте я убедился, что это редко бывает важно, но об этом стоит помнить, когда пишешь вложенный цикл в программе, в которой требуется быстродействие. В этом случае мы могли бы попробовать устранить вызов функции сотр!е1е пате (), сделав ее встроенной 1!л1!пе), или составлять результируюшуке строку путем применения операций низкого уровня Я 20.6(14]), 2а.ЗЛ ~. П ок Множество функций для поиска подстрок может обескуражить: 1етр!а1е<с)акк СЬ, с)азз Тг = сааг 1ги!1к<СЬ>,с1азз А = и!Еоса1ог<СЬ» с)ажч ЬазЕс зЕгЕлу ( риЫЕе 0 ... // поиск лодпоследовательности !наподобие кеаесЬ 1) у ! 8.5.5): ззяе Гуре/!ад (сопз1 Ьачес зГг!луйк, к)зе 1уре е = О) сопз1; кгее Гуре/елеЕ (сопя! СЬ'р, я!ее 1уре е', к!ее 1уре л) сопк1; кззг Гуре/(пеЕ(соляЕСЬ'р, к!ее 1урее = О) сопк1, к!ее Гуре/епсЕ(СЬ с, Ыяе 1уре е = О) соля!; //лился лодлосчедовательности, начинив с конца !подобно!чае! еле! козе 1уре г/епсЕ (сопкЕ Ьатс зГГЕлдй к, з(зе Гуре е = проз) сопк1; з(зе Гурееуелд(солзЕСЬ'р,к!ге Еурее,зсее Гуре п) сопкЕ, яссе 1урегУ<пд(сопк1 СЬ*р,з)яе Еурее =профсопкб к!ее Гуре г/епд (СЬ с, к)яе Гуре е = проз) сопз1; //ноиск силвола ГналодобиеЯпд /ия1 о/!) в у 18.5.5): к!ее Гуре/епс( Ягзг о/(солз1 Ьаяс кгг!пуйз, к!ее 1уре е = О) сопкЕ; з)яе Еурефлд Огзг о/(солкГСЬ*р,з)ге Гуре(,зые Еуреа) салай з)яе Гуре/елд Егьу о/ (сопз1СЬ* р, з)зе 1уре ! = О) сопя!; к!ее Гуре/епд йгзГ о/ (СЬ с,ксее Гуре!= О) сопя!, // поиск символа из аргумента, начиная с конца: зсее Гуре/!лд !азЕ о/(сопя! Ьак)с кГЕЕлуй к, з!зе Гуре е = проз) соля!; зсее Гуре/!пеЕ 1аз1 о/(солзГСЬ'р,з(яе 1урее,з(ее 1уреи) соля!; !), э" !8.5 5) Как обычно, оператор ь определен как функция-не-член.