Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 146
Текст из файла (страница 146)
20.3.3. Доступ к элементам (символам) Доступ к отдельным символам строки возможен с помощью индексирования: гетр1аге<с[авв Сй, с[ива Тг = сйаг ггаггв<СЬ>, с[иве А = апосагог<СЬ» с(авв Ьалс вгг1ия ( риЫ[с: г7... И доступ к элементам (как у иесгог: З! б.3.3): сопвг геуегепсе орегагог[] (в[се !уре и) соивг; Удостуи беэ проверки ге~егепсе орега<ог[) (в!ге гуре и); У доступ с проверкой свив! геГегепсе аг (в!се (уре и) сопвгг ге)егеисе аг (иге гуре и); У... ) При выходе за границы диапазона символов строки функция аг() генерирует исключение оиг о1' гаияе.
По сравнения с тес(ог, у класса з(ппй отсутствуют операции Иигиг ( ) и Ьасй ( ) . Чтобы обратиться к первому или последнему символу строки„мы должны написать соответственно в[01 и в[в. !епагй () -11. Дуализм «указатель/массив» (95.3) для типа вгг!ия не имеет места. Если в — это строка типа агг!ия, то м [ 01 — это не то же самое, что в. 20.3.4. Конструкторы Набор операций инициализации и копирования для типа вгг1ия отличается от такового для остальных контейнеров (516.3А) во многих деталях: гетр!те<с)авв Сй, с)авв Тг = сйаг гга!св<СЬ>, с!авв А = адосагог<СЬ» с(а55 Ьа51с ви 1ид ( риЫгс: Глава 20.
Строки 696 уу ... )(конструкторы и т.д. (немного положе на гесгог и лис 416,3.4): екрйсй Ьаз(с ииг(лл (сопли А и а = А ( ) ); Ьаяс зипл8(сопли Ьаз(с зипплз з, з(зе (уре роз = О, и(ее (уре и = прои, сопя Аз а = А () ); Ьаяс ыпл8 (сопзг СЬ* р, з(зе гуре п, сопя А а а = А () ); Ьаяс изппл (сопи( СЬ* р, сопигАз а = А () ); Ьаи(с игппл (и(зе гуре и, СЬ с, сопли Аз а = А () ); зетр(азе<с(азз 1п> Ьаз(с зиг(л8 (1п 1)гзз, 1п 1азб салаг Аз а = А () ) -Ьаяс зиг(л8 (); зиаз!с сопз( з(ге гуре проз; уу ... гоы Г(сваг* р, гесгог<сьаг> и и) ( зиг)лл иО; згг)ллиОО = ""; )У пустая строка УУ тоже пустая строка УУ епоп нет приведения из слог в ио!п8 УУ еггоп нет приведения из (пг в зпчп8 УУ еггог: нет соответствующего конструктора игг)п8 и1 = 'а'; згг(л8 з2 = 7; згпл8 и3 (7): зиг(л8 з4(7, 'а' ) и УУ 7 копий 'а', то есть "ааааааа" игг1лл и5 = г го«(о ззг(п8 зб = и5; уу копия гргодо" УУ копия и5 ззг(лл и7(и5,3,2); яппл з8 (р«7, 3); яппли9(р, 7,3) ) УУ и5(3) и и5(4); то есть 'Ыо" УУ р(7),р(8) и р(9) У)и(г(пл(игг(пл(р), 7,3), расточительно ззплл з10(».Ьел(п (), и.
епд() ) и У копирует все символы из г Символы нумеруются начиная с нуля, так что строка — это последовательность символом с номерами от О до 1елйгй () -1. Функция!епйтй () есть фактически синоним для и(зе(): обе функции возврашают количество символов в строке. Отметим, что работа этих функций не базируется на понятии терминального нуля, заканчиваюшего собой С-строки (920А.)).
Реализации Ьаяс изг)л8 хранят длину строк, не полагаясь на терминальный нуль. Подстроки фиксируются начальной позицией и числом символов. По умолчанию проз инициализируется максимально возможным числом символов, трактуемым как «все элементы». Не сушествует конструктора, который создает строку из и неопределенных символов. Ближайшим по смыслу является конструктор, который создает строку из и копий заданного символа. Отсутствие конструкторов, которые принимают единственный символ или одно лишь число символов, позволяет компилятору обнаруживать ошибки, такие как определение и1, з2 и иЗ в вышеприведенном примере. Строку типа згг(лл можно инициализировать С-строкой, другой строкой типа зл 1п8, полстРоками С-строк или строк типа ил 1п8, или послеДовательностью символов.
Но ее нельзя инициализировать символом или числом: 20.3. Стандартный строковый шаблон Ьаз(с мппй 697 чаЫ2'(»1ггпя з) ( тзтг(пя тз (з . Ьееги ( ), з . еи4 ( ) ); У... ~У кап«руются все символы из з Каждый элемент типа )чсйаг г в строке ив инициализируется соответствуюшим элементом типа айаг из з. 20.3.5. Ошибки Когда строки просто считывают, записывают, печатают, хранят, сравнивают, копируют и так далее, то при этом не возникает никаких проблем, кроме, возможно, производительности. Иное дело, когда мы начинаем использовать отдельные символы или подстроки для того, чтобы из сушествуюших строк получить новые строки — тут легко нарваться на ошибки, связанные с попытками записи за конец строки.
При явных обрашениях к отдельным символам строки функцией аг (), она генерирует исключение аиг ау' гаияе в случае выхода за границу диапазона строковых элементов; операция [) не делает этого. Многие строковые операции на входе принимают позицию символа и число элементов. Если заданная позиция символа превышает длину строки, генерируется исключение аиг а1 »аиде.
Если же заданное число элементов «слишком велико», то оно просто трактуется как «все остальные символы» Например: ча142'( ) ( зтг(иа з = "Яиава14"; зтггпе з2 (з, 100, 2); ~У символ за концом строки: генерируется аи! а) чапае У слишком много си«волив: эквив-но зЗ(з,2,з,згзеО-2) зтг(ия зЗ (з, 2, 100); з(егия з4 [в,2, зтг1ия:: прав); У символы, начиная с з(21 ) Таким образом, «слишком больших» позиций нужно избегать, в то время как «слишком много» символов могут оказаться полезными. Фактически, щюз есть наибольшее возможное для типа з1хе 1уре число. Копируюший конструктор принимает четыре аргумента.
Три из них имеют значения по умолчанию. Для эффективности такой конструктор можно реализовать в виде двух отдельных конструкторов. Пользователь может догадаться об этом, лишь посмотрев на сгенерированный код. Шаблонный конструктор классового шаблона Ьаз1с з)г1пя является наиболее универсальным. Он позволяет инициализировать строку значениями из произвольной последовательности. В частности, он может инициализировать строку элементами различных символьных типов, для которых имеются необходимые преобразования. Например: 699 Глава 20.
Строки Можно попробовать задать отрицательные значения для позиции и числа элементов: гоЫ д (кР!пдь к) ( к!пил к5 (я, -2, 3); кгг!пд кб(з,3, -2); У большая лозияив!: генерируется ои( о( галле //большое число символов/: все оЬ 20.3.б. Присваивание Естественно, что для строк определены присваивания; гетр(осе<с!вяз СЬ, с1акк тг = с«аг «аак<СЬ>, с!акк А = алова(ог<СЬ» с1акк Ьаяс кя«1пд ( риЫ1с: // ... // присвоивание (немного похоже но нес!о« и 1йг: 51«3 4): Ьаяс кзплеь орегаког= (сопя! Ьаяс ккг(леь к); Ьакус кз«!иль оре«аког- — (сопя! СЬ* р); Ьак!с к!плел орегасог= (СЬ с); Ьаяс ккг!леь акяеп (соля! Ьаяс ккг!пеь к); Ьаяс к!ппеь акк(дп (сопя! Ьаяс ккг!пеь к, к!ке (уре рок, яее (уре п); Ьаяс яппдь акяб« (сопя СЬ* р, к!ке куре и); Ьак(с кяг!леь акк(яи (соля! СЬ* р); ьаяс ккг!лдь акк!дл (зае (уре и, сь с); кетр(а!е<с1акк 1п> Ьак!с кгплдь акядп (1пу)гк(, 1« 1ак!); и Но поскольку з!ее гуре, применяемый и для позиции, и для числа элементов, есть тип беззнаковый, то отрицательные числа служат лишь запутанным способом задания больших положительных значений (916.3.4).
Обратите внимание на то, что функции, призванные находить подстроки в строках типа я«тля (920.3.11), в случае неудачи возвращают щюя. То есть они не возбуждают исключений. Однако при последующем использовании проз в качестве исходной позиции символа исключение генерируется. Друзой способ задания подстроки заключается в указании пары итераторов.
Первый итератор задает начальный символ, а разность итераторов указывает число элементов. Как обычно, итераторы не проверяют выход за границу диапазона элементов. В случае применения С-строк проверка диапазона символов лишь только усложняется. Когда функции класса Ьаяс з«1ля принимают С-строку (указатель на сйаг), они полагают указатель не равным нулю. Принимая позицию символа в С-строке, они предполагают, что строка достаточно длинна и позиция символа находится в ее пределах. Будьте осторожны! Здесь требуется прямо-таки параноидальная осторожность (кроме как в случае литералов).
Для всех строк 1елятЬ () <щюк. В редких случаях, таких как вставка одних строк в другие (920.3.9), может образовываться слишком длинная строка, которую невозможно представить, и тогда генерируется исключение !епатЬ еггог. Например; ккг!идя(яппд::прок, 'а'); //генерируется !еле(Ь еггог() 20.3. Стандартный строковый шаблон Ьаз(с Ипп9 699 Как и другие стандартные контейнеры, строки типа «зг!пя имеют семантику значений. То есть когда строка присваивается другой строке, ее содержимое копируется и после присваивания существуют две отдельные строки с одинаковым значением. Например: иоЫа() ( «зе!па «1 = "КпоЫ"; «те(па «2 = "То!" ! //две копии "То!" У«2 есть "Ти!", з! по-прежнему 'То!" з1 = «2; г(11 = и; ) Разрешено присваивание строке одиночного символа, хотя такой инициализации не существует: иоЫТ( ) ( ззе!паз = ' а'; «= а'; з = "а"; //еггот инициализация типом саат /У о!с присвоивоние 20.3.7. Преобразование в С-строку Как показано в 520.3.4, строки типа ззе!щ можно инициализировать С-строками, а также этим строкам можно присваивать С-строки.
И наоборот, можно в С-строку поместить копии символов строки типа ззг!пя: <етр!иге<с(азз СЬ, с!азз Те = свае геа(!«<СЬ>, с!азз А = а1!осатог<СЬ» с!азз Ьаис «змия ( риЫ(с: // ... // преобразование в С-строку: сопя! СЬ* с зь'() сонм; Присваивание одиночных значений типа сйаг строкам типа ззг!пд не столь полезно и чревато ошибками. В то же время, операция «= для одиночных символов бывает полезна (520.3.9), а допустить лишь з+='с' без допуска «=«« 'с' было бы странным.