Смекни!
smekni.com

Препроцессорные средства в C и С++ (стр. 5 из 7)

istream _FAR & _RTLENTRY ignore(int = 1, int = EOF);

Форматный ввод релизуется на основе переопределения операций ввода

istream _FAR & _RTLENTRY operator>> (bool _FAR &);istream _FAR & _RTLENTRY operator>> (istream _FAR & (_RTLENTRY *_f)(istream _FAR &));istream _FAR & _RTLENTRY operator>> (ios _FAR & (_RTLENTRY *_f)(ios _FAR &) );istream _FAR & _RTLENTRY operator>> ( char _FAR *);istream _FAR & _RTLENTRY operator>> ( signed char _FAR *);istream _FAR & _RTLENTRY operator>> (unsigned char _FAR *);istream _FAR & _RTLENTRY operator>> ( char _FAR &);istream _FAR & _RTLENTRY operator>> ( signed char _FAR &);istream _FAR & _RTLENTRY operator>> (unsigned char _FAR &);istream _FAR & _RTLENTRY operator>> (short _FAR &);istream _FAR & _RTLENTRY operator>> (int _FAR &);istream _FAR & _RTLENTRY operator>> (long _FAR &);istream _FAR & _RTLENTRY operator>> (unsigned short _FAR &);istream _FAR & _RTLENTRY operator>> (unsigned int _FAR &);istream _FAR & _RTLENTRY operator>> (unsigned long _FAR &);istream _FAR & _RTLENTRY operator>> (float _FAR &);istream _FAR & _RTLENTRY operator>> (double _FAR &);istream _FAR & _RTLENTRY operator>> (long double _FAR &);

Извлечение из istream и вставка в объект типа streambuf выполняет оператор-функция

istream _FAR & _RTLENTRY operator>> (streambuf _FAR *);

Макрос FAR управляет способом представления указателей, макрос RTLENTRY определяет применение стандартной билиотеки времени выполнения.

Аналогичные операции для вывода определены в классе ostream:

// вставить символ в потокostream _FAR & _RTLENTRY put( char); ostream _FAR & _RTLENTRY put(signed char);ostream _FAR & _RTLENTRY put(unsigned char);// вставить в поток строкуostream _FAR & _RTLENTRY write(const char _FAR *, int l);ostream _FAR & _RTLENTRY write(const signed char _FAR *, int l); ostream _FAR & _RTLENTRY write(const unsigned char _FAR *, int l);

Операции форматированного вывола

Вывод "true" или "false" для данных типа bool

ostream _FAR & _RTLENTRY ostream::operator<< (bool);

Вывод ланных типа char

ostream _FAR & _RTLENTRY operator<< ( char);ostream _FAR & _RTLENTRY operator<< ( signed char);ostream _FAR & _RTLENTRY operator<< (unsigned char);

Вывод числовых данных с преобразованием во внешнее представление

ostream _FAR & _RTLENTRY operator<< (short);ostream _FAR & _RTLENTRY operator<< (unsigned short);ostream _FAR & _RTLENTRY operator<< (int);ostream _FAR & _RTLENTRY operator<< (unsigned int);ostream _FAR & _RTLENTRY operator<< (long);ostream _FAR & _RTLENTRY operator<< (unsigned long);ostream _FAR & _RTLENTRY operator<< (float);ostream _FAR & _RTLENTRY operator<< (double);ostream _FAR & _RTLENTRY operator<< (long double);

Вывод строк, оканчивающихся нулевым байтом

ostream _FAR & _RTLENTRY operator<< (const char _FAR *);ostream _FAR & _RTLENTRY operator<< (const signed char _FAR*);ostream _FAR & _RTLENTRY operator<< (const unsigned char _FAR*);

Вывод значения указателя в символьном формате

ostream _FAR & _RTLENTRY operator<< (void _FAR *);

Извлечение данных их объекта streambuf и вставка в тот же ostream

ostream _FAR & _RTLENTRY operator<< (streambuf _FAR *);

Выводзначенийманипуляторов

ostream _FAR & _RTLENTRY operator<< (ostream _FAR & (_RTLENTRY *_f)(ostream _FAR &));ostream _FAR & _RTLENTRY operator<< (ios _FAR & (_RTLENTRY *_f)(ios _FAR &));

Имеется также класс iostream, производный от класса ios и объединяющий возможности классов istream и ostream.

Для рассмотренных выше классов отсутствуют конструкторы копирования и операция присваивания, точнее, они объявлены, но не определены. Для тех случаев, когда конструктор копирования и операция присваивания необходимы, предусмотрены классы istream_withassign, ostream_withassign и iostream_withassign. Как экземпляры объектов этих классов всегда объявляется объект cin (экземпляр istream_withassign), обычно предназначенный для ввода с клавиатуры, и объекты cout, cerr и clog (экземпляры ostream_withassign), обычно предназначенные для вывода на экран.

Ввод-вывод для дисковых файлов обепечивается классами, описания которых содержатся в файле fstream.h.

Класс filebuf, производный от streambuf, предназначен для добавления в streambuf дополнительных средств управления буфером ввода-вывода.

Класс fstreambase, производный от класса ios, служит базой для остальных классов, обеспечивающих файловый ввод-вывод, в нем определены методы:

void _RTLENTRY open(const char _FAR *, int, int = filebuf::openprot);void _RTLENTRY attach(int);void _RTLENTRY close();void _RTLENTRY setbuf(char _FAR *, int);

Назначение этих методов очевидным образом следует из их названий.

Для непосредственной работы с файлами служат классы ifstream, ofstream и fstream, базой для них служат классы fstreambase и, соответственно, istream, ostream и iostream.

6.2. Вывод в файл. Ввод из файла

Для вывода данных в дисковый файл в программе должна присутствовать директива препроцессора

#include <fstream.h>
подключающая описания необходимых классов.

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

_RTLENTRY ofstream(); // Пустой объект, без привязки к файлу // С привязкой к файлу, полное имя которого задается первым аргументом:_RTLENTRY ofstream(const char _FAR *, int = ios::out, int = filebuf::openprot);// С привязкой к ранее открытому файлу, заданному своим дескриптором_RTLENTRY ofstream(int);// То же, что и предыдущий вариант, но задается новый буфер вывода_RTLENTRY ofstream(int __f, char _FAR *, int);

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

Собственно операции вывода реализуются вызовом методов put, write или с использованием переопределенных операций <<.

Аналогичным способом обеспечивается и ввод из файла: создается объект типа ifstream и для ввода применяются методы get, read или переопределенные операции >>.

Для типа ifstream имеется набор аналогичных конструкторов:

_RTLENTRY ifstream();_RTLENTRY ifstream(const char _FAR *,int = ios::in, int = filebuf::openprot);_RTLENTRY ifstream(int);_RTLENTRY ifstream(int __f, char _FAR *, int);

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

#include <fstream.h>#include <process.h> // Длявызова exitint main ( int argc, char* argv [ ] ) { char ch; if ( argc != 3 ) // Проверкачислааргументов { cerr << “ Вызов dcopy файл1 файл2 &bsol;n” ; exit ( 1 ) ; } ifstream source( argv [ 1 ] ) ; // Входнойпотокif ( ! source ) { cerr << “ Нельзя открыть входной файл “ << argv [ 1 ] ;exit ( 1 ); } ofstream dest ( argv [2 ] ) ;if ( ! dest ) { cerr << “ Нельзя открыть выходной файл “ << argv [ 2 ] ;exit ( 1 ); } while ((ch = source.get ( ) ) != EOF ) dest.put( ch ); close ( source ); close ( dest );return 0 ; }

6.3. Ввод-вывод данных объектных типов

Организация вывода данных определенных программистом объектных типов, в общем случае зависит от предполагаемого дальнейшего использования этих данных. Могут сохраняться в файле все компоненты данные, или только часть из них, может применяться форматированный или бесформатный вывод. Часто возникает необходимость сохранить объектные данные в файле для последующего их восстановления в той же или другой программе.

Для вывода объекта в файл в определение класса может быть включена функция-компонента с параметром ссылкой на объект типа ostream. Часто такой функции назначают имя print или printon. Более изящным считается переопределение оператора << для вывода объектного данного. Если компоненты-данные объекта имеют уровень доступа protected или private, а оператор << не является компонентой класса, его следует объявить как friend-метод.

Пусть, например, в программе определен класс complex:

class complex { double re, im ; public: complex (double r =0, double i =0 ): re ( r ), im ( i ) { } // конструктор double real ( ) {return ( re ); } double image ( ) { return ( im ); }/* другие методы */ }

Тогда для форматированного вывода комплексного числа в формате ( вещественная часть, мнимая часть ) можно так переопределить операцию << :

ostream& operator << ( ostream& s, complex c ) { int old_precision = s.precision ( 4 ); // установкачисладробныхцифр s << “(“ << c.real( ) << “, “ << c.image( ) << “)” ; s.precision ( old_precision ) ; // восстановлениечисладробныхцифр return ( s );}

В данном случае в переопределении << нет обращения к личным переменным класса Complex. Если не использовать методы real и image, переопределение << нужно было бы включить в описание класса Complex с описателем friend.

Ввод объектного данного из файла или стандартного потока организуется аналогично: либо в определение класса включается функция-компонента для инициализации компонент данных их входного потока, либо переопределяется операция >> для ввода компонент-данных из потока. В некоторых случаях оказывается более удобным включить в описание класса дополнительный конструктор с параметром-ссылкой на объект типа istream, при этом все базовые классы должны иметь аналогичные конструкторы.

Пусть в описание класса Complex включена переопределенная операция >>:

class complex{ double re, im ; public: complex (double r =0,double i=0 ): re( r ), im( i ) { } // конструктор double real ( ) {return ( re ); } double image ( ) { return ( im ); } friend istream& operator >> ( istream& , Complex& );/* другие методы */ }

Если предположить, что комплексные числа поступают из потока либо в виде вещественного числа, возможно заключенного

в скобки, либо в виде пары чисел, разделенных запятой и заключенной в скобки,

то переопределяемую операцию ввода можно описать следующим образом:

istream& operator >> ( istream& s, Complex& c ) { double re_n = 0, im_n = 0; char ch = 0; s >> ch ; if ( ch == ‘(‘ ) { s >> re_n >> ch ; if ( ch == ‘,’ ) s >> im_n >> ch;if ( ch != ‘)’) s.clear ( ios::failbit ); //Установка признака ошибки} else { s.putback ( ch ); s >> re_n ; } if ( s ) { c.re = re_n; c.im = im_n; } // Еслинебылоошибкиreturn ( s );

}

Рассмотренные выше примеры сохранения объектов

в потоке и восстановления их из потока иллюстрируют наиболее простые варианты

этих операций. Проблема сохранения объектов в потоке существенно усложняется,

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

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

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

несколько других объектов. В этой ситуации требуется для каждого сохраняемого

в потоке объекта заносить в поток идентификатор типа объекта, гарантировать,

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

помещен в поток только один раз. Средства для разрешения этих проблем имеются

в библиотеке классов-контейнеров classlib, содержащей

файл objstrm.h с определениями необходимых

классов и макросов.


Приложение 1. Задачи по программированию на Си

1. Составить функцию для подсчета числа серий положительных, отрицательных чисел и нулей длиной не менее К в одномерном массиве целых чисел. Серией называется последовательность элементов массива, принадлежащих одному классу:

int series ( int n, int *mas, int *kzero, int *kplus, int *kminus, int k);

2. Составить функцию для слияния двух упорядоченных по возрастанию массивов целых чисел: