Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lek13_14.doc
Скачиваний:
9
Добавлен:
13.07.2019
Размер:
695.3 Кб
Скачать

Двоичные файлы

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

// //       binary.срр //       Эта программа является модификацией предыдущего примера //       и демонстрирует работу с файлом,открытым в двоичном режиме. //

#include <fstream > #include <string.h>

#define iSTRING_MAX 40

void main () {

int i = 0;

char pszString [iSTRING_MAX] = "Записываемая строка\n";

// файл открывается в двоичном режиме

ofstream ofMyOutputStream("OFSTREAM.OUT", ios :: binary)

// строка выводится символ за символом; // обратите внимание, что символ ' \n ' // никак не преобразуется while (pszString [i]!= '\0') {

ofMyOutputStream.put (pszString [i]);

cout <<' "\nПозиция маркера записи: << ofMyOutputStream.tellp() ;

i++;}

// запись всей строки целиком 

ofMyOutputStream.write(pszString, strlen(pszString)),

cout<< "\nНовая позиция маркера записи: "<< ofMyOutputStream.tellp() ; ofMyOutputStream.close() ; }

Вот результаты работы программы:

Позиция маркера записи:  1

Позиция маркера записи:  2

Позиция маркера записи:  3

Позиция маркера записи: 18

Позиция маркера записи: 19

Позиция маркера записи: 20

Новая позиция маркера записи: 40

При выводе строки pszString не происходит замены концевого символа \n парой символов возврата каретки и перевода строки, поэтому в поток записывается 20 символов — ровно столько, сколько содержится в строке.

Буферы потоков

В основе всех буферизованных потоков ввода-вывода в C++ лежит класс streambuf. В этом классе описаны основные операции, выполняемые над буферами ввода-вывода (табл. 10). Любой класс, порожденный от ios, наследует указатель на объект класса streambuf. Именно последний выполняет реальную работу по вводу и выводу данных.

Объекты класса streambuf управляют фиксированной областью памяти, называемой также областью резервирования. Она, в свою очередь, может быть разделена на область ввода и область вывода, которые могут перекрывать друг друга.

Класс streambuf является абстрактным, т.е. создать его объект напрямую нельзя (его конструктор является защищенным и не может быть вызван из программы). В то же время, имеются три производных от него класса, предназначенные для работы с потоками конкретного типа: filebuf (буферы дисковых файлов), strstreambuf (строковые буферы, хранящиеся в памяти) и stdiobuf (буферизация дискового ввода-вывода с помощью стандартных системных функций). Кроме того, можно создавать собственные классы, порожденные от streambuf, переопределяя его виртуальные функции (табл. 11) и настраивая, таким образом, его работу в соответствии с потребностями конкретного приложения. Только из производных классов можно вызывать и многочисленные защищенные функции этого класса, управляющие областью резервирования (табл. 12).

Таблица 10. Открытые функции класса streambuf

Открытая функция

Описание

in_avail

Возвращает число символов в области ввода

sgetc

Возвращает символ, на который ссылается указатель области ввода; при этом указатель не перемещается

snextc

Перемещает указатель области ввода на одну позицию вперед, после чего возвращает текущий символ

sbumpc

Возвращает текущий символ и затем перемещает указатель области ввода на одну позицию вперед

stossc

Перемещает указатель области ввода на одну позицию вперед, но не возвращает символ

sputbaqkc

Перемещает указатель области ввода на одну позицию назад, возвращая символ в буфер

sgetn

Читает требуемое количество символов из буфера

out_waiting

Возвращает число символов в области вывода

sputc

Записывает символ в буфер и перемещает указатель области вывода на одну позицию вперед

sputn

Записывает требуемое количество символов в буфер и перемещает указатель области вывода на соответствующее число позиций

dbp

В текстовом виде записывает в стандартный выходной поток различного рода информацию о состоянии буфера

Таблица 11. Виртуальные функции класса streambuf

Виртуальная функция

Описание

sync

Очищает области ввода и вывода

setbuf

Добавляет к буферу указанную зарезервированную область памяти

seekoff

Перемещает   указатель   области   ввода   или   вывода   на   указанное количество байтов относительно текущей позиции

seekpos

Перемещает указатель области ввода или вывода на указанную позицию относительно начала потока

overflow

Очищает область вывода

underflow

Если область ввода пуста, заполняет ее данными из источника

pbackfail

Вызывается функцией sputbackc() в случае неудачной попытки вернуться назад на один символ

Таблица 12. Защищенные функции класса streambuf

Защищенная функция

Описание

base

Возвращает указатель на начало области резервирования

ebuf

Возвращает указатель на конец области резервирования

blen

Возвращает размер области резервирования

phase

Возвращает указатель на начало области вывода

pptr

Возвращает значение указателя области вывода

epptr

Возвращает указатель на конец области ввода

eback

 Возвращает указатель на начало области ввода

gptr

Возвращает значение указателя области ввода

egptr

Возвращает указатель на конец области вывода

setp

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

setg 

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

pbump

Перемещает указатель области вывода на указанное число байтов относительно текущей позиции

gbump

Перемещает указатель области ввода на указанное число байтов относительно текущей позиции

setb

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

unbuffered 

Задает или возвращает значение переменной, определяющей состояние буфера

allocate

Вызывает виртуальную функцию deallocate для создания области резервирования

deallocate

Выделяет память для области резервирования (виртуальная функция)

Классы файловых потоков, такие как ifstream, ofstream и fstream, содержат встроенный объект класса filebuf, который вызывает низкоуровневые системные функции для управления буферизованным файловым вводом-выводом. Для объектов класса filebuf области ввода и вывода, а также указатели текущей позиции чтения и записи всегда равны друг другу. Функции этого класса перечислены в табл. 13.

Таблица 13.Функции класса filebuf

Функция

Описание

open

Открывает файл, связывая с ним объект класса filebuf

close

Закрывает файл, "выталкивая" все содержимое области вывода

setmode

Задает режим доступа к файлу: двоичный (константа filebuf:: binary) или текстовый (константа filebuf: :text)

attach

Связывает указанный открытый файл с объектом класса filebuf

fd

Возвращает дескриптор файла

is_open

Проверяет, открыт ли файл, связанный с потоком

В следующей программе создаются два файловых объекта: fbMylnputBuf и fbMyOutputBuf. Оба они открываются в текстовом режиме с помощью функции open(): первый — для чтения, второй — для записи. Если при открытии файлов не возникнет никаких ошибок, то каждый из них связывается с соответствующим объектом класса istream и ostream. Далее в цикле while символы читаются из файла fbMylnputBuf с помощью функции get() класса istream и записываются в файл fbMyOutputBuf с помощью функции put() класса ostream. Подсчет числа строк осуществляется с помощью выражения

iLineCount  +=   (ch ==   '\n');   

Когда в поток помещается символ \n, выражение в скобках возвращает 1 и счетчик iLineCount увеличивается на единицу, в противном случае он остается неизменным.

Оба файла закрываются с помощью функции close().

// //   filebuf.cpp //   Эта программа на языке C++ демонстрирует, как работать //   с объектами класса filebuf. //

#include <f stream. h>

t#include <process.h> // содержит прототип функции exit()

void main (void) 

{

char ch;

int iLineCount = 0;

filebuf fbMyInputBuf, fbMyOutputBuf;

fbMyInputBuf .open ("FILEBUF.CPP", ios::in);

if (fbMylnputBuf .is_open()== 0) {

cerr<< "Невозможно открыть файл для чтения";

exit (1);

}

istream is(SfbMylnputBuf) ;

fbMyOutputBuf.open("output.dat",ios::out);

if(fbMyOutputBuf.is_open() == 0) {

cerr<< "Невозможно открыть файл для записи";

exit(2); }

ostream os(SfbMyOutputBuf);

while (is) {

is.get(ch);

os.put(ch);  

iLineCount += (ch== '\n');

}

bMylnputBuf. close (); fbMyOutputBuf.close();

cout << "Файл содержит " << iLineCount << " строк";

}

Cтроковые буферы

Класс strstreambuf управляет символьным буфером, расположенным в динамической памяти.

Несколько примеров форматного вывода данных

В первом примере на экран выводится список факториалов чисел от 1 до 25 с выравниванием влево:

// //  fact.cpp //  Эта программа на языке C++ выводит список факториалов чисел от 1 до 25. //

#include <iostream.h> main ()

{ double number = 1.0,factorial = 1.0;

cout .precision (0);  //0 цифр после запятой

cout .setf (ios:: left) ;    //  выравнивание влево

cout .setf (ios:: fixed) ;   //     фиксированный формат (безэкспоненты)

for(int i =0; i < 25;i++) {

factorial *= number++;

cout << factorial << endl; }

return(0); }       

Результаты работы программы будут такими:

1

2

6

24

120

720

5040

40320

362880

3628800

39916800

479001600

6227020800

87178291200

1307674368000

20922789888000

355687428096000

6402373705728000

121645100408832000

2432902008176640000

51090942171709440000 

1124000727777607680000

25852016738884976640000

620448401733239439360000  

15511210043330985984000000

Во втором примере на экран выводится таблица квадратов и квадратных корней целых чисел от 1 до 15.

// //       sqrt.cpp //  Эта программа на языке C++ строит таблицу квадратов и квадратных //  корней чисел от 1 до 15. //

#include <iostream.h> # include <math.h>

main () {

double number =1.0,square, sqroot;

cout << "Число\tKвaдрат\t\tKвадратный корень\n";

cout <<  " ______________________________________ \n";

cout .setf (ios:: fixed) ; // фиксированный формат (без экспоненты)

for(int i = 1; i < 16;i++) {

square = number * number; // вычисление квадрата числа sqroot = sqrt(number);   // нахождение корня числа

cout.fill('0');    // заполнение недостающих позиций нулями cout.width(2);    // ширина столбца — минимум 2 символа cout.precision(0); // 0 цифрпосле запятой cout << number << "\t";

cout.fill(' ');   // использовать пробел в качестве заполнителя cout << square << "\t\t";

cout.precision(6);  // 6 цифр после запятой cout<< sqroot<< endl;

number++; }

return(0); }

Программа выведет следующую таблицу чисел:

число  корень  квадратный корень

01

1

1.000000

02

4

1.414214

03

9

1.732051

04

16

2.000000

05

25

2..236068

06

36

2.449490

07

49

2.645751

08

64

2.828427

09

81

3.000000

10

100

3.162278

11

121

3.316625

12

144

3.464102

13

169

3.605551

14

196

3.741657

15

225

3.872983

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]