Освой самостоятельно С++ за 21 день.
Шрифт:
29: if (!fout)
30: {
31: cout << "Unable to open " << argv[1] << " for writing.\n";
32: return(1);
33: }
34:
35: Animal Bear(50,100);
36: fout.write((char*) &Bear,sizeof Bear);
37:
38: fout.close;
39:
40: ifstream fin(argv[1],ios::binary);
41: if (!fin)
42: {
43: cout << "Unable to open " << argv[1] << " for reading.\n";
44: return(1);
45: }
46:
47: Animal BearTwo(1,1);
48:
49: cout << "BearTwo weight: " << BearTwo.GetWeight << endl;
50: cout << "BearTwo days: " << BearTwo.GetDaysAlive << endl;
51:
52: fin.read((char*) &BearTwo, sizeof BearTwo);
53:
54: cout << "BearTwo weight: " << BearTwo.GetWeight << endl;
55: cout << "BearTwo days: " << BearTwo.GetDaysAlive << endl;
56: fin.close;
57: return 0;
58: }
Результат:
BearTwo weight: 1
BearTwo days: 1
BearTwo weight: 50
BearTwo days: 100
Анализ:
В строках 22—26 проверяется, соответствует ли установленное число аргументов ожидаемому. Если пользователь забыл ввести имя файла, то выводится сообщение об ошибке:
Usage TestProgram <имя файла>
После этого программа завершает свою работу. Обратите внимание, что при выводе имени программы используется не константная строка, а значение argv[0] . Данное выражение будет правильно выводить имя программы, даже если оно будет изменено после компиляции.
В строке 28 программа пытается открыть двоичный файл с указанным именем. Однако, вместо того чтобы копировать и хранить имя файла во временном массиве, как это было в листинге 16.18, его можно задать в командной строке и затем возвратить из argv[1 ].
Точно так же имя файла возвращается в строке 40, где этот файл открывается для ввода данных, и в строках 25 и 31 при формировании сообщений об ошибках открытия файлов.
Резюме
Сегодня вы познакомились с потоками и глобальными объектами cout и cin. Основное предназначение объектов istream и ostream состоит в инкапсулировании буферизированого ввода и вывода данных на стандартные устройства ввода-вывода.
В каждой программе создается четыре стандартных потоковых объекта: cout, cin, cerr и clog. Однако в большинстве операционных систем эти объекты можно переадресовывать.
Объект cin класса istream используется для ввода данных обычно вместе с перегружаемым оператором ввода (>>). Объект cout класса ostream используется для вывода данных в комбинации с оператором вывода (<<).
Стандартные объекты ввода-вывода включают много других функций-членов, например get и put. Поскольку эти методы возвращают ссылки на объект потока, несколько вызовов функций можно объединять в одном выражении.
Для настройки работы объектов потока используются манипуляторы. С их помощью можно устанавливать не только опции форматирования и отображения, но и многие другие атрибуты объектов потока.
Обмен данными с файлами осуществляется с помощью классов fstream, производных от класса iostream. Кроме обычных операторов ввода и вывода, эти классы поддерживают использование функций read и write, позволяющих считывать и записывать целые объекты в двоичные файлы.
Вопросы и ответы
Как определить, когда использовать операторы ввода и вывода, а когда другие функции-члены классов потока?
В целом операторы ввода и вывода проще в использовании, поэтому в большинстве случаев лучше обращаться именно к ним. В некоторых других случаях, когда эти операторы не справляются со своей работой (например, при вводе строки из слов, разделенных пробелами), можно прибегнуть к использованию других функций.
Какое отличие между cerr и clog?
Объект cerr не буферизируется? Другими словами, все данные, поступающие в cerr, немедленно выводятся на экран. Это отлично подходит для вывода ошибок на
экран, однако дорого обойдется при записи регистрационной информации на диск. Объект clog буферизирует свой вывод, поэтому в последнем случае может быть более эффективным.
Зачем создавать потоки, если отлично работает функция printf? Функция printf не контролирует строго типы выводимых данных, чего требуют стандарты C++. Кроме того, эта функция не поддреживает работу с классами.
Когда следует применять метод putback?
Этот метод весьма эффективен в тех случаях, когда для определения соответствия введенного символа установленным ограничениям используется одна операция считывания, а для записи символа в буфер используются некоторые другие операций. Наиболее часто это находит применение при анализе синтаксических конструкций файла, например при создании компиляторов.
Когда следует использовать функцию ignore?
Наиболее часто она используется после функции get. Поскольку последняя оставляет в буфере символ разрыва строки, иногда за вызовом функции get следует вызов ignore(1, '\n');. Эта функция, как и putback, используется, как правило, при синтаксическом разборе файлов.
Мои друзья используют в своих программах на C++ функцию printf. Можно ли и мне ее использовать?
Конечно же, можно. Однако, хотя эта функция более проста в использовании, вы утратите строгий контроль за типами файлов и затрудните работу с объектами классов.
Коллоквиум
В этом разделе предлагаются вопросы для самоконтроля и укрепления полученных знаний и приводится несколько упражнений, которые помогут закрепить ваши практические навыки. Попытайтесь самостоятельно ответить на вопросы теста и выполнить задания, а потом сверьте полученные результаты с ответами в приложении Г. Не приступайте к изучению материала следующей главы, если для вас остались неясными хотя бы некоторые из предложенных ниже вопросов.