Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 20
Текст из файла (страница 20)
3.4. Вывод Библиотека сои!геат определяет вывод для каждого встроенного типа. Легко можно определить вывод для типа, определяемого пользователем. По умолчанию, значения, выводимые в сои!, преобразуются в последовательность символов. Например, ио!д /!) ( сои!«!О; поместит символ 1, а затем 0 в стандартный поток вывода. То же самое произойдет н в следуюпием примере. Вывод различных типов можно объединить очевидным способом: ооЫ )г (!аы) ( сои! 'значение !равно "; ооЫу~ ( !пг!= гд; сои!«с; // сделаем доступными стандартные // средства работы со строкалш // обеспечили доступ к именам из иЫ // без префикса иЫ:: 84 Глава 3.
Обзор стандартной библиотеки сои! «й сои! « '~п'; Если!равно 1О, то на выходе мы получим: значение!равно !О Символьной константой называется символ, заключенный в одиночные кавычки. Обратите внимание, что символьная константа выводится как символ, а не как чнсловоезначение. Например, функция ооЫ !е)) ( сои! « 'а'; сои! « 'Ь'; сои! « 'с'; выведет або. Довольно быстро вам надоест повторять имя потока вывода прн выводе нескольких связанных элементов.
К счастью, результат операции вывода может в свою очередь быть использован для дальнейшего вывода: ооЫ 62 )!п! й ( сои! « "значение ! равно" «! «'~,п', Это эквивалентно й (). Потоки излагаются более подробно в главе 21. 3.5. Строки В стандартной библиотеке имеется тип з!г!пн, который дополняет строковые литералы, использовавшиеся ранее. Тип з!ппхгобеспечивает множество полезных операций над строками, таких, например, как конкатенация (объединение): згг!пуз! = Здравствуй'; згг!пдз2 = 'мир"; войт! )) ) згг!пу зЗ = з1 е ', ' е з2;- "Г~п; сои! «зд; В этом примере зЗ инициализируется последовательностью символов Здравствуй, мир! за которой следует символ перевода строки. Слохсение строк означает конкатенацию.
Вы можете складывать строку со строкой, строковым литералом н символом. Во многих приложениях наиболее часто встречающаяся форма конкатенации— добавление чего-либо в конец строки. Это непосредственно поддерживается операцией +=. Например; 85 3.5. Строки ооЫ т2 (згггпуй з1, з1ппайз2) ( з1 = з1 е '~п'; // добавить ссшвол перевода строки з2 += '~р', // добавипсв свивал перевода строки з1ппя (псап1адоп; воЫ гезроп 0 (со и з1 з1п пдй а азтег) ( (/ (апзтег == 1псап!айоп) ( //сотворим чудеса (1пспп1пдоп — зпклиноние) е!зе ~~' (апзсвег == 'да") ( Класс з1ппд из стандартной библиотеки описывается в главе 20. Помимо других полезных вещей, он предоставляет операции с подстроками (фрагментами строк). Например: згггпа пате = Ме(з $1гоиз1гир'; ооЫтд () ( згггпдз = пате.
сибз1г (б, 10); пате.гер1асе (О, Б, Ъ(с1со!аз'); ) // з = "51юиз1гир" // паве = 'МгсИо1аз 51юиз1гир' Операция зибз1г() возвращает строку, которая является копией части исходной строки. Первый аргумент является индексом в строке (указателем позиции), а второй указывает размер фрагмента строки, который требуется получить. Так как индексация начинается с О, з получает значение Игоиз1гир. Операция гер1асе () замещает фрагмент строки другим значением. В нашем случае, подстрока, начинающаяся с 0-й позиция, длины 5 (Ме1з), заменяется на Мсйо1аз. Значит пате примет значение Мсйосаз Игоиз1гир. Обратите внимание, что замешаюшая строка не обязана иметь размер, равный размеру замещаемой подстроки. 3.5.1. С-строки С-строки — зто массивы символов, ограниченные нулем (з 5.2.2).
Мы можем легко преобразовать С-строку в з1г(пр. Для вызова функции, аргументом которой является С-строка, нам нужно уметь представлять значение з(ппд в виде С-строки. Это выполняет функция с з(г() (Ч' 20.3.7), Например, мы можем вывести пате, воспользовавшись функцией вывода языка С рг(пЯ (8 21.8), следующим образом: Оба способа добавления к концу строки семантически эквивалентны, но я предпочитаю второй, потому что он более точно отражает смысл операции и, скорее всего, реализован более эффективно.
Естественно, строки могут сравниваться друг с другом и со строковыми литералами. Например: Глава 8. Обзор стандартной библиотеки 86 иоЫД ( ргьпф'пате:%ячп', пате,с ятгя; З.б. Ввод иоМД ( ьпс й //считать целоев Ь с!п»й йоиЫе й; с!и» й; //считоть число с плавающей точкой двойпой точности в д считывает число (скажем, 1234) из стандартного ввода и помещает сго в целую перс менную с а число с плавающей точкой (например, 12.34е5) помещается в переменную с плавающей точкой двойной точности К. Приведем пример преобразования дюймов в сантиметры и сантиметров в д1оймы. Вы вводите число, за которым следует символ, означающий единицу измерения— сантиметры или дюймы.
Программа выведет соответствуюгцее значение в других единицах: ьпгтасп (1 ( сопяГЯоа!/ассог = 2.54; Яоас х, пв ст; айаг ей = О; //1 дюйч равен 2.54 ся // Гп — это дюйлик Ппсйея) соиг« 'введите длину; О считать число с плавающей точкой // считать су4чрикс сгп»х; сгп» сй; этной ~сЛ~ ( саяе чй т=х; ст = х"/асьог; Ьгеай; саяе 'с' // си т = хДасгог; ст =х; Ьгеай; де/аий 0 дюйиы Стандартная библиотека предлагает потоки ввода ((я1геат). Как и потоки вывода, потоки ввода работают с символьным представлением встроенных типов и их можно легко расширить для работы с типами, определяемыми пользователем. В качестве оператора ввода, используется» (чпрочесть изь). Стандартным потоком ввода является сгп. Тип операнда в правой части оператора» определяет способ интерпретации вводимых символов и то, куда будут записываться значения из входного потока.
Например, функция 3.6. Ввод ~и=от-0; Ьгеал; соле«гл «'дюймов="«ст «" см'~п"; зий(сй-инструкция сравнивает значение с набором констант. Ьгеай-инструкции используются для выхода из инструкции зиеусл. Все константы в инструкции саве должны отличаться друг от друга. Если сравниваемое значение не равно ни одной из констант, выбирается г(е~аи(с Часто нам нужно прочитать последовательность символов. Удобным способом решения этой задачи является чтение в в1г(пд. Например: те та(л () ( егыпу зге,. сонг « 'Пожалуйста, введите ваше имя'~п'; с(л» етг; свис «'Здравствуй, зсг « "Г~п'; Если вы введете Эрик вывод будет Здравсепвуй, Эрик) По умолчанию, символ-разделитель (например, пробел) Я 5.2.2) означает конец вво- да, поэтому, если вы введете Эрик Кровавый Топор притворяясь несчастным королем Йорка, ответом все равно будет Здравствуй, Эрик! Считать всю строку можно с помощью функции деШпе ().
Например: еле таил () ( есг(лу егг; соле « 'Пожалуйста, введите ваше имя~,п; уеудпе (с!л, еег); соле « "Здравствуй, ' «еег «Ч~п; ) Теперь при вводе ЭрикКровавыи" Топор на выходе мы получим ожидаемое; Здравствуй, Эрик Кровавый Топор) 88 Глава 3. Обзор стандартной библиотеки Стандартные строки имеют замечательное свойство расширяться для хранения всей информации, которую вы хотите в них поместить, позтому если вы введете пару мегабайт двоеточий, программа выведет вам в ответ всю эту кучу двоеточий — если только вап компьютер или операционная система не исчерпают раныпе какой-либо критичный ресурс. 3.7. Контейнеры Многие вычисления подразумевают создание наборов объектов в различных формах и обработку таких наборов.
Простыми примерами являются чтение символов в строку и вывод строки. Класс, главной целью которого является хрансние объектов, называется контейнерозь Реализация контейнеров, подходяп!их для данной зада !и, и поддержка их основными полезнымн операциями — важнейшие шаги при написании любой программы. Для иллюстрации наиболее полезных контейнеров стандартной библиотеки рассмотрим простую программу, хранящую имена и номерателефонов. Здесь для людей с разным опьшом «простыми и очевиднымнь окажутся совершенно различные подходы к реализации таких программ. 3.7.1. Вектор Для многих программистов на С подходящей точкой отсчета будет стандартный мас- сив пар (имя, номер): // запись телефоннои книги з1гис1 Ел1гу ( згг!лд лате; 1л1 питЬег; Еппу рьопе Ьоо)ь(1000ь.
// телефонная кннга из ! 000 записеп оо!Орг!и! еп1гу (!п! й //использовпние (пенал!аемзапнсь) ( сои! «руопе Ьооу(!)лате « ' ' «рьопе Ьоой(!).питЬег ''чл'; Ло вс.гроенныс массивы имеют фиксированный размер, Если мы выберем слишком большой размер, то впустую израсходуем память. Если же выбранный размер слишком мал, массив может переполниться. В любом случае нам придется написать код низкого уровня для управления памятью. Стандартная библиотека предоставляет вектора (оес1ог) (б 16.3), которые сами позаботятся об зтом: иес!ог Епггу> рйопе Ьооу(1000); оо!г!рып1 еп1гу йп1 й // используем как раньше ( сои1 «рьопе Ьоод(!) пате « ' ' «рйопе Ьоо!г(!( питЬег« "чп', ооЫаЫ еп!Пев (ьл1 п) //увеличивает размер книги на и записеп ( р)голе Ьоо!глез!ее (рйоле Ьоо!г з!ге () + п)! 89 3.7.
Контейнеры Функция в!хе ((, член класса пес1ог, возвращает количество элементов. Обратите внимание на использование скобок при определении рйоле Ьоой. Мы создали единственный объект типа пес1огкЕп1гу> и в качестве инициализатора передали его начальный размер (в круглых скобках), Это существенно отличается от объявления встроенного массива; оесгогкЕпсгу> ЬооЬ (!000) //вектор иэ 1000 элементов оессогкЕп1гу> ЬооЬв(!0001 // !000 пустгек векторов Если при об ьявлении переменной типа оес1ог вы сделаете ошибку, записав П вместо (), компилятор почти наверняка «выловит» ее и выдаст сообщение об ошибке при попытке использования переменной Ьоойз. Вектор является единым объектом, который можно присвоить.
Например: ооЫЯоесгог<Епггу>& о( ( оес1ог Еп1гу> о2 = рдопе ЬооЬ; о =о2; О. ' Присваивание переменной типа вес1ог означает копирование элементов из присваиваемой переменной. Поэтому после инициализации и присваивания в Д, и и п2 содержат отдельные копии всех записей в телефонной книге. Когда вектор содержит много элементов, такие невинные на первый взгляд присваивания и инициализации могут оказаться недопустимо ресурсоемкими/Там, где нет необходимости копировать, следует пользоваться ссылками или указателями.