Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 161
Текст из файла (страница 161)
При необходимости число округляется. Если точность не задана, выводится шесть цифр; если точность задана явным указанием О. н 11 не указано, не выводится ни цифр, ни десятичной точки; е Аргумент типаЯоа1 или с1оиЫе преобразуется в десятичный вид в научном стиле [-1с1.ЙЫе+~Ы или [-1сЫЙ1е-сЫ, где до точки стоит одна цифра, а число цифр после точки равно указанной для данного аргумента точности.
При необходимости число округляется. Если точность не задана, выводится шесть цифр; если точность задана явным указанием О, и 11 не указано, не выводится ни цифр, ни точки; Е Подобно е, но для обозначения показателя степени используется большое Е; о Аргументы типаЯоа1или с1оиЫе выводятся в стиле с1, 1сили ев зависимости оттого, что из них дает максимальную точностгч занимая минимум места; 0 Подобно я, но для обозначения показателя степени используется большое Е; с Выводится символьный аргумент.
Нулевые символы игнорируются; з Аргументдолжен быть строкой(указателем на символ), и символы из строки выводятся, пока не встретится нулевой символ, или пока не выведется число символов, определяемое точностью; однако если точность равна О или отсутствует, выведутся все символы до нулевого; р Аргумент должен быть указателем.
Вид печатаемого представления зависит от реализации; Целочисленный аргумент без знака преобразуется в десятичный вид; п Количество символов, выведенное на данный момент вызовом рстпс1 [), ~ргшЯ или зрг1пЯ и записанное в аргументе типа 1п1, на который указывает указатель на шб Неуказанная или недостаточная ширина поля ни в коем случае не приведет к урезанию вывода; дополнение символами-заполнителями имеет место, только если указанное поле шире действительного. Вот более замысловатьш пример: спас'Ипе 1агта1="Пйпе%с1~"Ум',"~п'; 1пгйпе= И; алас*я!е пате = С++утат.с"; 12! 21.9.
Советы рг!пу" ('(и!айп ), рг!пу )1спс /огта1, 1!пе,1!1с пате); ргсп1/( т1Ь»\и ), В результате будет выведено: !и! а; Ф1тс 1в 'С++/тасп.с !и! Ь; Использование ргсп у [) небезопасно в том смысле, что проверки типа не производится. Папрнмер, ниже представлен хорошо известный способ, как получить непредсказуемый вывод, вывести содержимое какого-то участка памяти или сделать чтонибудь еще хуже: сйагх; //..
рг!пу" ( недопустимый вводимый сшивал: Аьв", х); //должно бы!пь %с, а не %в Однако функция рг1пф'() обеспечивает чрезвычайную гибкость, к тому же она знакома программистам, пишущим на С. Подобным же образом йе!сйаг [) предоставляет знакомый способ чтения вводи мых символов: !и! й той!1с ((1=ас!сйаг())1=ЕОг) ( /* использование!*/ ) Для того чтобы можно было сравнивать ЕОГ как целое, значение, возвращаемое функцией йе!сйаг [), должно быть типа !и1, а не сйаг.
Более подробно с вводом/выводом в стиле С можно ознакомиться в вашем справочном пособии по С или в книге Кернигана и Рнчн «Язык программирования С» [Кегп(йпап, 1988]. 21.9. Советы [1) Определяйте операторы «и» для типов, определяемых пользователем, имеющих значения осмысленного текстового представления; в 21.2.3, 9 21,3.5, [2] Когда вы пишете выражения, содержащие операторы с низким приоритетом, пользуйтесь скобками; () 21.2. [3) Чтобы добавить новые операторы «и», вам не нужно изменять 1в!геат и ов!геат; 9 21.2.3. [4] Вы можете определить функцию так, чтобы она вела себя, как виртуальная, основываясь на втором (или следующем) аргументе; в 21.2.3.1.
[5] Помните, что по умолчани!о оператор» пропускает символы-разделители; в 21.3.2. [6] Пользуйтесь низкоуровневыми функциями ввода, такими как де! [) и геас()), в основном при реализации высокоуровневых функций ввода; в 21.3А. [7] При использовании уе! )), йе!Йпе [) и геаН [) будьте внимательны с определением конца ввода; !! 21.3А.
[8] Для установки флагов управления вводом/выводом предпочитайте манипуляторы; 5 21.3.3, () 21А, 5 21А.6. Глава 21. Потоки 722 [9] Полъзуйтесь исключениями (только) для перехвата редких ошибок ввода/вывода; 6 21.3.6. [10] Связывайте потоки, используемые для интерактивного ввода и вывода; 6 2 1.3.7. [11] Чтобы сконцентрировать начальный и завершающий код для разных функций в одном месте, используйте часовых; 9 213.8.
[12] Пе пользуйтесь скобками после манипулятора без аргументов; 9 21.4.6.2. [13] Прн использовании стандартных манипуляторов не забывайте й/пс(ийегйотап/р>; 6 21Л.6.2. [И] Вы можете достичь эффекта(н эффективности) тернарного оператора, определив простую функцию-обьект; 6 21А.6.3.
[15] Помните, что спецификация ш(сЕЕЬ применяется только к ближайшей операции ввода/вывода; з 21АА. [16] Помните, что спецификации ргесйяЕоа применяются ко всем последующим операциям вывода чисел с плавакпцей точкой; 6 21А.3. [17] Для форматировании в памяти пользуйтесь потоками строк; 6 21.5.3. [18] Вы можете установить способ работы с файловым потоком; 9 21.5.1. [19] При расширении системы ввода/вывода четко различайте форматирование (Еаяггеат) и буферизацию (я(геатЬиЯ; 9 21.1, 9 21.6.
[20] Реализуйте нестандартные способы передачи значений через буфера потоков; 6 21.6А. [21] Реализуйтс нестандартные способы форматирования значений через операции с потоками; [] 21.2.3, 6 21.3.5. [22] Вы можете изолировать и инкапсулировать обращения к пользовательскому коду прн помощи пар функций; 9 21.6А. [23] Вы можете до чтения воспользоваться функцией Еа аиаЕЕ [], чтобы определить, не будет ли операция ввода заблокирована; 9 21.6.4.
[24] Различайте простые операции, которые должны быть эффективными, и операции, реализующие тактику действий: первые делайте встроенными, а вторые виртуальныьли; 9 21.6А. [25] Для отражения различий в культурных традициях пользуйтесь ЕосаЕе; Я 21.7. [26] Если вы смешиваете ввод/вывод в стиле С и в стиле С++, пользуйтесь яупс пл(Ь я(гЕЕо [[; чтобы чразъединитьь ввод/вывод в стиле С и в стиле С++ используйте вызов яупс ш(ЕЬ я(гЕЕо [Еа(яе]; 9 21.8. [27] При вводе/выводе в стиле С опасайтесь ошибок в типе; 9 21.8.
21.10. Упражнения 1. (*1,5) Прочитайте файл, содержащий числа с плавающей точкой, скомбинируйте пары прочитанных чисел в комплексные числа и выведите их. 2. ('1.5) Определите тип Мате алЫ ааег(геяя (имя и адрес). Определите для него операторы «и». Скопируйте поток объектов типа Мате апгЕ аг(г(геяя. 3. (*2.5) Скопируйте поток объектов типа Мате аас( ас(с(геяя, и вставьте в него столько ошибок, сколько сможете придумать (например, ошибки формата и преждевременные концы строк). Обработайте эти ошибки таким образом, чтобы гарантировать, что функция копирования прочитает большинство правильно отфор- 723 матнрованных объектов Мате апя( апЯя(геэз, хотя на вводе будут чередоваться < плохие» значения с «хорошими».
4. ("2.5) Заместите формат ввода/вывода объектов Мате аЫ апЯпЯгеэз, чтобы сделать его менее чувствительным к ошибкам в формате. 5. ("2.5) Напишите несколько функций для запроса и чтения информации разного типа. Например: целые числа, числа с плавающей точкой, имена файлов, почтовые адреса, анкетные данные н т. п. Попытайтесь сделать их защищенными от ошибок. 6. ('1.5) Напишите яярограмь«у, которая выводит: (а) все буквы нижнего регистра, (б) все буквы, (в) все буквы и цифры, (г) все символы, которые могут встретиться в идентификаторе С++ для вашей системы, (д) все знаки препинания, (е) коды всех управляющих символов, (ж) все символы-разделители, (з) коды всех символов-разделителей и наконец (и) все печатаемые символы. 7.
(*2) Прочитайте последовательность текстовых строк (11пез) в символьный буфер фиксированного размера. Удалите все символы-разделители н замените все буквы алфавита следующими за ними в алфавите ( г заменяется па а, а 9 па О). Выведите получившуюся строку. 8. (*3) Напишите «миниатюрную» систему потокового ввода/вывода, предоставляющую классы юз(геат, оэ(геат, яуз1геат, о(эягеат, функции орега(ог«() и орега1ог» () для целых чисел и такие операпип, как ореп () и с1озе (), для файлов. 9.
(*4) Реализуйте стандартную библиотеку ввода/вьявода С (<вяя(яо.Ь>) при помощи стандартной библиотеки ввода/вывода С++ (<юв(геат>). 10. ('4) Реализуйте стандартную библиотеку ввода/вьявода С++ (<юэ(геат>) при помощи стандартной библиотеки ввода/вывода С (<э(я(яо. Ь>). 11. ('4) Реализуйте эти библиотеки на С и С++ так, чтобы имп было можно пользоватьсяодновременно. 12. (*2) Реализуйте класс, для которого оператор [) перегружен, чтобы выполнять чтение символов из указанной позиции файла. 13.
(*3) Повторите З 21.10[12], но сделайте оператор [) применимым как для чтения, так и для записи. Подсказка: сделайте так, чтобы оператор Ц возвращал объект «дескрипторного типа», для которого присваивание означало бы «записать в файл через дескриптор», а неявное преобразование в сЬаг означало бы «прочитать из файла через дескриптор». 14.
(*2) Повторите 2 21.10[14), но пусть оператор [) индексирует объекты произвольного типа, а не только символы. 15. (*3.5) Реализуйте версии яэягеат и озггеат для чтения и записи чисел в двоичном виде без преобразования пх в символы. Рассмотрите достоинства и недостатки этого подхода по сравнению с подходом, основанным на символьном представлении. 16. ('3.5) Спроектируйте и реализуйте операцию ввода по шаблону. Для задания шаблона воспользуйтесь строками формата в стиле ргяп(7' К одному и тому же введенному значению можно потенциально применить несколько шаблонов, перед тем как установить его действительный формат.