Литмир - Электронная Библиотека
A
A

 

Программирование. Принципы и практика использования C++ Исправленное издание - _001.png
 Будучи программистами, мы предпочитаем регулярность. Единообразная обработка всех объектов, находящихся в памяти, одинаковый подход ко всем источникам входной информации и стандартное унифицированное представление объектов при входе в систему и выходе из нее позволяют создавать самый ясный, простой, понятный и часто самый эффективный код. Однако наши программы должны служить людям, а люди имеют стойкие предпочтения. Таким образом, как программисты мы должны поддерживать баланс между сложностью программы и настройкой на персональные вкусы пользователей. 

11.2. Форматирование вывода

 

Программирование. Принципы и практика использования C++ Исправленное издание - _003.png
 Люди уделяют много внимания мелким деталям, связанным с представлением выходной информации, которую им необходимо прочитать. Например, для физика число
1.25
(округленное до двух цифр после точки) может сильно отличаться от числа
1.24670477
, а для бухгалтера запись
(1.25)
может сильно отличаться от записи
(1.2467)
и совершенно не совпадать с числом
1.25
(в финансовых документах скобки иногда означают убытки, т.е. отрицательные величины). Как программисты мы стремимся сделать наш вывод как можно более ясным и как можно более близким к ожиданиям потребителей нашей программы. Потоки вывода (
ostream
) предоставляют массу возможностей для форматирования вывода данных, имеющих встроенные типы. Для типов, определенных пользователем, программист сам должен определить подходящие операции
<<
.

Количество деталей, уточнений и возможностей при выводе кажется неограниченным, а при вводе, наоборот, есть лишь несколько вариантов. Например, для обозначения десятичной точки можно использовать разные символы (как правило, точку или запятую), денежные суммы в разных валютах также выводятся по-разному, а истинное логическое значение можно выражать как словом

true
(или
vrai
or
sandt
), так и числом
1
, если в вашем распоряжении находятся только символы, не входящие в набор ASCII (например, символы в системе Unicode). Кроме того, существуют разные способы ограничения символов, записываемых в строку. Эти возможности не интересны, пока они вам не нужны, поэтому мы отсылаем читателей к справочникам и специализированным книгам, таким как Langer Standard C++ IOStreams and Locales; главе 21 и приложению D в книге The C++ Programming Language Страуструпа; а также к §22 и 27 стандарта ISO C++. В настоящей книге мы рассмотрим лишь самые распространенные варианты вывода и некоторые общие понятия. 

11.2.1. Вывод целых чисел

Целые числа можно вывести как восьмеричные (в системе счисления с основанием 8), десятичные (в обычной системе счисления с основанием 10) и шестнадцатеричные (в системе счисления с основанием 16). Если вы ничего не знаете об этих системах, сначала прочитайте раздел A.2.1.1. В большинстве случаев при выводе используется десятичная система. Шестнадцатеричная система широко распространена при выводе информации, связанной с аппаратным обеспечением.

Причина популярности шестнадцатеричной системы кроется в том, что шестнадцатеричные цифры позволяют точно представить четырехбитовые значения. Таким образом, две шестнадцатеричные цифры можно использовать для представления восьмибитового байта, четыре шестнадцатеричные цифры представляют два байта (которые часто являются полусловом), восемь шестнадцатеричных цифр могут представить четыре байта (что часто соответствует размеру слова или регистра).

Когда был разработан язык С — предшественник языка С++ (в 1970-х годах), не менее популярной была восьмеричная система, но сейчас она используется редко. Мы можем указать, что (десятичное число)

1234
при выводе должно трактоваться как десятичное, шестнадцатеричное или восьмеричное.

cout << 1234 << "\t(decimal)\n"

     << hex << 1234 << "\t(hexadecimal)\n"

     << oct << 1234 << "\t(octal)\n";

Символ

'\t'
означает “символ табуляции”. Он обеспечивает следующее представление выходной информации:

1234 (decimal)

4d2 (hexadecimal)

2322 (octal)

Обозначения

<< hex
и
<< oct
не являются значениями, предназначенными для вывода. Выражение
<< hex
сообщает потоку, что любое целое число в дальнейшем должно быть представлено как шестнадцатеричное, а выражение
<< oc
t означает, что любое целое число в дальнейшем должно быть представлено как восьмеричное. Рассмотрим пример.

cout << 1234 << '\t' << hex << 1234 << '\t' << oct << 1234 << '\n';

cout << 1234 << '\n'; // восьмеричная основа продолжает действовать

В итоге получаем следующий вывод:

1234 4d2 2322

2322 // целые числа продолжают трактоваться как восьмеричные

Обратите внимание на то, что последнее число выведено как восьмеричное; иначе говоря, термины

oct
,
hex
и
dec
(для десятичных чисел) являются персистентными (инертными) — они применяются к каждому целому числу, пока мы не дадим потоку другое указание. Термины
hex
и
oct
используются для изменения поведения потока и называются манипуляторами (manipulators). 

ПОПРОБУЙТЕ

Выведите ваш день рождения в десятичном, восьмеричном и шестнадцатеричном форматах. Обозначьте каждое из этих значений. Выровняйте ваш вывод по столбцам, используя символ табуляции, и выведите свой возраст.

Представление чисел в системе счисления, отличной от десятичной, может ввести читателя в заблуждение. Например, если заранее не знать, в какой системе представлено число, то строка 11 может означать десятичное число 11, а не восьмеричное число 9 (т.е. 11 в восьмеричной системе) или шестнадцатеричное число 17 (т.е. 11 в шестнадцатеричной системе). Для того чтобы избежать таких проблем, можно попросить поток показать базу, в которой представлено целое число. Рассмотрим пример.

cout << 1234 << '\t' << hex << 1234 << '\t' << oct << 1234 << '\n';

154
{"b":"847443","o":1}