Функция as_bytes()
позволяет получить адрес первого байта объекта. Ее определение выглядит так (некоторые особенности языка, использованные здесь, будут рассмотрены в разделах 17.8 и 19.3):
template
char* as_bytes(T& i) // рассматривает объект T как последовательность
// байтов
{
void* addr = &i // получаем адрес первого байта
// памяти, использованной для хранения объекта
return static_cast
}
Небезопасное преобразование типа с помощью оператора static_cast необходимо для того, чтобы получить переменную в виде совокупности байтов. Понятие адреса будет подробно изучено в главах 17 и 18. Здесь мы просто показываем, как представить любой объект, хранящийся в памяти, в виде совокупности байтов, чтобы прочитать или записать его с помощью функций read()
и write()
.
Этот двоичный вывод запутан, сложен и уязвим для ошибок. Однако программисты не всегда должны иметь полную свободу выбора формата файла, поэтому иногда они просто вынуждены использовать двоичный ввод-вывод по воле кого-то другого. Кроме того, отказ от символьного представления иногда можно логично обосновать. Типичные примеры — рисунок или звуковой файл, — не имеющие разумного символьного представления: фотография или фрагмент музыкального произведения по своей природе является совокупностью битов.
11.3.3. Позиционирование в файлах
Эти позиции можно использовать следующим образом.
fstream fs(name.c_str()); // открыть для ввода и вывода
if (!fs) error("Невозможно открыть файл ",name);
fs.seekg(5); // перенести позицию считывания (буква g означает "get")
// на пять ячеек вперед (шестой символ)
char ch;
fs>>ch; // считать и увеличить номер позиции для считывания
cout << " шестой символ — это " << ch << '(' << int(ch) << ")\n";
fs.seekp(1); // перенести позицию для записи (буква p означает "put")
// на одну ячейку вперед
fs<<'y'; // записать и увеличить позицию для записи
Будьте осторожны: ошибки позиционирования не распознаются. В частности, если вы попытаетесь выйти за пределы файла (используя функцию seekg()
или seekp()
), то последствия могут быть непредсказуемыми и состояние операционной системы изменится.
11.4. Потоки строк
istream
или цели вывода для потока ostream
можно использовать объект класса string
. Поток istream
, считывающий данные из объекта класса string
, называется istringstream
, а поток ostream
, записывающий символы в объект класса string
, называется ostringstream
. Например, поток istringstream
полезен для извлечения числовых значений из строк.
double str_to_double(string s)
// если это возможно, преобразовывает символы из строки s
// в число с плавающей точкой
{
istringstream is(s); // создаем поток для ввода из строки s
double d;
is >> d;
if (!is) error("Ошибка форматирования типа double: ",s);
return d;
}