Главная » Просмотр файлов » Бьерн Страуструп

Бьерн Страуструп (947334), страница 58

Файл №947334 Бьерн Страуструп (Стpаустpуп - Книга о C++) 58 страницаБьерн Страуструп (947334) страница 582013-09-15СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 58)

ostream& flush(ostream&);

а в классе есть операция operator<<, которая использует указатель на

функцию, как указано выше:

class ostream : public virtual ios {

// ...

public:

ostream& operator<<(ostream& ostream& (*)(ostream&));

// ...

};

В приведенной ниже строке буфер выталкивается в поток cout дважды в

подходящее время:

cout << x << flush << y << flush;

Похожие определения существуют и для класса istream:

istream& ws(istream& is ) { return is.eatwhite(); }

class istream : public virtual ios {

// ...

public:

istream& operator>>(istream&, istream& (*) (istream&));

// ...

};

поэтому в строке

cin >> ws >> x;

действительно обобщенные пробелы будут убраны до попытки чтения в x.

Однако, поскольку по умолчанию для операции >> пробелы "съедаются" и

так, данное применение ws() избыточно.

Находят применение и манипуляторы с параметрами. Например,

может появиться желание с помощью

cout << setprecision(4) << angle;

напечатать значение вещественной переменной angle с точностью до

четырех знаков после точки.

Для этого нужно уметь вызывать функцию, которая установит

значение переменной, управляющей в потоке точностью вещественных.

Это достигается, если определить setprecision(4) как объект, который

можно "выводить" с помощью operator<<():

class Omanip_int {

int i;

ostream& (*f) (ostream&,int);

public:

Omanip_int(ostream& (*ff) (ostream&,int), int ii)

: f(ff), i(ii) { }

friend ostream& operator<<(ostream& os, Omanip& m)

{ return m.f(os,m.i); }

};

Конструктор Omanip_int хранит свои аргументы в i и f, а с помощью

operator<< вызывается f() с параметром i. Часто объекты таких классов

называют объект-функция. Чтобы результат строки

cout << setprecision(4) << angle

был таким, как мы хотели, необходимо чтобы обращение setprecision(4)

создавало безымянный объект класса Omanip_int, содержащий значение 4

и указатель на функцию, которая устанавливает в потоке ostream значение

переменной, задающей точность вещественных:

ostream& _set_precision(ostream&,int);

Omanip_int setprecision(int i)

{

return Omanip_int(&_set_precision,i);

}

Учитывая сделанные определения, operator<<() приведет к вызову

precision(i).

Утомительно определять классы наподобие Omanip_int для всех

типов аргументов, поэтому определим шаблон типа:

template<class T> class OMANIP {

T i;

ostream& (*f) (ostream&,T);

public:

OMANIP(ostream (*ff) (ostream&,T), T ii)

: f(ff), i(ii) { }

friend ostream& operator<<(ostream& os, OMANIP& m)

{ return m.f(os,m.i) }

};

С помощью OMANIP пример с установкой точности можно сократить так:

ostream& precision(ostream& os,int)

{

os.precision(i);

return os;

}

OMANIP<int> setprecision(int i)

{

return OMANIP<int>(&precision,i);

}

В файле <iomanip.h> можно найти шаблон типа OMANIP, его двойник для

istream - шаблон типа SMANIP, а SMANIP - двойник для ioss.

Некоторые из стандартных манипуляторов, предлагаемых поточной

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

необходимые ему манипуляторы, не затрагивая определений istream,

ostream, OMANIP или SMANIP.

Идею манипуляторов предложил А. Кениг. Его вдохновили процедуры

разметки (layout ) системы ввода-вывода Алгола68. Такая техника имеет

много интересных приложений помимо ввода-вывода. Суть ее в том, что

создается объект, который можно передавать куда угодно и который

используется как функция. Передача объекта является более гибким

решением, поскольку детали выполнения частично определяются создателем

объекта, а частично тем, кто к нему обращается.

10.4.2.1 Стандартные манипуляторы ввода-вывода

Это следующие манипуляторы:

// Simple manipulators:

ios& oct(ios&); // в восьмеричной записи

ios& dec(ios&); // в десятичной записи

ios& hex(ios&); // в шестнадцатеричной записи

ostream& endl(ostream&); // добавить '\n' и вывести

ostream& ends(ostream&); // добавить '\0' и вывести

ostream& flush(ostream&); // выдать поток

istream& ws(istream&); // удалить обобщенные пробелы

// Манипуляторы имеют параметры:

SMANIP<int> setbase(int b);

SMANIP<int> setfill(int f);

SMANIP<int> setprecision(int p);

SMANIP<int> setw(int w);

SMANIP<long> resetiosflags(long b);

SMANIP<long> setiosflags(long b);

Например,

cout << 1234 << ' '

<< hex << 1234 << ' '

<< oct << 1234 << endl;

напечатает

1234 4d2 2322

и

cout << setw(4) << setfill('#') << '(' << 12 << ")\n";

cout << '(' << 12 << ")\n";

напечатает

(##12)

(12)

Не забудьте включить файл <iomanip.h>, если используете манипуляторы с

параметрами.

10.4.3 Члены ostream

В классе ostream есть лишь несколько функций для управления выводом,

большая часть таких функций находится в классе ios.

class ostream : public virtual ios {

//...

public:

ostream& flush();

ostream& seekp(streampos);

ostream& seekp(streamoff, seek_dir);

streampos tellp();

//...

};

Как мы уже говорили, функция flush() опустошает буфер в выходной поток.

Остальные функции используются для позиционирования в ostream при

записи. Окончание на букву p указывает, что именно позиция используется

при выдаче символов в заданный поток. Конечно эти функции имеют смысл,

только если поток присоединен к чему-либо, что допускает

позиционирование, например файл. Тип streampos представляет позицию символа

в файле, а тип streamoff представляет смещение относительно позиции,

заданной seek_dir. Все они определены в классе ios:

class ios {

//...

enum seek_dir {

beg=0, // от начала файла

cur=1, // от текущей позиции в файле

end=2 // от конца файла

};

//...

};

Позиции в потоке отсчитываются от 0, как если бы файл был массивом из

n символов:

char file[n-1];

и если fout присоединено к file, то

fout.seek(10);

fout<<'#';

поместит # в file[10].

10.4.4 Члены istream

Как и для ostream, большинство функций форматирования и управления

вводом находится не в классе iostream, а в базовом классе ios.

class istream : public virtual ios {

//...

public:

int peek()

istream& putback(char c);

istream& seekg(streampos);

istream& seekg(streamoff, seek_dir);

streampos tellg();

//...

};

Функции позиционирования работают как и их двойники из ostream.

Окончание на букву g показывает, что именно позиция используется при

вводе символов из заданного потока. Буквы p и g нужны, поскольку

мы можем создать производный класс iostreams из классов ostream и

istream, и в нем необходимо следить за позициями ввода и вывода.

С помощью функции peek() программа может узнать следующий символ,

подлежащий вводу, не затрагивая результата последующего чтения. С

помощью функции putback(), как показано в $$10.3.3, можно вернуть

ненужный символ назад в поток, чтобы он был прочитан в другое время.

10.5 Файлы и потоки

Ниже приведена программа копирования одного файла в другой. Имена

файлов берутся из командной строки программы:

#include <fstream.h>

#include <libc.h>

void error(char* s, char* s2 ="")

{

cerr << s << ' ' << s2 << '\n';

exit(1);

}

int main(int argc, char* argv[])

{

if (argc != 3) error("wrong number of arguments");

ifstream from(argv[1]);

if (!from) error("cannot open input file",argv[1]);

ostream to(argv[2]);

if (!to) error("cannot open output file",argv[2]);

char ch;

while (from.get(ch)) to.put(ch);

if (!from.eof() || to.bad())

error("something strange happened");

return 0;

}

Для открытия выходного файла создается объект класса ofstream -

выходной поток файла, использующий в качестве аргумента имя файла.

Аналогично, для открытия входного файла создается объект класса

ifstream - входной файловый поток, также использующий в качестве

аргумента имя файла. В обоих случаях следует проверить состояние

созданного объекта, чтобы убедиться в успешном открытии файла, а

если это не так, операции завершатся не успешно, но корректно.

По умолчанию ifstream всегда открывается на чтение, а ofstream

открывается на запись. В ostream и в istream можно использовать

необязательный второй аргумент, указывающий иные режимы открытия:

class ios {

public:

//...

enum open_mode {

in=1, // открыть на чтение

out=2, // открыть как выходной

ate=4, // открыть и переместиться в конец файла

app=010, // добавить

trunc=020, // сократить файл до нулевой длины

nocreate=040, // неудача, если файл не существует

noreplace=0100 // неудача, если файл существует

};

//...

};

Настоящие значения для open_mode и их смысл вероятно будут зависеть

от реализации. Будьте добры, за деталями обратитесь к руководству по

вашей библиотеке или экспериментируйте. Приведенные комментарии

могут прояснить их назначение. Например, можно открыть файл с условием,

что операция открытия не выполнится, если файл уже не существует:

void f()

{

ofstream mystream(name,ios::out|ios::nocreate);

if (ofstream.bad()) {

//...

}

//...

}

Также можно открыть файл сразу на чтение и запись:

fstream dictionary("concordance", ios::in|ios::out);

Все операции, допустимые для ostream и ostream, можно применять к

fstream. На самом деле, класс fstream является производным от iostream,

который является, в свою очередь, производным от istream и ostream.

Причина, по которой информация по буферизации и форматированию для

ostream и istream находится в виртуальном базовом классе ios, в том,

чтобы заставить действовать всю эту последовательность производных

классов. По этой же причине операции позиционирования в istream и

ostream имеют разные имена - seekp() и seekg(). В iostream есть

отдельные позиции для чтения и записи.

10.5.1 Закрытие потоков

Файл может быть закрыт явно, если вызвать close() для его потока:

mystream.close();

Но это неявно делает деструктор потока, так что явный вызов close()

может понадобиться, если только файл нужно закрыть до достижения

конца области определенности потока.

Здесь возникает вопрос, как реализация может обеспечить

создание предопределенных потоков cout, cin и cerr до их первого

использования и закрытие их только после последнего использования.

Конечно, разные реализации библиотеки потоков из <iostream.h> могут

по-разному решать эту задачу. В конце концов, решение - это

прерогатива реализации, и оно должно быть скрыто от пользователя. Здесь

приводится только один способ, примененный только в одной реализации,

но он достаточно общий, чтобы гарантировать правильный порядок

создания и уничтожения глобальных объектов различных типов.

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

который по сути служит счетчиком, следящим за тем, сколько раз

<iostream.h> был включен в раздельно компилировавшиеся программные

Характеристики

Тип файла
Документ
Размер
4,26 Mb
Тип материала
Учебное заведение
Неизвестно

Список файлов книги

Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6513
Авторов
на СтудИзбе
302
Средний доход
с одного платного файла
Обучение Подробнее