Чтение онлайн

ЖАНРЫ

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

При малейшей возможности считывайте и записывайте файлы от начала до конца. Это проще всего и открывает меньше возможностей для совершения ошибок. Каждый раз, когда вы понимаете, что пора изменить файл, лучше создайте новый и запишите в него все изменения. Однако, если вы должны поступить иначе, то можно выполнить позиционирование и указать конкретное место для чтения и записи в файле. В принципе в любом файле, открытом для чтения, существует позиция для считывания/ввода (“read/get position”), а в любом файле, открытом для записи, есть позиция для записи/вывода (“write/put position”).

Эти

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

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;

}

double d1 = str_to_double("12.4"); // проверка

double d2 = str_to_double("1.34e–3");

double d3 = str_to_double("twelve point three"); // вызывается

// error

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

istringstream
, то он перейдет в состояние
eof
. Это значит, что для потока
istringstream
можно использовать обычный цикл ввода; поток
istringstream
на самом деле является разновидностью потока
istream
.

Поток

ostringstream
, наоборот, может быть полезен для форматирования вывода в системах, ожидающих
аргумента в виде простой строки, например в системах графического пользовательского интерфейса (раздел 16.5). Рассмотрим пример.

void my_code(string label, Temperature temp)

{

// ...

ostringstream os; // поток для составления сообщения

os << setw(8) << label << ": "

<< fixed << setprecision(5) << temp.temp << temp.unit;

someobject.display(Point(100,100), os.str.c_str);

// ...

}

Функция-член

str
класса
ostringstream
возвращает объект класса
string
, составленный операторами вывода, в поток
ostringstream
. Функция
c_str
— это функция-член класса
string
, возвращающая строки в стиле языка C, которые ожидаются интерфейсами многих систем.

Потоки
stringstream
обычно используются, когда мы хотим отделить собственно ввод-вывод от обработки данных. Например, аргумент типа
string
в функции
str_to_double
обычно поступает из файла (например, из журнала событий веб) или с клавиатуры. Аналогично, сообщение, составленное функцией
my_code
, в конце концов выводится на экран. Например, в разделе 11.7 мы используем поток
stringstream
при выводе для фильтрации нежелательных символов. Таким образом, потоки
stringstream
можно интерпретировать как механизм настройки ввода-вывода для особых потребностей и вкусов.

Продемонстрируем использование потока

ostringstream
на простом примере конкатенации строк.

int seq_no = get_next_number; // вводим число из системного журнала

ostringstream name;

name << "myfile" << seq_no; // например, myfile17

ofstream logfile(name.str.c_str); // например, открыть myfile17

Как правило, поток

istringstream
инициализируется объектом класса
string
, а затем считывает из него символы, используя операторы ввода. И наоборот, поток
ostringstream
инициализируется пустым объектом класса
string
, а затем заполняется с помощью операторов вывода. Существует более простой способ доступа к символам в потоке
stringstream
, который иногда оказывается полезным: функция
ss.str
возвращает копию строки из объекта
ss
, а функция
ss.str(s)
присваивает строке в объекте
ss
копию строки
s
. В разделе 11.7 приведен пример, в котором функция
ss.str(s)
играет существенную роль.

11.5. Ввод, ориентированный на строки

Оператор

>>
вводит данные в объекты заданного типа в соответствии со стандартным форматом, установленным для этого типа. Например, при вводе чисел в объект типа
int
оператор
>>
будет выполнять ввод, пока не обнаружит символ, не являющийся цифрой, а при вводе в объект класса
string
оператор
>>
будет считывать символы, пока не обнаружит разделитель (whitespace). Стандартная библиотека istream содержит также средства для ввода отдельных символов и целых строк. Рассмотрим пример.

Поделиться с друзьями: