13.1  Ввод-вывод встроенных типов

Для организации ввода-вывода в программе на языке C++ использует­ся подключаемый файл iostream.h, который содержит определение не­скольких классов и объектов, обеспечивающих методы ввода-выво­да. В частности, язык C++ поддерживает четыре предопределенных объекта, выполняющих ввод-вывод:

1) cout – стандартный вывод, соответствующий stdout в языке С (обычно дисплей);

2) cin – стандартный ввод, соответствующий stdin в языке С (обыч­но клавиатура);

3) cerr – стандартный вывод ошибок, соответствующий stderr в языке С;

4) clog – буферизованная версия cerr (нет эквивалента в языке С).

Эти стандартные потоки можно переназначать на другие уст­ройства или в файлы.

Объект cout является объектом класса ostream. Этот класс используется для управления форматированным и неформатированным выводом. Здесь определяется операция << для обработки вывода встроен­ных типов. Например:

class ostream

{

public:

inline  ostream& operator<<(ostream& (__cdecl * _f)(ostream&));

inline  ostream& operator<<(ios& (__cdecl * _f)(ios&));

ostream& operator<<(const char *);

inline  ostream& operator<<(const unsigned char *);

inline  ostream& operator<<(const signed char *);

inline  ostream& operator<<(char);

ostream& operator<<(unsigned char);

inline  ostream& operator<<(signed char);

ostream& operator<<(short);

ostream& operator<<(unsigned short);

ostream& operator<<(int);

ostream& operator<<(unsigned int);

ostream& operator<<(long);

ostream& operator<<(unsigned long);

inline  ostream& operator<<(float);

ostream& operator<<(double);

ostream& operator<<(long double);

ostream& operator<<(const void *);

ostream& operator<<(streambuf*);

……

};

Таким образом, оператор cout << x посылает значение перемен­ной х в объект cout класса ostream для вывода. Функция operator << возвращает ссылку на объект ostream, для которого она была вы­звана. Поэтому к результату операции вывода можно еще раз при­менить операцию вывода, т.е. несколько операций вывода можно сцепить. Например:

int х=5;

cout << "х = " << х << "n";

В зависимости от типа переданного аргумента будет вызываться тот или иной экземпляр функции operator <<.

Для вывода двоичных данных полезными могут оказаться фун­кции put и write, объявленные в классе ostream. Например:

inline  ostream& put(char);

ostream& put(unsigned char);

inline  ostream& put(signed char);

ostream& write(const char *,int);

inline  ostream& write(const unsigned char *,int);

inline  ostream& write(const signed char *,int);

Функция put() записывает единственный символ в поток ostream, тогда как функция write() передает заданное число байтов.

Поскольку функции put() и write() возвращают ссылку на объект выводного класса, то они также могут быть сцеплены.

Аналогично выводу в языке  C++ определяется и ввод. С вводом свя­зан класс istream, в котором определена перегруженная операция >> для стандартных типов:

class istream {

 public:

inline istream& operator>>(istream& (__cdecl * _f)(istream&));

inline istream& operator>>(ios& (__cdecl * _f)(ios&));

istream& operator>>(char *);

inline istream& operator>>(unsigned char *);

inline istream& operator>>(signed char *);

istream& operator>>(char &);

inline istream& operator>>(unsigned char &);

inline istream& operator>>(signed char &);

istream& operator>>(short &);

istream& operator>>(unsigned short &);

istream& operator>>(int &);

istream& operator>>(unsigned int &);

istream& operator>>(long &);

istream& operator>>(unsigned long &);

istream& operator>>(float &);

istream& operator>>(double &);

istream& operator>>(long double &);

istream& operator>>(streambuf*);

};

Объект cin класса istream используется для ввода с назначенно­го устройства. Например:

int х;

cin >> х;

В зависимости от того, как объявлена переменная х, в область памяти, именуемую х, вводится целое, плавающее число, символ или строка символов.

Функция operator >> возвращает ссылку на определенный объ­ект класса istream, значит, операции ввода можно связывать в це­почку. Например:

cin >> х >> d >> с;

Вводимые значения должны соответствовать объявленному ти­пу и должны разделяться пробелом. В качестве альтернативы мож­но использовать набор перегружаемых функций get() и read():

class istream

{

int get();

inline istream& get(         char *,int,char =’n’);

inline istream& get(unsigned char *,int,char =’n’);

inline istream& get(  signed char *,int,char =’n’);

istream& get(char &);

inline istream& get(unsigned char &);

inline istream& get(  signed char &);

istream& get(streambuf&,char =’n’);

inline istream& getline(         char *,int,char =’n’);

inline istream& getline(unsigned char *,int,char =’n’);

inline istream& getline(  signed char *,int,char =’n’);

istream& read(char *,int);

inline istream& read(unsigned char *,int);

inline istream& read(signed char *,int);

istream& putback(char);

int peek();

inline istream& ignore(int =1,int =EOF);

};

Используя эти функции, можно ввести любые символы, в том числе и пробельные. Например, функция get (char &) просто читает один сим­вол и помещает его в свой аргумент. Другая функция get() из набора перегружаемых функций может выполнить более сложную работу. Она читает и размещает по адресу, заданному первым аргументом, не более символов, чем задано вторым аргументом.

По умолчанию функция get() прочтет не более чем n символов и не более чем одну строку. Последнее ограничение определяется третьим аргументом – он задает символ-ограничитель, по прочтении которого функция прекращает работу. По умолчанию таким символом-ограничителем является ‘n’. Но пользователь может его переустановить, задав при вызове функции три аргумен­та. Этот символ-ограничитель остается во входном потоке и бу­дет первым символом для чтения при выполнении следующей операции чтения, если его оттуда не удалить каким-либо способом. Например:

char buffer[512];

cin.get(buffer, 512, ‘v‘);

Функция get() будет читать в buffer не более 512 символов, но если среди символов встретится символ вертикальной табуля­ции (v), то функция прекратит работу. В этом случае первым символом, который будет прочитан из cin следующей операцией чтения, будет символ ‘v’. Заметим, что функции get возвращают ссылку на объект класса istream, для которого они были вызваны. Значит, они могут быть сцеплены в цепочку. Например:

char str[10];

char ch, ph;

cin.get(ch).get(str).get(ph);

В переменные ch, str и ph из потока cin будут введены значения.

При организации ввода-вывода полезными могут оказаться еще несколько функций:

· функция putback(char с)  возвращает символ обратно в поток iostream;

· функция peek () возвращает следующий символ (или EOF), но не удаляет его из потока;

· функция ignore (int Limit = 1, int Delim = EOF)  пропускает указанное количество символов и останавливается, если встречает символ Delim. По умолчанию, если никакие аргументы не заданы, функция ignore() пропускает один символ и останавливается, если встречает конец файла.