
- •1.2 Философские замечания
- •1.3 Процедурное программирование
- •1.4 Модульное программирование
- •1.5 Абстракция данных
- •1.6 Пределы абстракции данных
- •1.7 Объектно-ориентированное программирование
- •1.8 Концепции объектно-ориентированного программирования
- •1.8.1 Инкапсуляция
- •1.8.2 Полиморфизм
- •1.8.3 Наследование
- •1.10 Несколько полезных советов
- •2.2 Перегрузка функций
- •2.3 Перегрузка операторов
- •2.4 Наследование
- •2.5 Конструкторы и деструкторы
- •2.7 Два новых типа данных
- •Глава 3. Классы и объекты
- •3.1 Параметризованные конструкторы
- •3.2 Дружественные функции
- •3.3 Значения аргументов функции по умолчанию
- •3.3.1 Корректное использование аргументов по умолчанию
- •3.4 Взаимосвязь классов и структур
- •3.5 Связь объединений и классов
- •3.6 Анонимные объединения
- •3.7 Inline-функции
- •3.7.1 Создание inline-функций внутри класса
- •3.8 Передача объектов в функции
- •3.9 Возвращение объектов функциями
- •3.10 Присваивание объектов
- •3.11 Конструктор копирования
- •3.12 Массивы объектов
- •3.12.1 Инициализация массивов объектов
- •3.12.2 Создание инициализированных и неинициализированных массивов
- •3.13 Указатели на объекты
- •3.14 Статические члены класса
- •Глава 4. Перегрузка функций и операторов
- •4.1 Перегрузка конструкторов
- •4.2 Локализация переменных
- •4.3 Локализация создания объектов
- •4.4 Перегрузка функций и неопределенность
- •4.5 Определение адреса перегруженной функции
- •4.6 Указатель this
- •4.7 Перегрузка операторов
- •4.8 Дружественная функция-оператор
- •4.9 Ссылки
- •4.9.1 Параметры-ссылки
- •4.9.2 Передача ссылок на объекты
- •4.9.3 Возврат ссылок
- •4.9.4 Независимые ссылки
- •4.9.5 Использование ссылок для перегрузки унарных операторов
- •4.10 Перегрузка оператора []
- •4.11 Создание функций преобразования типов
- •Глава 5. Наследование, виртуальные функции и полиморфизм
- •5.1 Наследование и спецификаторы доступа
- •5.1.1 Спецификаторы доступа
- •5.1.2 Спецификатор доступа при наследовании базового класса
- •5.1.3 Дополнительная спецификация доступа при наследовании
- •5.2 Конструкторы и деструкторы производных классов
- •5.3 Множественное наследование
- •5.4 Передача параметров в базовый класс
- •5.5 Указатели и ссылки на производные типы
- •5.6 Ссылки на производные классы
- •5.7 Виртуальные функции
- •5.8 Для чего нужны виртуальные функции?
- •5.9 Чисто виртуальные функции и абстрактные типы
- •5.10 Виртуальный базовый класс
- •5.11 Раннее и позднее связывание
- •Глава 6. Подсистема динамического выделения памяти
- •6.1 Введение в обработку исключений
- •6.1.1 Перехват всех исключений
- •6.2 Работа с памятью с помощью new и delete
- •6.3 Размещение объектов
- •6.4 Перегрузка new u delete
- •7.1.1 Потоки
- •7.3 Создание собственных операторов вставки и извлечения
- •7.3.1 Создание операторов вставки
- •7.3.2 Перегрузка операторов извлечения
- •7.4 Форматирование ввода/вывода
- •7.4.1 Форматирование с помощью функций-членов класса ios
- •7.4.2 Использование манипуляторов
- •7.5 Создание собственных функций-манипуляторов
- •7.5.1 Создание манипуляторов без параметров
- •7.5.2 Создание манипуляторов с параметрами
- •7.6 Файловый ввод/вывод
- •7.6.1 Открытие и закрытие файлов
- •7.6.2 Чтение и запись в текстовые файлы
- •7.6.3 Двоичный ввод/вывод
- •7.6.4 Определение конца файла
- •7.6.5 Произвольный доступ
- •Глава 8. Ввод/вывод в массивы
- •8.1 Классы ввода/вывода в массивы
- •8.2 Создание потока вывода
- •8.3 Ввод из массива
- •8.4 Использование функций-членов класса ios
- •8.5 Потоки ввода/вывода в массивы
- •8.6 Произвольный доступ в массив
- •8.7 Использование динамических массивов
- •8.8 Манипуляторы и ввод/вывод в массив
- •8.9 Собственные операторы извлечения и вставки
- •8.10 Форматирование на основе массивов
- •Глава 9. Шаблоны и библиотека stl
- •9.1 Функции-шаблоны
- •9.2 Функции с двумя типами-шаблонами
- •9.3 Ограничения на функции-шаблоны
- •9.4 Классы-шаблоны
- •9.5 Пример с двумя типами-шаблонами
- •9.6 Обзор библиотеки stl
- •9.7 Класс vector
- •9.7 Класс string
- •9.8 Класс list
7.6 Файловый ввод/вывод
Для файлового ввода/вывода можно использовать систему ввода/вывода C++. Хотя конечный результат тот же самый, но подход C++ к файловому вводу/выводу отличается в некоторых моментах от стандарта ANSI языка С для системы ввода/вывода. По этой причине обратим особое внимание на данный раздел. Для выполнения файлового ввода/вывода в программу необходимо включить заголовочный файл fstream.h. Он определяет несколько важных классов и значений.
7.6.1 Открытие и закрытие файлов
В C++ файл открывается путем связывания его с потоком. Имеется три типа потоков: ввода, вывода и ввода/вывода. Для открытия потока ввода необходимо объявить поток как объект класса ifstream. Для открытия потока вывода необходимо объявить его как объект класса ofstream. Потоки, которые выполняют как ввод, так и вывод, должны быть объявлены как объекты класса fstream. Например, следующий фрагмент программы создает один поток ввода, один поток вывода и один поток, способный выполнять как ввод, так и вывод:
ifstream in; // ввод
ofstream out; // вывод
fstream both; // ввод и вывод
После создания потока единственным способом ассоциировать его с файлом является использование функции open(). Эта функция является членом каждого из трех классов потока. Она имеет следующий прототип:
void open(const char *filename, int mode, int access=filebuf::openprot);
Здесь filename является именем файла и может включать указание пути. Величина mode определяет, каким способом открывается файл. Mode может принимать одно или более из следующих значений, (определенных в заголовочном файле ios.h):
ios::app
ios::ate
ios::binary
ios::in
ios::nocreate
ios::noreplace
ios::out
ios::trunc
Можно комбинировать два и более из этих значений, используя побитовое ИЛИ.
ios::app указывает на то, что выводимые данные будут добавляться в конец файла. Это значение может быть использовано только для файлов, для которых возможен вывод. Использование ios::ate вызывает поиск конца файла в момент открытия файла.
ios::in задает возможность ввода из файла. ios::out указывает, что файл предназначен для вывода. Однако создание потока с использованием ifstream задает режим ввода, а создание потока с использованием ofstream задает режим вывода, и в этих случаях нет необходимости задавать указанные выше величины.
ios::nocreate задает такой режим, при котором функция open() может открыть только существующий файл. ios::noreplace нe позволяет функции open() открыть файл, если он уже существует, но не указаны атрибуты ios::ate или ios::app.
ios::trunc предусматривает уничтожение содержимого файла с заданным именем и усечение длины файла до нуля.
Режим ios::binary обусловливает открытие файла для двоичных операций. Это означает, что не будет никаких преобразований символов.
Величина access определяет, каким образом осуществляется доступ к файлу. Эта величина соответствует коду атрибута файла в системе DOS/Windows. Значения атрибута файлов определяются следующим образом:
Атрибут Значение
0 Обычный файл, отрытый доступ
1 Файл только для чтения
2 Скрытый файл
4 Системный файл
8 Архивный файл
С помощью операций побитового ИЛИ можно задать одновременно несколько атрибутов. Обычно эти атрибуты оставляются по умолчанию, что соответствует filebuf::openprot и соответствует нормальному файлу.
В следующем фрагменте открывается нормальный файл для вывода:
ofstream out;
out.open("test", ios::out, 0);
Тем не менее, практически никогда не бывает подобного вызова функции open(), поскольку два последних параметра имеют значения по умолчанию: для ifstream значением по умолчанию mode служит ios::in; а для ofstream значение по умолчанию равно ios::out. Параметр доступа access по умолчанию соответствует нормальному файлу, как это уже отмечалось выше. Поэтому предыдущая инструкция будет выглядеть следующим образом:
out.open("test"); // значения по умолчанию для вывода и обычного файла
Для того чтобы открыть поток одновременно для ввода и вывода, необходимо задать обе величины ios::in и ios::out для режима mode, как показано в следующем примере:
fstream mystream;
mystream.open("test", ios::in | ios::out);
Если функции open() не удается открыть поток, то поток остается равным NULL.
Хотя открытие файла с использованием функции open() является вполне допустимым, в большинстве случаев так не делается, потому что классы ifstream, ofstream и fstream содержат конструкторы, автоматически открывающие файл. Конструкторы имеют те же параметры и значения по умолчанию, что и функция open(). Поэтому наиболее типичный способ открытия файла выглядит следующим образом:
ifstream mystream("myfile"); // открытие файла для чтения
Если по каким-либо причинам файл не может быть открыт, значение ассоциированного потока будет равно NULL. Можно использовать следующий код для того, чтобы убедиться, что файл действительно открыт:
ifstream mystream("myfile");
if (!mystream) {
{
cout << "Cannot open file\n";
// обработка ошибки
}
Для того чтобы закрыть файл, следует использовать функцию-член close(). Например, чтобы закрыть файл, связанный с потоком mystream, используется следующая инструкция:
mystream.close();
Функция close() не имеет ни параметров, ни возвращаемого значения.