Объект cerr в C++
Объект cerr в C++ – это объект класса ostream. Он связан со стандартным потоком вывода ошибок C stderr.
Декларация
extern ostream cerr;
Он определен в заголовочном файле .
Гарантируется, что объект cerr в С++ будет инициализирован во время или до первого создания объекта типа ios_base :: Init. После создания объекта cerr выражение (cerr.flags unitbuf) не равно нулю, что означает, что любой вывод, отправленный этим объектам потока, немедленно сбрасывается в операционную систему. Также cerr.tie() == cout, т.е. cerr.tie() возвращает cout, что означает, что cout.flush() выполняется перед любой операцией вывода на cerr.
«C» в cerr означает «символ», а «err» означает «ошибку», следовательно, cerr означает «символьную ошибку».
Объект cerr используется вместе с оператором вставки (<<) для отображения потока символов. Общий синтаксис:
cerrcerrОператор извлечения может использоваться более одного раза с комбинацией переменных, строк и манипуляторов (например, endl):
cerrНачинающие программисты на используют cout C++ для отображения ошибки, используя стандартный вывод для отладки своих программ, но всегда полезно использовать cerr для отображения ошибок.
Это связано с тем, что вместо того, чтобы отображать поток ошибок на экране, вы можете позже изменить поток ошибок, чтобы записать ошибки в файл.
Пример: как работает cerr?
#include #include using namespace std; int main()Когда вы запустите программу, вывод будет: [если файл не может быть открыт]
Error while opening the file data.txtCerr – обработка ошибок в C++
Эта статья пытается пролить некоторый свет на (часто игнорируемый) объект cerr в C++. ‘C’ в Сerr означает “символ” и “err” означает “ошибка”, значит Cerr означает “Ошибка символа”.
Он определен в заголовочном файле iostream и соответствует потоку C stderr. Он имеет очень похожее использование на объект cout (т. е. печать символов на консоли во время выполнения) под потоком stdout.
Различие
Даже при том, что результат обоих cout и cerr одинаков, есть очень тонкое различие между ними, которое мы можем найти в случае использования вышеупомянутых обоих потоков.
Вот пример кода, чтобы показать разницу между ними:
#include using namespace std; int main()
Оба приведенных выше оператора будут печатать символы, но под разными консолями / контекстом. Взгляните на результат.
Hey there, Geek! :: coutHey there, Geek! :: cerrИтак, что же можно извлечь из их использования?
Как правило, stdout:: cout должен использоваться для фактического вывода программы, в то время как вся информация и сообщения об ошибках должны быть напечатаны в stderr::cerr.
Например: предположим, что пользователь хочет открыть файл и перенаправить вывод на этот внешний файл. Предположим, что во время выполнения программы (из-за какой-то проблемы) открытие файла выдает ошибку. Чтобы сохранить проверку таких ошибок, разработчик должен зарегистрировать ошибку где-то, чтобы проверить ее позже. Он может использовать cerr, так как эта ошибка все еще печатается, не будучи выходом на консоль или выходной файл.
Давайте посмотрим примерную программу для этого:
#include #include using namespace std; int main() < char fileName[] = "data.txt"; // Открытие файла с помощью объекта infile класса ifstream в заголовочном файле fstream ifstream infile(fileName); // Если файл существует, начните чтение с файла if(infile) cout << infile.rdbuf(); /* Если возникает какая-либо проблема, это сообщение отображается как ошибка. Таким образом, пользователь может четко различать между подлинным выводом и ошибками в своем коде. еще */ cerr
Понравилось то, что вы прочитали?
Подписывайтесь на нашу рассылку и получайте ежедневные обновления о новых учебниках, статьях, курсах и о многом другом!
Просто введите ваш адрес электронной почты, чтобы подписаться.
(Без спамов; ежемесячно два письма; отписаться от рассылки можно в любое время)
Спасибо!
Подписка успешно оформлена.
std::cout, std::cerr и std::clog
При запуске приложения (речь идёт о POSIX) вместе с ним открывается 3 файловых дескритоптора:
- 0 - ассоциирован со стандартным вводом (stdin)
- 1 - ассоциирован со стандартным выводом (stdout)
- 2 - ассоциирован со стандартным выводом в поток ошибок (stderr)
В стандартной библиотеки Си используется FILE* -based буфферизируемый доступ к файлам и терминалу. В stdio.h объявлены следующие глобальные символы, которые отражают стандартные потоки ввода вывода:
Соответственно их свободно можно использовать вместе с семейством функций fread() / fprintf() , обеспечивая буфферизированный доступ.
Сами файловые дескрипторы POSIX объявляет через макросы в unistd.h:
- STDIN_FILENO
- STDOUT_FILENO
- STDERR_FILENO
Соответственно их свободно можно использовать со всем семейством функций read() , write() и, даже, select() / epoll() и fcntl() (например, при помощи fcntl(O_NONBLOCK) + select + read можно реализовать аналог [getch()](http://www.codenet.ru/progr/cpp/spr/175.php) из старого доброго Borland C++). Доступ через эти функции не буфферизирован.
Доступ к одному потоку разными механизмами в одной программе лучше не осуществлять: буферизация это уровень библиотеки C и внутреннего устройства FILE. write() или read() ближе к системным вызовам и ничего про это знать не обязаны. Как результат можете получить перемешивание текста даже в однопоточном приложении. Это не отменяет того файла, что сам fwrite() может, в конце концов, вызвать write() .
На этом экскурс закончим и вернёмся в C++.
В C++ для работы с потоками служит библиотека [iostream](http://www.cplusplus.com/reference/istream/iostream/) . Причём доступ к конкретному стриму может быть как буфферизируемым так и не буфферизируемым (зависит от потребностей).
Библиотека декларирует объекты, связанные со стандартными потоками:
- std::cin - стандартный ввод
- std::cout - стандартный вывод
- std::cerr - стандартный вывод ошибок и
- std::clog - для логирования
Про std::cin особо гооврить (пока?) не будем - он один, в своём роде. А вот про оставшиеся три стоит.
Итак, начнём с std::cout и std::cerr . В C++ они, помимо того, что связаны с разными дескрипторами, несколько отличаются поведением:
- std::cout - буферизируемый
- std::cerr - не буферизируемый
Такое отличие явственно следует из семантики использования: ошибку нужно увидеть сразу без ожидания каких-то дополнительных действий со стороны программиста типа std::flush или std::endl (он, кстати, делает и flush, поэтому, для большей производительности строки в нормальном выводе стоит заканчивать ‘
n’, а не std::endl ).
Ок, а что за std::clog ? А это всего-лишь std::cerr + буферизация. И снова, семантика использования проста: диагностика может чуть и подождать, что бы не понижать производительность вывода, но смешиваться с нормальным выводом не есть хорошо, мы, ведь, можем использовать приложения в пайпе и, желательно, разделить диагностику и ошибки от обычного вывода.
Собственно, немного обобщая:
- std::cout - используется для обычного вывода результатов работы программы на экран, эти данные могут быть переданы дальше по пайпу для обработки.
- std::cerr - вывод сообщений об ошибке в обработке, что бы не подмешивались в основной поток и не ломали логику работы других программ в пайпе. При этом сообщение выводим максимально скоро.
- std::clog - используем для разного рода диагностических сообщений, но когда использование std::cerr замедляет вывод из-за более частого дёргания системных вызовов, при этом, не подмешиваемся в основной поток и не мешаем работе других приложений в пайплайне.
Хорошим тоном, так же, является вывод справки по программе в std::cout , если вызвано с параметрами -h|--help - тогда её удобно смотреть в, например, less без дополнительных телодвижений, а вот справку по опциям, в случае неправильной установки какого-то параметра (или пропуска обязательного), лучше выводить (тут особой разницы не вижу) в std::cerr или std::clog .
И, на последок, лекция по поводу тормозов iostream и вообще, а как оно там внутри устроено:
- https://events.yandex.ru/lib/talks/3309/ - просмотр строго рекомендован.
Posted by Alexander Drozdov Mar 15, 2016 Tags: c++ iostream programming
Поточный ввод-вывод в C++
Поточный ввод-вывод в C++ выполняется с помощью функций сторонних библиотек. В С++, как и в С, нет встроенных в язык средств ввода-вывода.
В С для этих целей используется библиотека stdio.h .
В С++ разработана новая библиотека ввода-вывода iostream , использующая концепцию объектно-ориентированного программирования:
Библиотека iostream определяет три стандартных потока:
- cin стандартный входной поток ( stdin в С)
- cout стандартный выходной поток ( stdout в С)
- cerr стандартный поток вывода сообщений об ошибках ( stderr в С)
Для их использования в Microsoft Visual Studio необходимо прописать строку:
using namespace std;
Для выполнения операций ввода-вывода переопределены две операции поразрядного сдвига:
Вывод информации
Здесь значение преобразуется в последовательность символов и выводится в выходной поток:
int n;
char j;
cin >> n >> j;
cout
Ввод информации
cin >> идентификатор;
При этом из входного потока читается последовательность символов до пробела, затем эта последовательность преобразуется к типу идентификатора, и получаемое значение помещается в идентификатор:
int n;
cin >> n;
Возможно многократное назначение потоков:
cin >> переменная1 >> переменная2 >>. >> переменнаяn;
При наборе данных на клавиатуре значения для такого оператора должны быть разделены символами (пробел, \n, \t ).
int n;
char j;
cin >> n >> j;
Особого внимания заслуживает ввод символьных строк. По умолчанию потоковый ввод cin вводит строку до пробела, символа табуляции или перевода строки.
1
2
3
4
5
6
7
8
9
10
#include
using namespace std;
int main()
char s[80];
cin >> s;
cout system( "pause" );
return 0;
>

Результат выполнения
Для ввода текста до символа перевода строки используется манипулятор потока getline() :
1
2
3
4
5
6
7
8
9
10

Результат выполнения
Манипуляторы потока
Функцию - манипулятор потока можно включать в операции помещения в поток и извлечения из потока (>).
В С++ имеется ряд манипуляторов. Рассмотрим основные:
| Манипулятор | Описание |
| endl | Помещение в выходной поток символа конца строки '\n' |
| dec | Установка основания 10-ой системы счисления |
| oct | Установка основания 8-ой системы счисления |
| hex | Установка основания 16-ой системы счисления |
| setbase | Вывод базовой системы счисления |
| width(ширина) | Устанавливает ширину поля вывода |
| fill('символ') | Заполняет пустые знакоместа значением символа |
| precision(точность) | Устанавливает количество значащих цифр в числе (или после запятой) в зависимости от использования fixed |
| fixed | Показывает, что установленная точность относится к количеству знаков после запятой |
| showpos | Показывает знак + для положительных чисел |
| scientific | Выводит число в экспоненциальной форме |
| get() | Ожидает ввода символа |
| getline(указатель, количество) | Ожидает ввода строки символов. Максимальное количество символов ограничено полем количество |
Пример Программа ввода-вывода значения переменной в C++
1
2
3
4
5
6
7
8
9
10
11
Та же программа, написанная на языке Си
1
2
3
4
5
6
7
8
9
10
#include
int main()
int n;
printf( "Введите n:" );
scanf( "%d" , &n);
printf( "Значение n равно: %d\n" , n);
getchar(); getchar();
return 0;
>
Пример Использование форматированного вывода
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

Результат выполнения
Еще один пример использования форматированного вывода: для t∈[0;3] с шагом 0,5 вычислить значение y=cos(t).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Результат выполнения