Для каждого из трех классов файловых потоков предусмотрено по четыре перегруженных конструктора. Рассмотрим два из них, применяемых наиболее часто. Это, в первую очередь, три пустых конструктора:
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.
24.5 Перегрузка операций сдвига для файлового ввода/вывода
Осуществляется подобно рассмотренному ранее расширению потоков для типов, определяемых пользователем с использованием дружественных функций. Их заглавия имеют вид:
friend ifstream & operator >> (ifstream & ifs, имя класса & имя объекта);
friend ofstream & operator << (ofstream & ofs, имя класса & имя объекта);
Пример. Условия задачи такие же, как и в предыдущем примере, но складываемые матрицы находятся в одном файле v hod. dan.
Пусть конкретно находится серия матриц v [ 2 ] [ 3 ] и w [ 2 ] [ 3 ]. Их элементы последовательно записаны в файле v hod. dan. Например, в файле v hod. dan имеются следующие числа:
1 2 3
4 5 6
-1 -2 -3
-4 -5 -6
Первые две строки – элементы матрицы v, а вторые – матрицы w.
# include < iostream. h >
# include < fstream. h >
# include < stdlib.h >
# define N 2
# define M 3
class matr
{
float x [ N ] [ M ];
friend ifstream & operator >> (ifstream & ifs, matr & x);
friend ofstream & operator << (ofstream & ofs, matr & a);
friend matr operator + (matr & a, matr & b);
};
ifstream & operator >> (instream & ifs, matr & x)
{
for (int I = Ø; I < N; I ++)
for (int j = Ø; j < M; j ++)
ifs >>x. x [ I ] [ j ]; / * Допускается совпадение символических имен элементов данных и параметров * /.
return ifs; //Не забывать!
}
ofstream & operator << (ofstream & ofs, matr & a)
{
for (int I = Ø; I < N; I ++)
for (int j = Ø; j < M; j ++)
ofs << a. x [ I ] [ j ];
return ofs;
}
matr operator + (matr & a, matr & b)
{
matr v;
for (int I = Ø; I < N; I ++)
for (int j = Ø; j < M; j ++)
v. x [ I ] [ j ] = a. x [ I ] [ j ] + b. x [ I ] [ j ];
return v;
}
void main ()
{
matr w, v;
ifstream fvh (“v hod. dan”);
fvh >> v >> w; // * Дважды вызывается оператор >>. Первой вводится матрица v, а за ней w */
matr q;
q = v + w; //вызывается оператор + ().
ofstream viv (“q. dan”);
viv << q; //Вывод q в файл q.dan.
//Вызывается оператор << ().
}
Лекция 25
Форматирование данных
Библиотека потоков С + + предусматривает три способа управления форматом выходных данных: вызов форматирующих функций – элементов, использование флагов и применение манипуляторов.