Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по Программированию.doc
Скачиваний:
49
Добавлен:
11.02.2015
Размер:
1.22 Mб
Скачать

Ввод-вывод двоичных данных

Для ввода-вывода двоичных данных используются функции (методы классов ostream и istream) put, write и get, которые определены следующим образом:

ostream& ostream::put(char ch);

//посылает ch в ostream

ostream& ostream::write(const char* buff, int n);

//посылает n символов из buff в ostream;

Put и write позволяют выводить неформатированные двоичные данные в объект ostream. Put выводит один символ, а write может послать любое количество символов из указанного буфера. Write полезна, когда нужно вывести необработанные данные, которые могут включать нули. (Запись двоичных данных требует, чтобы файл был открыт в двоичном режиме.)

Обычное извлечение строки не будет работать до тех пор, пока строка не будет завершена нулем.

Входная версия put называется get:

char ch;

cin.get(ch); //захватывает следующий символ из

//cin независимо от того пробел это или нет

Другая версия get позволяет захватывать любое количество необработанных, двоичных символов из istream до заданного максимума и помещать их в заданный буфер (так же, как и в случае с write, файлы должны быть открыты в двоичном режиме):

istream& istream::get(char *buff, int max, int term='\n');

//читает символы до максимального количества из istream, а

//затем помещает их в buff. Прекращает чтение, если

//прочитан

//символ, указанный в term.

Можно установить term равным определенному конечному символу (по умолчанию — это символ новой строки), в котором get будет прекращать работу, если он будет достигнут прежде, чем max символов будет передано в buff.

Ввод/вывод с диска

Библиотека iostream включает много классов, порожденных из streambuf, ostream и istream, предоставляя, таким образом, широкий выбор методов ввода/вывода файлов. Класс filebuf например, поддерживает ввод/вывод через дескрипторы файлов с помощью функций элементов для открытия, закрытия и поиска.

Наиболее часто используемыми классами являются ifstream (порожденный из istream), ofstream (порожденный из ostream) и fstream (порожденный из iostream). Все они поддерживают форматированный файл ввода/вывода, используя объекты filebuf. Ниже приведен простой пример, который копирует существующий дисковый файл в другой заданный файл:

/* DCOPY исходный файл / файл назначения *

* копирует существующий исходный файл в файл назначения *

* Если последний существует, то он перезаписывается; *

* если не существует, DCOPY создаст его, если это возможно *

*/

#include <iostream.h>

#include <process.h> // для exit()

#include <fstream.h> // для ifstream, ofstream

int main(int argc, char* argv[])

{

char ch;

if (argc != 3) // проверка числа аргументов

{

cerr << "USAGE: dcopy file1 file2\n";

exit(-1);

}

ifstream source; // объявить входной и выходной потоки

ofstream dest;

source.open(argv[1],ios::nocreate); // должен быть исходный файл

if (!source)

{

cerr << "Cannot open source file " << argv[1] << " for input\n";

exit(-1);

}

dest.open(argv[2]); // файл назначения будет создан, если

// не он найден или создан/перезаписан, если найден

if (!dest)

{

cerr << "Cannot open destination file " << argv[2] << " for output\n";

exit(-1);

}

while (dest && source.get(ch))

dest.put(ch);

cout << "DCOPY completed\n";

source.close(); // закрыть оба потока

dest.close();

}

Типичный вызов этой программы в командной строке выглядит следующим образом:

dcopy letter.spr letter.bak

Пример 2. Разработать программу для ввода/вывода с диска массива структур.

#include <iostream.h>

#include <fstream.h>

int main(int argc, char* argv[])

{

struct emp

{

char* name;

int dept;

};

emp e[2];

e[0].name="aaaa";

e[0].dept=1;

e[1].name="bbbbbbb";

e[1].dept=2;

ifstream source;

ofstream dest;

char filename[20]="s.dat";

dest.open(filename);

for(int i=0;i<2;i++)

dest<<e[i].name<<" "<<e[i].dept<<endl;

dest.close();

source.open(filename,ios::nocreate); // файл должен быть создан

for(int i=0;i<2;i++)

{

source>>e[i].name>>e[i].dept;

cout<<e[i].name<<" "<<e[i].dept<<endl;

}

source.close();

cin.get();

return 0;

}

При этом файл s.datсодержит следующие данные:

aaaa 1

bbbbbbb 2

Если поле nameможет содержать пробелы, то такой способ ввода/вывода непригоден. Нужно использовать разделитель полей, отличный от пробела, например,@.

for(int i=0;i<2;i++)

dest<<e[i].name<<"@"<<e[i].dept<<endl;

Теперь чтение данных будет выглядеть следующим образом:

char buf[22];

for(int i=0;i<2;i++)

{

source.get(e[i].name, 100, '@');

source.get(); //отбросить @

source.get(buf, 100, '\n');

source.get(); //отбросить \n

e[i].dept=atoi(buf);

cout<<e[i].name<<" "<<e[i].dept<<endl;

}