
- •Лабораторная работа №6. Запись / чтение структуры из файла. Теоретическая часть
- •Открытие и закрытие файлов
- •Класс istream
- •Функции get, getline и read
- •Функция возвращения
- •Позиционирование потока
- •Класс ostream
- •Функции вывода put и write
- •Функции класса filebuf
- •Функции класса streambuf
- •Функции класса strstreambuf
- •Определение состояния потока
- •Работа со списком.
- •Работа со списками через файл.
- •Контрольные вопросы:
- •Порядок выполнения лабораторной работы:
- •Практическая часть. Индивидуальные задания.
Функция возвращения
Функция-компонент
istream istream::putback(char c);
возвратит обратно в istream один символ c; если этот символ не может быть помещен обратно, то устанавливается состояние потока "отказ".
Позиционирование потока
Функция seekg() может содержать один или два аргумента: в качестве первого – требуемая позиция курсора или величина смещения, если присутствует второй аргумент; второй - смещение на величину первого аргумента. Второй аргумент может быть один из флагов:
Флаг |
Назначение |
ios::beg ios::cur ios::end |
Смещение от начала файла Смещение от текущего положения курсора Смещение от конца файла |
Пример:
io.seekg(5,ios::end);
io.seekg(5,ios::beg);
Пример: Выполнить чтение из файла построчно по 80 символов в каждой строке с выводом считанных данных на экран.
#include <fstream.h>
#define col 80
void main()
{
char str[col];
ifstream fstr(“a.cpp”);
while(fstr){
fstr.getline(str,col);
cout<<’\n’<<str;
}
fstr.close();
}
Класс ostream
Функции управления потоковым выводом сосредоточены в классе оstream. С каждым из объектов этого класса и его производных связан объект класса streambuf. Функции класса оstream, доступные его потомкам, перечислены в таблице.
Функция |
Назначение |
opfx
|
Вызывается перед операцией записи для проверки наличия ошибок в потоке |
osfx |
Вызывается после каждой операции записи для очистки буфера |
put |
Записывает в поток одиночный байт |
write |
Записывает в поток требуемое число байтов |
flush
|
Очищает буфер потока; аналогичное действие выполняет манипулятор flush |
seekp
|
Перемещает маркер, обозначающий текущую позицию записи, на требуемую позицию в потоке |
tellp |
Возвращает позицию маркера записи |
Функции вывода put и write
Для вывода двоичных данных или отдельного символа можно использовать функцию-компонент put, объявленную в ostream следующим образом:
ostream ostream::put (char ch);
При объявлении int ch='x'; следующие две строки эквивалентны:
cout.put(ch);
cout << (char)ch;
Функция-компонент write позволяет вывод больших по размеру объектов:
ostream& ostream::write( signed char* ptr, int n);
ostream& ostream::write( unsigned char* ptr, int n);
Функции write выводят n символов (включая любые входящие пустые символы) в двоичном формате. В отличие от строковой вставки, write не прекращает работу, встретив пустой символ.
Например,
int x; char s[12];
cout.write((char *)&x, sizeof(x));
cout.write(s,sizeof(s));
пошлет не преобразованное представление х и s на стандартное устройство вывода.
Существует тонкое различие между форматированной операцией << и неформатированными функциями put и write. Форматированная операция может вызвать очистку связанных потоков и иметь атрибут ширины поля. Неформатированные операции не обладают этими свойствами. Поэтому cout << 'a' и cout put('a') могут давать разные результаты. Все флаги форматирования применимы к <<, но ни один из них не применим к put или write.
Пример: В файл, открытый в текстовом режиме, дважды записывается одна и та же строка: первый раз – посимвольно; второй – вся строка целиком.
#include <fstream.h>
#include <string.h>
#define n 40
main()
{ int i=0;
char str[n]="Записываемая строка\n";
ofstream fstr("ofstream.out");
while(str[i] !='\0')
{fstr.put(str[i]);
cout<<"\nПозиция маркера записи: "<<fstr.tellp();
i++;}
fstr.write(str,strlen(str));
cout<<"\nНовая позиция маркера записи: "<<fstr.tellp();
fstr.close();
}
Результат:
Позиция маркера записи: 1
Позиция маркера записи: 2
… … …
Позиция маркера записи: 19
Позиция маркера записи: 21
Новая позиция маркера записи: 42
При выводе данных в файл, открытый в текстовом режиме, автоматически выполняется преобразование \n = CR/LF, т.е. символ новой строки преобразуется в пару символов возврата каретки и перевода строки. При чтении происходит обратное преобразование. Именно поэтому наблюдается “скачок” счетчика: после 19 идет 21. Функция put(), записывающая в файл \n, на самом деле помещает в файл два других символа. Функция write() выполняет такое же преобразование, поэтому конечное число счетчика равно 42, а не 41.
Если в данной программе указать не текстовый, а двоичный файл
ofstream fstr("ofstream.out", ios::binary);
то такого “скачка” счетчика наблюдаться не будет, т.к. не происходит замены символа новой строки в пару символов возврата каретки и перевода строки.