Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 147
Текст из файла (страница 147)
Функции азз!дп() используются для присваиваний, сопоставляемым конструкторам со многими аргументами (5!6.3.4, 520.3.4). Как упоминалось в 511.12, тип «зг!пд можно оптимизировать так, чтобы копирование фактически выполнялось лишь тогда, когда на самом деле требуются две раздельные копии строки. Класс ззг!пд запроектирован таким образом, что он поощряет создание реализаций, минимизирующих фактическое копирование. Это делает применение строк «только для чтения» и их передачу в качестве аргументов функциям более дешевым. Но программистам следует детально ознакомиться с конкретными реализациями, прежде чем полагаться на такую оптимизацию (520.6(13)).
Глава 20. Строки сонм СЬ* еаза ( ) сопев! з!зе гуре сору (Оь* р, з!зе гуре п, з!ге гуре роз = О) сопл!! // ... ): Функция ч!а!а () пишет символы строки в массив и возвращает указатель на этот массив. Массив принадлежит строке типа витям и пользователь не должен пытаться его уничтожать. Пользователь также не должен полагаться на содержимое массива после выполнения над строкой неконстантной операции (вызова неконстантной функции). Функция с згг() похожа на г!ага (), но добавляет в конец массива терминальный нуль. Например: //зйепдйо== 7 Рр! указывает на 7 символов //плохо: отсутствует терминальный нуль р1[2) = 'а'; 5[2) = 'а'; сваг с = р1[1) ' сопзг сваг* р2 = з.с зг'(); //р2 указывает но восемь символов рг!п(Г(чр2 = %зчпч,р2) ) //о!с с з(г() добавляет терминальный нуль Другими словами, ч!а!а () создает массив символов, в то время как с згг() создает С-строку.
Эти функции предназначены в первую очередь для того, чтобы упростить применение функций, использующих С-строки. Следовательно, с згг() представляется более полезной, чем Ыа!а() . Например: В типичном случае, пока вам символы непосредственным образом не требуются, лучше оставить их в составе строки типа ззг!пя. В то же время, если вы не можете сразу распорядиться ими, то символы можно скопировать и во внешний буфер, а не оставлять их во временных буферах, выделяемых функциями с ззг() или е!а!а().
Для этого предназначена функция сору() . Например: сваг* с згг!пд(соагаззг!паз з) ( сйаг* р = пою с!ьаг[з.1епдзй() +1); //внимание: +! длл терминального нуля р[в.сору(р,згг!пд::проз) ] = 0; /Увнимание: добавляем терминатор и гегигп р; ге!игл р! ) Вызовом з. сору (р, и, гп) в область памяти, указуемую через р, копируется не более и символов, начиная с з [гп) . Если в строке з символов меньше, чем и, функция сору() просто копирует все имеющиеся символы.
го!а 2'( ) ( згг!па з = неаи!похч; сопя спаг* р! = з. дага (); рг!пй" (ьр! = лвзч пь,р1) г ио!Й)'(згг!пд з) ( !пз ! = аго! (з. с зо ( ) ); // ... ) гУ еггог: р! указывает на константный массив //плохо: доступ к з.йа(ао после модификации з // получает числовое значение из цифр строки (з20.4.!) 20.3 Стандартный строковый шаблон Ьаяс з(ппд 701 1еа аго1 (сопзт зтг)ляь з) ( ге!игл ага!(з.с згг() ) ) 20.3.8. Сравнения Строки можно сравнивать со строками их же типа и с массивами элементов того же самого символьного типа; гетр!иге<с!азз СЬ, сгая уг = сьаг тга11з<СЬ>, сгазз А = айосагог<СЬ» с1ат Ьаяс зтг(пе ( риЫ(с: У...
1и сотраге (сопя Ьаяс зггглеь з) соле!; !лт сотраге (сопи СЬ* р) сопят; У комбинируются > и тг сотраге(яге гурероз, яге гуре л, сопя Ьаяс згнплг з) сопя; 1пг сотраге(яге туре роз, згйе гуре и, сопя Ьаяс яппяг З, яге гуре роз2, згге гуре п2) сопзг; т< сотраге(з(ге гуре роз, яге гуре л, сопят СЬ* р, з)ге ~ре п2 = проз) сопзг; ll .. )( Когда строке передаются позиция и размер в виде параметров функции сотраге(), используется лишь обозначенная тем самым подстрока. Например, з. сотраге (роз, и, з2) эквивалентно яг1пй(з,роз, и) . сотраге (з2) .
В качестве критерия сравнения используется сотраге() из сйаг иа)вз<СЬ> (820.2.1). Таким образом, з.сотраке(з2) возвращает нуль, если строки имеют одинаковое значение; отрицательное число, если з лексикографически предшествует з2, и положительное значение в противном случае. Пользователь не может задать свой критерий сравнения, как это делалось в 5!3.4. Если нужен такой уровень гибкости, мы можем применить !ах!со)!гарйса1 соиграге() (518.9), определить функцию, как в 513.4, или написать явный цикл.
Например, функция «пзррег() (520.4.2) позволит нам выполнить сравнение без учета регистра символов: Отметим, что строки типа яг1ия могут содержать нули. Функции, манипулирующие С-строками, воспримут эти нули в качестве терминальных. Поэтому вносите нули либо если вы не собираетесь обращаться к функциям, работающим с С-строками, либо вносите их именно в качестве терминальных.
Для преобразования к С-строкам предназначена также и операция орегагог соиМ сйаг* (), а не только функция с згг() . Она дает удобство неявного приведения вместе с сюрпризами в виде непреднамеренных преобразований. Если функция с яг() слишком часто вызывается в вашей программе, то скорее всего вы излишне опираетесь на интерфейсы в С-стиле. Почти всегда есть возможность полностью перейти на интерфейсы класса згг1пя, что устранит необходимость в лишних преобразованиях.
Можно и по-другому избавиться от явных вызовов функции с згг(), просто определив свои собственные функции вместо тех, которые требуют вызовов с з(г (): ех~егп С" тг ого! (сопят слег*); Глава 20. Строки <зм стр посазе (соле< в<«<паз з, сопев в<«<паз з2) в<«<ля<:соле< Йега<ог р = з. Ьефл (); з<г(пд «соле< 1<его<о« р2 = з2. Ьефп (); <«Ь11е(р! =з.ела () ьь р2! =з2.еп«() ) ( (Т (<оиррег (*р) ! =<оиррег (*р2) ) ге<игл (<оиррег(чр) «оиррег("р2) ) ? -1: 1; +ар; ++р2< ) ге<игл (з2.в<ге() ==з.в<ге() ) ? О: (з.в<ге() <з2.з!ге() ) ? -1: 1< ) воЫ/'(солз< зл!лаа з, сопел в<«<ада з2) ( <Г(з == з2) ( УУ ..
) УУ сравнение з и з2 с учетом регистра (Г(стр посазе(з,з2) == О) ( УУ ... ) УУ... ) У сравнение з и з2 без учета регистра Для типа Ьаяс зй 1лд определены обычные операции сравнения ==, .' =, >, <, >= и «< <етр<а<е<с<азз СЬ, с<лаз Тг, с<аз<А> Ьоо< орега<ог== (сола Ьаз!с з<г<пд<СЬ, Тг, А> з, соле< Ьаз<с ел<па<СИ, Тг, А> ь ); <етр<а<е<с<азз СЬ, с<азз Тг, с1азз А> Ьоо< орега<ог== (солз< Сй*, сопз< Ьаз!с з<г<пд<СЬ, Тг, А>й ); <етр1а<е<с1азз СЬ, с<а<в Т«, с1ат А> Ьоо< орега<ог== (сопя< Ьаз<с <аг<пд<СЬ, Тг, А>а, сопз< СЬ*) IУ аналогичные объявления дяя 1=, >, <, >= и <= «оЫ Г(соля< в<«<пай лате) ( (/(лате =="ОЬе<сс" ( ( "Аз<епх" ==лате) ( УУ ...
УУ используется оптимизированная == Операции сравнения определены вне класса Ьаз<с зп!ля(то есть не являются его членами), так что преобразование типов одинаковым образом применимо к обоим операндам (511.2.3). Версии, работающие с С-строками, введены для оптимизации сравнения с литералами. Например: 20.3. Стандартный строковый шаблон (заз)с з(ппо 703 20.3.9. Вставка Когда строка создана, ею можно манипулировать разными способами. Из всех операций, изменяющих содержимое строки, наиболее распространенной является операция добавления навьи символов в конец строки (оррел(((пя). Вставка символов в иные позиции внутри строки встречается реже: (етр(а(е<с(азз СЬ, с(азз (г = сяаг (га!(з<СЬ>, с1ат А = айоса(ог<СЬ» с1ат Ьаяс з(г!ия ( риЫ(с: //...
//добавление символов после (*(Ь(з)(!епд(ЬВ<Ц; Ьаяс зп !пяь орега(ого= (сопз! Ьаяс з(г!пйа з) ( Ьазк зсйпйз орега(о«+= (сопл( СЬ* р) ( Ьаяс з(г!пяв орега(ого= (СЬ с) ( юЫризЬ Ьаса(СЬ с); Ьазк з(г!пвз арреп(((соля Ьаяс з(ппяв з) ! Ьаяс з(г!пяь аррел(((сопл! Ьаяс з(г!пяз з, зае (уре роз, яге (уре и) Ьаяс з(г!лез аррел(((соля СЬ* р, яге (уре п); Ьаяс з(г!лвз арреп(((сопя СЬ* р) ! Ьаяс з(г!ивз аррепд(зае (уре и, СЬ с); (етр1а(е<с1азз 1п> Ьаяс з(г!пяа арреп(( (1п ((гз(, 1п 1аз() ( // вставка символов перед (*(Ь(з)(роз)! Ьаяс з(г!пйа тзег((яге (уре роз, сопя! Ьаяс з(г!пда з); Ьаяс з(г!пяз Ызег((з1ге (уре роз, сопл( Ьаяс з(г!пвз з, зае (уре роз2, яге (уре и) Ьаяс з(пияв !пзея(яге гуре роз, соле( СЬ* р, яге (уре и); Ьаз!с з(г!лаз тле«((яге (уре роз, сопл( СЬ* р); Ьаяс з(плйз !лзеп(яге (уре роз, зае (уре п, СЬ с); // вставка символов перед р: йега(ог !лзег((йега(ог р, СЬ с); «оЫ (пзег((йегатгр, яге (уре п, СЬ с) ! (етр(а(е<с(азз 1п> юЫ (пзе«( (!(ега(ог р, 1п ((гз(, 1п (аз(); // ...
Операция в= обеспечивает наглядное отображение для большинства операций добавления символов. Например: з(г(ля сотр!е(е пате ( соле! з(г!пяз у)гз( пате, соаз! з(г!ляг 1атйу лате) ( з(г!пв з = ((гз( пате> 3 в= з в=уатйу лате; ге(игл з; ) Добавление символов в конец строки часто намного эффективнее вставок символов в иные позиции. Например: зи!пя сотр1е(е пате2 (соил( з(г(ияа 27«з( па(пе, сопя з(плов (атйу пате) й плохой алгоритм 204 Глава 20.
Строки 1 я(г!нд я = Тат!(у пате; з.!нзег<(я. Ьед!п (), ' ' ); гетгн з. (тег((0,!)гз< нате) ) В общем случае вставки вынуждают реализацию з(г1пд вьшелять дополнительную память и переписывать символы с места на место. Поскольку з(г(поимеет операцию рпзЬ Ьасй() (в163.5), для строк можно применять Ьасй (пяег(ег() так же, как для любых стандартных контейнеров. 20.3.10.
Конкатенация Добавление символов в конец — это специальный случай конкатенации. Конкатена<(ия (солса<ела(!ои) — формирование строки из двух строк их сцеплением, выполняется операцией я< <етр(а<с<с(аяя СЬ, с(аяз Тг, с1ат А> Ьаи'с тп'пд<СЬ, Тг, А> орега<ого (соня( Ьаис тгтд<СЬ, Тг, А>ь, соля< Ьаис з*!пе<СЬ, Тг, А>я) <етр(а(е<е(ат СЬ, с(азя Тг, с(от А> Ьаис я(ипд<СЬ Тг, А> орега(ого(соня( СЬ*, сопя( Ьоис з(г!нд<СЬ, Тг,А>я) <етр(а(е<с(аяя СЬ, с1ат Тг, с(ат А> Ьаие я(г!ля<СЬ, Тг, А> орега(оге (СЬ, сопи Ьаис з<г!пе<СЬ, Тг, А>я) (етр!а(с<с!азя СЬ, с(азз Тг, с(аяя А> Ьаис з(г!лд<СЬ, Т<,А> орега(ого (сопи Ьаис з(г!пд<СЬ, Тг,А>я, соля( СЬ*) (етр!а(е<с!аяз СЬ, с(ат Тг, с(азз А> Ьаис я(г!щ<СЬ, Тг,А> прего<ос+ (соня< Ьая!с аппд<СЬ, Тг,А>з, СЬ) Как обычно, операция + определяется вне класса Ьаис з(г1пд (не является его членом).