Порядок выполнения лабораторной работы
1. Изучить теоретические сведения. Разобрать представленные примеры. Запустить первые четыре примера.
2. Получить вариант индивидуального задания у преподавателя. Предполается реализация двух задач разными способами: первый способ для первой задачи – использовать стандартные потоковые классы для решения задачи, второй способ для второй задачи – перегрузить операторы << и >> для работы со стандартными потоковыми классами.
3. Реализовать полученные задания. Для выбора решения задачи пользователем реализовать меню. Любое общение с пользователем должно сопровождаться поясняющимся текстом. Также в программе должно быть реализовано минимум 2 исключительных ситуации. Исключительные ситуации должны обрабатываться в отдельном классе. Обязательна оконная (формочная) реализация программы с использованием элементов управления.
4. Показать результат работы программы преподавателю.
5. Защитить лабораторную работу.
Требования к отчету
|
|
Отчет должен содержать:
1. Цель работы.
2. Задание.
3. Словесное описание исключительных ситуаций.
4. UML диаграмма классов.
5. Блок-схема программы.
6. Текст программы на языке C++ с комментариями.
7. Тесты (копии выходных форм программы/сформированных файлов).
8. Выводы.
Теоретические сведения
Потоковый ввод/вывод дисковых файлов
Для работы с дисковыми файлами необходимо подключение заголовочного файла <fstream>, содержащего наборы специальных классов:
- ifstream — для ввода,
- ofstream — для вывода,
- fstream — для чтения и записи данных в один и тот же файл.
Чтобы получить возможность работать с дисковым файлом, нужно открыть его с указанием режима доступа, который определяется значением константы open-mode класса ios.
Режим доступа | Стандарт | Действие |
app | нет | открывает файл для дозаписи |
ate(atend) | да | при открытии файла устанавливает файловый указатель на конец файла |
binary(bin) | да | открыть файл в двоичном представлении |
in | да | открыть файл для чтения (ввода) |
nocreate | нет | если файл не существует, то новый файл не создается |
noreplace | нет | если файл уже существует, файл не перезаписывается |
out | да | открыть файл для записи (вывода) |
trunc | нет | Открывает и усекает существующий файл. Новая информация замещает существующую |
Текстовые файлы
Создание и запись.
Для создания текстового файла определяют объект класса ofstream и передают конструктору класса имя дискового файла в качестве первого параметра и режим доступа в качестве второго параметра:
ofstream out_file(“Out.txt”, ios::out);
Можно объявить константу, определяющую режим открытия файла, например:
|
|
const ios::open_mode=ios::out | ios::app;
После того, как предпринималась попытка открыть файл, следует убедиться в том, что файл открыт и готов для записи (или перезаписи):
if (! out_file) { cerr<<”Error: unable to write to out.txt”<<endl;
exit(1);
}
Все сказанное верно и для файлов, открываемых для чтения (или входных файлов):
ifstream in_file(“Input.txt”, ios::in);
if (! in_file) { cerr<<”Error: unable to open Input.txt”<<endl;
exit(1);
}
При работе с текстовыми файлами наиболее часто встречаются четыре действия:
- посимвольное чтение - посимвольная запись | - построчное чтение - построчная запись |
Посимвольное чтение текста.
Функция get(), которая является методом istream, применяется для посимвольного чтения текстового файла.
Пример 1. Посимвольное чтение файла и вывод его на экран.
# include <fstream>
# include <iostream>
using namespace std;
int main()
{
setlocale(LC_ALL, "RUS");
char sym;
ifstream in_file("Input_file.txt", ios::in);
if (!in_file) {
cerr << "Error input file" << endl;
exit(1);
}
while (in_file) {
in_file.get(sym);
cout << sym;
}
cout << endl;
system("pause");
return 0;
}
Посимвольная запись текста.
Функция put(), которая является методом ostream, позволяет осуществлять посимвольную запись данных в текстовый файл.
Пример 2.
# include <fstream>
# include <iostream>
# include <string>
using namespace std;
void main()
{
setlocale(LC_ALL, "RUS");
string guote = "Зорко одно лишь сердце.Самого главного глазами не увидишь.А.де Сент Экзюпери";
ofstream out_file("Out_file.txt", ios::out);
if (!out_file)
{
cerr << "Error output file" << endl;
exit(1);
}
for (int i = 0; i<guote.size(); i++)
out_file.put(guote[i]);
cout << "Конец записи" << endl;
system("pause");
}
Построчное чтение файла.
Обычно построчное чтение и запись файлов работают быстрее посимвольных действий. Для чтения строки из файла воспользуемся функцией getline(), которая является методом класса ifstream. Функция читает строку (в том числе и разделители), пока не встретит символ новой строки ‘\n’, помещая ее в буфер (первый аргумент функции). Максимальный размер буфера задается как второй аргумент функции.
Пример 3.
# include <fstream>
# include <iostream>
using namespace std;
void main()
{
setlocale(LC_ALL, "RUS");
const int LEN = 80;
char BUF[LEN];
ifstream in_file("Input_file.txt", ios::in);
if (!in_file)
{
cerr << "Error input file" << endl;
exit(1);
}
while (in_file) {
in_file.getline(BUF, LEN);
cout << BUF << endl;
}
system("pause");
}
Построчная запись текста.
Пример 4.
# include <fstream>
# include <iostream>
# include <string>
using namespace std;
void main()
{
setlocale(LC_ALL, "RUS");
ofstream out_file("Out_file.txt", ios::out);
if (!out_file) {
cerr << "Error output file" << endl;
exit(1);
}
out_file << "Я не знаю, где встретиться\n";
out_file << "Нам придется с тобой, \n";
out_file << "Глобус крутится - вертится, \n";
out_file << "Словно шар голубой\n";
cout << "Файл записан" << endl;
system("pause");
}
Записываемые строки являются не объектами класса string, а строками типа *char, завершающимися символом ‘\n’.
Признак конца файла
Признак конца файла приходится искать в файлах, открытых для чтения. Этот признак устанавливается в тот момент, когда в файле не осталось больше данных, которые можно считать.
Признак конца файла анализируется в выражении вида
while (! In_file.eof()) { … }
Для этой цели нельзя пользоваться циклом
do { … } while (! In_file.eof()), поскольку файл может оказаться пустым.
Однако проверка на конец файла не анализирует ошибки, которые могут встретиться в процессе чтения файла.
Для проверки как конца файла, так и наличия ошибок при его чтении пользуются условием выхода из цикла:
while (In_file.good()) { … }
Оператор цикла
while (In_file) { … }
выполняется до тех пор, пока нет ошибок, в том числе и конца файла (EOF).
Имена файлов и аргументы командной строки
|
|
В приведенных выше примерах были использованы файлы с фиксированными именами. Однако более удобны программы, в которых имена файлов для чтения или записи можно ввести с клавиатуры или задать в качестве аргументов командной строки.
Пример 5.
# include <fstream>
# include <iostream>
# include <stdlib.h>
using namespace std;
int main(int argc, char *argv[])
{
char I;
char c;
if (argc <= 1)
{
cout << "usage: primer.exe filename1 [filename2]" << endl;
system("pause");
return 1;
}
ifstream file;
for (I = 1; I <= argc - 1; I++)
{
file.open(argv[I]);
if (!file.is_open())
{
cout << "Bad file" << endl;
system("pause");
return 1;
};
cout << "file " << argv[I] << endl;
while (file)
{
c = file.get();
cout << c;
};
file.close();
}
cout << endl;
system("pause");
return 0;
}
Для работы с файловыми потоками любого из стандартных типов, нужно перегрузить операторы ввода и вывода под требуемый тип данных или воспользоваться шаблоном класса, задаваемым с помощью ключевого слова template.
Пример 6.
Файл myclass.h
#include <iostream>
using namespace std;
class myclass
{
public:
int x;
float y;
friend ostream& operator << (ostream& out, myclass& m);
friend istream& operator >> (istream& out, myclass& m);
myclass(int x_in, float y_in);
myclass(void);
};
Файл myclass.cpp
#include "myclass.h"
myclass::myclass(int x_in, float y_in)
{
x = x_in;
y = y_in;
}
myclass::myclass(void)
{
x = 0;
y = 0.0;
}
ostream& operator << (ostream& out, myclass& m)
{
out << m.x << ' ' << m.y << endl;
return out;
}
istream& operator >> (istream& in, myclass& m)
{
cout << "Введите X: ";
in >> m.x;
cout << "Введите Y: ";
in >> m.y;
return in;
}
Главный модуль
#include "myclass.h"
int _tmain(int argc, _TCHAR* argv[])
{
setlocale(LC_ALL, "RUS");
myclass m1(5, 6.3);
cout << "m1: " << m1;
myclass m2;
cout << "m2: " << m2;
cout << "Введиту m2:" << endl;
cin >> m2;
cout << "m2: " << m2;
myclass m3 (3, 6.9);
cout << "m3: " << m3;
cout << "Введиту m3:" << endl;
cin >> m3;
|
|
cout << "m3: " << m3;
system("pause");
return 0;
}
Контрольные вопросы
1) Что такое поток?
2) Что представляет собой файловый указатель?
3) Перечислить режимы доступа к файлу.
4) Как открыть и как закрыть файл?