Форматирование Библиотека потоков С++ предусматривает три способа управления форматов выходных данных: вызов форматирующих функций-элементов использование флагов использование манипуляторов 1. Форматирующие функции-элементы Для чтения и установки ширины поля потока в классе ios имеется функция width Функция Описание int ios::width( ); Возвращает текущее значение внутренней переменной ширины поля потока int ios::width(int); Устанавливает значение внутренней переменной ширины поля потока Применяемый при вводе, метод (функция член класса) width может быть использован для задания максимального числа читаемых символов Применяемый при выводе, задает минимальную ширину поля Если ширина меньше заданной, выход заполняется дополнительными символами fill Если больше, значение width игнорируется. По умолчанию width = 0 (выход не дополняется и не обрезается) width обнуляется после каждого помещения данных в поток Пример ограничения числа вводимых символов при вводе: #include <iostream.h> const int MAX_LEN = 10; int main(void) { char name[MAX_LEN]; cout << "Введите имя:"; cin.width(MAX_LEN); cin >> name; return 0; } Пример использования для выравнивания правого поля при выводе: #include <iostream.h> const int FLD_LEN = 10; int main(void) { int x1=2867, y1=20051; cout.width(FLD_LEN); cout << x1 << '\n'; cout.width(FLD_LEN); cout << y1 << '\n'; return 0; } Для чтения или изменения заполняющего символа можно применять функции ios:fill Функция Описание char ios:: fill( ); Возвращает текущий символ заполнения char ios::fill(char); Устанавливает символ и возвращает его предыдущее значение По умолчанию - символ заполнения пробел Функции ios:precision могут применяться при выводе чисел с плавающей точкой Функция Описание int ios::precision( ); Возвращает текущее значение int ios::precision(int); Устанавливает символ и возвращает его предыдущее значение По умолчанию точность равна 6 цифрам. Если установлен флаг scientific или fixed задается число цифр, выводимых после запятой Если эти флаги не заданы - задается общее число цифр #include <iostream.h> int main(void) { float f = 3456.141592; double d = 50.2345639101; cout. precision(4); cout << d << '\n'; // 50.23 cout << f << '\n'; // 3456 cout.precision(3); cout << f << '\n'; // 3.46e+3 cout.precision(3); cout.setf(ios::fixed, ios::floatfield); // Тип Fixed cout << f << '\n'; // 3456.142 Тип Fixed return 0; } 2. Флаги В потоках С++ имеются флаги формата. Они задают, каким образом форматируется ввод и вывод. Флаги являются битовыми полями, хранящимися в переменной long Функция Описание long ios::flags(); Возвращает текущее значение long ios::flags(long); Присваивает флагам значение и возвращает предыдущее значение long ios::setf(long,long); Присваивает флагам, биты которых установлены во втором параметре, значения соответствующих бит первого параметра. Возвращает предыдущее значение long ios::setf(long); Устанавливает флаги, биты которых установлены в параметре. Возвращает предыдущее значение long ios::unsetf(long); Сбрасывает флаги, биты которых установлены в параметре. Возвращает предыдущее значение Следующая таблица описывает флаги форматирования Функция ios::skipws По умолчанию x Если установлен, при вводе игнорируются предшествующие пробелы или эквивалентные им символы Данные при выводе выравниваются по левой границе поля ios::left ios::right Описание x по правой ios::internal Знак числа слева, число выравнивается по правому. Промежуток заполняется символами fill ios::dec ios::oct ios::hex Числа выводятся по основанию 10 (десятичные) , 8 (восьмеричные), 16 (шестнадцатиричные) ios::showbase Добавляется индикатор основания 0x 16 (шестнадцатеричные) 0 - 8 (восьмеричные) ios::showpoint При выводе чисел типа float, double или long double показывается десятичная точка ios::uppercase Буквы A-F в шестнадцатеричных выводятся в верхнем регистре, E как показатель тоже ios::showpos Выводится знак + для положительных ios::sientific Вещественные числа показателем E или e ios::fixed Вещественные числа выводятся с десятичной точкой ios::unitbuf Буфер освобождается после каждой операции помещения ios::stdio Потоки stdio , sterr освобождаются после каждой операции помещения выводятся с 3. Манипуляторы Манипуляторы - это функции, которые можно включать в цепочку последовательных операций помещения и извлечения. За исключением setw, изменения, внесенные манипуляторами, сохраняются до следующей установки Манипуляторы, не требующие аргументов, называются простыми Предопределенные простые манипуляторы показаны в следующей таблице Манипулятор Описание endl Помещает в выходной поток символ новой строки (\n) и вызывает манипулятор flush ends Помещает в выходной поток нулевой символ (\0) flush Принудительно записывает все выходные данные на соответствующие физические устройства dec Устанавливает основание 10 (см. ios::dec) hex Устанавливает основание 16 (см. ios::hex) oct Устанавливает основание 8 (см. ios::oct) ws Заставляет игнорировать при вводе ведущие пробельные символы(см. ios::skipws) #include <iostream.h> #include <iomanip.h> int main(void) { int i; cout << "Введите число:"; cin >> i; if (!cin) // Проверить корректность введенного { cout << "Ошибочный ввод" << endl; } else { cout << "Hex:" << hex << i <<endl; cout << "Oct:" << oct << i <<endl; cout << "Dec:" << dec << i << endl; } return 0; }; Параметризованные манипуляторы требуют спецификации аргументов Манипулятор Описание setbase(int _b); Задает преобразования в соответствии с параметром: 0 - Основание по умолчанию 8 - 8-ричное 10 - ... 16 - ... resetiosflags(long _b); Сбрасывает флаги, биты которых установлены в параметре setiosflags(long _b) ; Устанавливает флаги, биты которых установлены в параметре setfill(int _b); Задает заполняющий символ Манипулятор Описание setprecision(int _n); Задает значение внутренней переменной точности вещественных чисел setw(int _w) ; Задает значение внутренней переменной ширины поля Для входного потока максимальное число символов, которые должны быть прочитаны Для выходного - минимальную ширину поля Если ширина меньше заданной, выход заполняется дополнительными символами fill Если больше, значение width игнорируется. Ширина поля устанавливается на 0 после каждой операции помещения #include <iostream.h> #include <iomanip.h> int main(void) { double dbls = { 1.245, -12.99133, 134.007804, -2.345, 0.000003 }; cout << setfill('.') << setprecision(4) << setiosflags(ios::showpoint | ios::fixed | ios::right); for (int i=0; i<sizeof(dbls)/sizeof(dbls[0]); i++) cout << "результат" << setw(20) << dbls[i] << endl; return 0; } Ошибки потоков Все объекты потоки происходят от класса ios и наследуют элемент данных state. Этот элемент представляет состояние потока в виде битового множества Все возможные состояния задаются классом ios, который определяется в iostream.h: class _EXPCLASS ios { public: enum io_state { goodbit = 0x00, // нет установленных битов, все OK eofbit = 0x01, // достигнут конец файла failbit = 0x02, // последний оператор i/o ошибочный // использование потока может продолжаться, // после того как бит будет сброшен badbit = 0x04, // попытка неправильной операции // Серьезная ошибка, потоком, скорее // всего, нельзя будет пользоваться hardfail = 0x08 // невосстановимая ошибка, обычно связанная // с неисправностью оборудования }; // // }; Состояния потока Существуют различные функции и операции, позволяющие читать состояние потока, а также функции для установки или очистки состояния потока Методы опроса состояния потока Метод Описание int rdstate(); Возвращает текущее значение int eof(); Возвращает ненулевое значение, если установлен флаг ios:eofbit int fail(); Возвращает ненулевое значение, если установлен флаг ios:failbit, ios:badbit, ios:hardfail int bad(); Возвращает ненулевое значение, если установлен флаг ios: badbit, ios:hardfail int good() Возвращает ненулевое значение, если сброшены все биты ошибок Метод Описание void clear(int=0); Если параметр =0 (по умолчанию), все биты очищаются. В противном случае параметр принимается в качестве состояния ошибки operator void*( ) Возвращает нулевой указатель, если установлен один из ios:failbit, ios:badbit, ios:hardfail (так же как fail() ) int operator!( ); Возвращает нулевое значение, если установлен один из ios:failbit, ios:badbit, ios:hardfail (так же как fail() ) Операция void*( ) всякий раз вызывается, когда поток сравнивается с нулем while (strm0bj) { // С потоком все в порядке } В следующей таблице приведены распространенные операции, которые можно производить с флагами потока. Действие Пример Проверить установлен ли flag if (strm.rdstate()&ios::flag) Сбросить flag strm.clear(rdstate() & ~ios::flag) Установить flag strm.clear(rdstate() | ios::flag) Установить flag strm.clear(ios::flag) //сбрасывает другие флаги Сбросить все флаги strm.clear()