Операции помещения и извлечения
Библиотека потоков С++ предусматривает два основных класса для ввода и вывода: соответственно istream и ostream. Класс ostream использует для вывода операцию левого сдвига(<<). Если эта операция применяется к объектам-потокам, ее называют операцией помещения (в поток). Следующий пример выводит приветствие, применяя операцию помещения к предопределенному объекту cout.
#include<iostream.h>
void main(0
{
cout<<”Всем привет!” <<’\n’;
}
После приветствия стоит символ перевода на новую строку ‘\n’.
Класс istream использует для ввода операцию правого сдвига (>>). В таком контексте ее часто называют операцией извлечения (из потока). Следующий пример применяет операцию извлечения к предопределенному объекту cin.
#include<iostream.h>
void main(0
{
char name [20]];
cout<<”Введите имя”;
cin >>name;
}
Классы istream и ostream перегружают соответственно операции извлечения и помещения для всех встроенных типов. Такая перегрузка позволяет использовать единообразный синтаксис для ввода/вывода символов, строк, целых и вещественных типов.
Кроме того, перегруженные операции << и >> возвращают ссылку на объект (return*this) соответствующего типа. Это позволяет последовательно соединять несколько операций, т.е. реализовать сцепление вызовов операций ввода/вывода.
Например:
cout<<”Введите а,в,с” <<’\n’;
cin >>а>>в>>с;
cout<<”Вы ввели: а=”<<a<<” в=”<<в<<” c=”<<c<<’\n’;
В этом фрагменте программы приведены сцепленные операции ввода и вывода.
В следующей программе приведены примеры перегруженных операций для встроенных типов.
#include<iostream.h>
#include<iomanip.h>
void main(0
{
int k;
cout<<”Введите k=” <<’\n’;
cin >>k;
long m;
cout<<”Введите m=” <<’\n’;
cin >>m;
float x;
cout<<”Введите x=” <<’\n’;
cin >>x;
double y;
cout<<”Введите y=” <<’\n’;
cin >>y;
char nch;
cout<<”Введите символ nch =” <<endl;/*endl – т.н. манипулятор. Он помещает в поток символ новой строки (\n) и вызывает манипулятор flush, который принудительно записывает все данные на соответствующие физические устройства. Поэтому endl рекомендуется ставить перед вводом символа и строки */
cin >> nch;
char name [15];
cout<<”Введите name =” <<endl;
cin >> name;
cout<<”Вы ввели: k=”<<k<<” m=”<<m<<” x=”<<x<< y=”<<y<< nch=”<<nch<< name =”<< name <<’\n’;
}
Расширение потоков для типов, определяемых пользователем
Можно легко расширить библиотеку, чтобы приспособить операции помещения/извлечения к собственным типам данных. Для этого следует определить две функции со следующими заголовками:
// Чтение данных из потока
istream& operator >> ( istream &is, имя_типа &имя_перем.);
// Запись данных в поток
оstream& operator << ( ostream &os, имя_типа &имя_перем.);
При использовании классов следует операции извлечения и помещения объявлять друзьями данного класса. Это обеспечивает операции доступа к элементам данных.
Пример расширения потоков для объектов class dog.
#include<iostream.h>
#include<iomanip.h>
class dog
{
char*poroda;
char*name;
int nomer;
friend istream &operator>>( istream &is, dog &x.);
friend оstream &operator<<( ostream &os, dog &x.);
};
istream &operator>>( istream &is, dog &x.);
{
poroda=new char[15];
name=new char[10];
cout<<”Введите породу” <<endl;
is>>x.poroda;
cout<<”Введите имя” <<endl;
is>>x.name;
cout<<”Введите номер” <<’\n’;
is>>x.nomer;
return is;//Обязательно!
}
оstream&operator<<( ostream&os, dog &x.);
{
os<<”Порода–” <<x.poroda<<” Имя–”<<x. name<<” Номер–”<<x. nomer<<’\n’;
return os;//Обязательно!
}
void main()
(
dog q;
cin>>q;
cout<<q;
}
Описан объект q класса dog. При его вводе вызывается дружественная функция operator>>(). В этой функции вместо формальных параметров (ссылок) x и is будут соответственно q и cin. Результат работы функции через return is присваивается предопределенному объекту класса istream cin. Аналогично выполняется дружественная функция operator<<().
Лекция 24
24.1 Файловый ввод/вывод с применением потоков С++
Библиотека С++ содержит три специализированные класса для файлового ввода/вывода. Это следующие классы:
ifstream – для операций с входным дисковым файлом;
ofstream– для операций с выходным дисковым файлом;
fstream – для входных и выходных операций с файлом.
Эти классы являются производными соответственно от istream, оstream и iostream. Таким образом, они наследуют все их функциональные особенности, в т.ч. перегруженные операции << и >> для встроенных типов.
Конструкторы файловых потоков
Для каждого из трех классов файловых потоков предусмотрено по четыре перегруженных конструктора. Рассмотрим два из них, применяемых наиболее часто. Это, в первую очередь, три пустых конструктора:
ifstream() ofstream() fstream()
{ { {
} } }
Они конструируют объекты, не открывая файла. Например, ifstream ifs; ofstream ofs; fstream f1,f2;
Три вторых конструктора позволяют конструировать объект, открыть файл и прикрепить объект к файлу. Их заголовки имеют вид:
ifstream(const char*name,int omode=ios::in,int prot=filebuf::openprot);
ofstream(const char*name,int omode=ios::out,int prot=filebuf::openprot);
fstream (const char*name,int omode, int prot=filebuf::openprot);
24.3 Открытие файла
Чтобы открыть файл, можно использовать конструкторы ifstream, ofstream или fstream. Автоматически вызываются вторые конструкторы. Для ifstream и ofstream обязательными являются лишь имена файлов. Остальные два параметра берутся по умолчанию. При вызове fstream необходимо обязательно передать первые два параметра: имя файла и режим его работы.
Примеры.
ifstream ifs1(“ish.dan”);
ofstream of1(“rezult.dan”);
ofstream of2(“rezult2.txt”,ios::app);
Файл rezult2.txt используется для дозаписи в конец файла (append).
fstream fil1(“file1.txt”,ios::in);
file1.txt – для чтения.
fstream fil2(“file2.dan”,ios::out);
fstream fil3(“file3.dan”,ios::app);
Файлы file2.dan и file3.dan созданы соответственно для записи и для дозаписи в конец файла.
Открыть файл можно также с помощью функции –члена open() класса ios. Ее прототип имеет вид:
filebuf*open(const char*name,int mode, int prot=filebuf::openprot);
При ее вызове обязательными являются только первые два параметра: имя файла и режим его работы (доступа). Режимы доступа задаются перечисляемыми битовыми масками в классе ios.
еnum open_mode
{
in=0x01://open for reading
out=0x02://open for writing
ate=0x04://seek to end of file upon original//open
app=0x08://append mode
trunc=0x10://trancate file if already exist
nocreate=0x20:// open fails if file doesn’t exist
noreplace=0x40:// open fails if file already exists
binary=0x80:// binary file
};
Примеры.
Предположим, с помощью пустого конструктора были созданы объекты:
fstream fin, fout;
fin.open(“ish.dan”, ios::in);
fout.open(“rez.dan”, ios::out);
Эти два файловых объекта открыты соответственно для чтения и для записи. Можно указывать несколько режимов доступа через вертикальную линию. Например:
fout.open(“rez.dan”, ios::out|ios::ate);
Закрытие файла
В классах файловых потоков имеется метод close, который опорожняет поток и закрывает закрепленный за потоком файл. Примеры:
fin.close ( );
fout.close ( );
Предполагается, что деструктор файлового объекта (или его базового класса) автоматически закрывает файл.
Примеры программ работы с файлами.
Пример 1 Табулирование функции. Исходные данные размещаются в файле ish.dan, а результаты будут заноситься в файл rez.dan.
# include < iostream. h >
# include < fstream. h >
# include < math. h >
# include < stdlib. h >
void main ( )
{
ifstream fin (“ist. dan”);
if (fin)
{
cout << “не открылся файл ish. dan” <<’\ n ‘;
exit (1);
}
ofstream fout (“rez. dan”);
double x, y, xn, dx, xk;
fin >>xn>>dx>>xk;
fout << “xn=” <<xn<<” dx=” <<dx<<“ xk = “<<xk<<’ \ n ‘;
for (x = xn; x <= xk; x += dx)
{
y = exp ( -x );
fout << “ x = “ <<x<< ” y = “<< y << ‘ \ n’;
}
fin. close ( );
fout. close ( );
}
Пример 2 Постановка задачи.
Описать класс «матрица». Предусмотреть функцию-член для ввода элементов матрицы из выходного файла, дружественную функцию для их сложения и член-функцию для занесения результирующей матрицы в файл результатов. Количество строк и столбцов считать заведомо известными.
# include < iostream. h >
# include < fstream. h >
# include < stdlib. h >
# define N 2
# define M 3
class matr
{
float x [ N ] [ M ];
public:
void vvod (char * S);
void vivod (char * S);
friend matr operator + (matr & a, matr & b);
};
void matr :: vvod (char * S)
{
ifstream ifs (S);
if (ifs)
{
cout << “Не открылся файл” << S << ‘ \ n ‘;
exit (1);
}
for ( int i = Ø; i < N; i + +)
for ( int j = Ø; j < M; j + +)
ifs >> x [ i ][ j ];
}
void matr :: vivod ( char * S)
{
ofstream ofs ( S );
for (int i = Ø; i < N; i ++)
for (int j = Ø; j < M; j ++)
ofs <<x [ i ][ j ];
}
matr operator + ( matr & a, matr & b)
{
matr z;
for (int i = Ø; i < N; i ++)
for (int j = Ø; j < M; j ++)
z. x [ i ] [ j ] = a. x [ i ] [ j ] = b. x [ i ] [ j ] ;
return z;
}
void main ( )
{
matr v, w, q
v. vvod (“v. dan”);
w. vvod (w. dan”);
q = v + w;
q. vivod (“q. dan”);
}
Матрицы v и w записаны соответственно в файлах v.dan и w.dan. Результирующая матрица q заносится в файлq.dan.
Не нашли, что искали? Воспользуйтесь поиском по сайту:
©2015 - 2024 stydopedia.ru Все материалы защищены законодательством РФ.
|