- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
Вполне логично, что для класса istream, а также производных от него классов ifstream и istringstream (см. раздел 8.1) можно использовать только версии g, а для классов ostream и классов ofstream и ostringstream, производных от него, можно использовать только версии p. Классы iostream, fstream и stringstream способны читать и записывать данные в поток, поэтому для них можно использовать обе версии, g и p.
Существует только один маркерТот факт, что библиотека различает версии функций seek() и tell() для чтения и записи, может ввести в заблуждение. Хотя библиотека и различает эти функции, в файле существует только один маркер, т.е. нет разных маркеров для чтения и записи.
Когда речь идет о потоке только ввода или вывода, различие не столь очевидно. В таких потоках можно использовать версии только g или p. Если попытаться вызвать функцию tellp() для объекта класса ifstream, компилятор сообщит об ошибке. Аналогично он поступит при попытке вызвать функцию seekg() для объекта класса ostringstream.
Типы fstream и stringstream допускают чтение и запись в тот же поток. У них есть один буфер для хранения подлежащих чтению и записи данных, а также один маркер, обозначающий текущую позицию в буфере. Библиотечные функции версий g и p используют тот же маркер позиции.
Поскольку существует только один маркер, для переустановки маркера при каждом переключении между чтением и записью следует применять функцию seek().
Перемещение маркераИмеются две версии функции установки позиции: одна обеспечивает переход к указанной позиции в файле, а другая осуществляет смещение от текущей позиции.
// установка маркера в заданную позицию
seekg(new_position); // установить маркер чтения в позицию pos_type
seekp(new_position); // установить маркер записи в позицию pos_type
// смещение позиции на указанную дистанцию от текущей
seekg(offset, from); // установить дистанцию смещения маркера чтения
seekp(offset, from); // от from; offset имеет тип off_type
Возможные значения параметра from перечислены в табл. 17.21.
Аргументы new_position и offset этих функций имеют машинно-зависимые типы pos_type и off_type соответственно. Они определены в классах istream и ostream. Тип pos_type представляет позицию файла, а тип off_type — смещение от этой позиции. Значение типа off_type может быть положительным или отрицательным, что соответствует смещению вперед или назад.
Доступ к маркеруФункции tellg() и tellp() возвращают значение типа pos_type, обозначающее текущую позицию в потоке. Эти функции обычно используются для того, чтобы запомнить позицию и впоследствии вернуться к ней:
// запомнить текущую позицию записи в переменную mark
ostringstream writeStr; // поток вывода в строку
ostringstream::pos_type mark = writeStr.tellp();
// ...
if (cancelEntry)
// возврат к отмеченной позиции
writeStr.seekp(mark);
Чтение и запись в тот же файлРассмотрим пример программы, которая читает файл и записывает в его конец новую строку, содержащую относительную позицию начала каждой строки. Предположим, например, что работать придется со следующим файлом.
Abcd
efg
hi
j
Модифицированный программой файл должен выглядеть следующим образом.
Abcd
efg
hi
j
5 9 12 14
Обратите внимание: программа не записывает смещение для первой строки, она всегда начинается с позиции 0. Обратите также внимание на то, что смещения должны также учитывать невидимый символ новой строки, завершающий каждую строку. И наконец, последнее число в выводе — смещение для строки, с которой начинается вывод. При включении этого смещения в вывод можно отличить свой вывод от первоначального содержимого файла. Можно прочитать последнее число в полученном файле и установить смещение так, чтобы получить позицию начала вывода.
Наша программа будет читать файл построчно. Для каждой строки значение счетчика будет увеличиваться на размер только что прочитанной строки. Этот счетчик содержит смещение, с которого начинается следующая строка:
int main() {
// открыть файл для ввода и вывода, а затем перейти в его конец
// аргументы режима файла приведены в табл. 8.4
fstream inOut("copyOut",
fstream::ate | fstream::in | fstream::out);
if (!inOut) {
cerr << "Unable to open file!" << endl;
return EXIT_FAILURE; // EXIT_FAILURE см. p. 6.3.2
}
// inOut открыт в режиме ate, поэтому исходной позицией файла будет
// его конец
auto end_mark = inOut.tellg(); // запомнить позицию первоначального
// конца файла
inOut.seekg(0, fstream::beg); // перейти к началу файла
size_t cnt = 0; // счетчик количества байтов
string line; // содержит каждую строку ввода
// пока нет ошибки и исходные данные читаются
while (inOut && inOut.tellg() != end_mark
&& getline(inOut, line)) { // и можно получить следующую строку
cnt += line.size() + 1; // добавить 1 для новой строки
auto mark = inOut.tellg(); // запомнить позицию чтения
inOut.seekp(0, fstream::end); // установить маркер записи в конец
inOut << cnt; // записать общую длину
// вывести разделитель, если это не последняя строка
if (mark != end_mark) inOut << " ";
inOut.seekg(mark); // восстановить позицию чтения
}
inOut.seekp(0, fstream::end); // перейти к концу
inOut << "n"; // вывести символ новой строки в конце файла
return 0;
}
Эта программа открывает поток fstream в режимах in, out и ate (см. табл. 8.4). Первые два режима означают, что предполагается чтение и запись в тот же файл. Режим ate означает, что начальной позицией открытого файла будет его конец. Как обычно, необходимо удостовериться, что файл открыт корректно, если это не так, следует выйти из программы (см. раздел 6.3.2).
Поскольку программа пишет в свой исходный файл, нельзя использовать конец файла как признак прекращения чтения. Цикл должен закончиться по достижении конца первоначального ввода. В результате сначала следует запомнить первоначальную позицию конца файла. Так как файл открыт в режиме ate, поток inOut уже установлен в конец. Сохраним текущую (т.е. первоначальную) позицию конца файла в переменной end_mark. Запомнив конечную позицию, маркер чтения следует установить в начало файла, чтобы можно было приступить к чтению данных.
Цикл while имеет три условия выхода: сначала проверяется допустимость потока; если это так, то проверяется, не достигнут ли конец исходных данных. Для этого текущая позиция чтения, возвращаемая функцией tellg(), сравнивается с позицией, заранее сохраненной в переменной end_mark. И наконец, если обе проверки пройдены успешно, происходит вызов функции getline(), которая читает следующую строку из файла. Если вызов функции getline() успешен, выполняется тело цикла.
Тело цикла начинается с запоминания текущей позиции в переменной mark. Она сохраняется для возвращения после записи следующего относительного смещения. Вызов функции seekp() переводит маркер записи в конец файла. Выводится значение счетчика, а затем функция seekg() возвращается к позиции, сохраненной в переменной mark. Восстановив положение маркера, можно снова проверить условие выхода из цикла while.
Каждая итерация цикла выводит смещение следующей строки. Поэтому последняя итерация цикла заботится о записи смещения последней строки. Однако в конец файла следует еще записать символ новой строки. Как и в других случаях записи, для позиционирования в конец файла перед выводом новой строки происходит вызов функции seekp().
Упражнения раздела 17.5.3Упражнение 17.39. Напишите собственную версию программы, представленной в этом разделе.
Резюме
В этой главе рассматривались дополнительные операции ввода-вывода и четыре библиотечных типа: кортеж, набор битов, регулярные выражения и случайные числа.

