Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курс лекций по Программированию на С++.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
795.65 Кб
Скачать

Двунаправленный ввод/вывод

До сих пор мы рассматривали программы, в которых использовали только ifstream – класс входных файловых потоков (для чтения файла) и ofstream – класс выходных файловых потоков (для записи в файл). Хотя, как уже раннее говорилось, существует ещё fstream – класс двунаправленных файловых потоков. Двунаправленный файловый поток обеспечивает возможность считывать данные из файла и записывать данные в файл, ограничиваясь всего одним потоком и объектом. Использование класса двунаправленных файловых потоков освобождает нас от необходимости создания файловых объектов, предназначенных либо для ввода, либо для вывода. Таким образом, с помощью объекта класса fstream можно создать поток к файлу, который может быть использован как входной и выходной.

Создавать двунаправленные файловые потоки имеет смысл в том случае, когда в одной программе необходимо обеспечивать как считывание данных из файла, так и запись данных. Причём ввод/вывод может происходить хаотично или вследствие определённых событий или действий пользователя. Приведём пример, демонстрирующий создание двунаправленного файлового потока.

fstream file;

file.open("имя_файла", ios::out | ios::in | ios::binary);

file.write(…);

file.read(…);

Здесь, с помощью объекта file можно осуществлять как считывание данных из файла, так и запись данных в этот файл.

Функции стандартной библиотеки для работы с файлами или ввод/вывод в стиле с

Ввод/вывод в стиле С удобнее использовать при форматированном выводе в программах, не использующих объектно-ориентированную технологию. Представление о вводе/выводе в стиле С необходимо иметь по причине существования множества программ, написанных на С, с которыми программисту поневоле приходится сталкиваться.

Для использования функций ввода/вывода в стиле С необходимо подключать к программе заголовочный файл <stdio.h> или <cstdio>. Практически также как в случае с потоковыми классами С++, при вводе/выводе в стиле С данные рассматриваются как поток байтов. Работа с потоком начинается с его открытия. Поток можно открыть для чтения и/или записи в двоичном или текстовом режиме.

Функция открытия потока имеет формат: FILE* fopen(const char* имя_файла, const char* режим);. При неудачном открытии потока функция возвращает NULL. Первый параметр – имя открываемого файла в виде С-строки, второй – режим открытия файла:

"r" – файл открывается для чтения;

"w" – открывается пустой файл для записи (если файл существует, он стирается);

"а" – файл открывается для добавления информации в его конец;

"r+" – открыть для чтения и записи (файл должен существовать);

"w+" – открыть пустой файл для чтения и записи (если файл существует, он стирается);

"a+" – файл открывается для чтения и добавления информации в его конец.

Режим открытия может также содержать символы t (текстовый режим) или b (двоичный режим). По умолчанию файл открывается в текстовом режиме. Приведём пример открытия бинарного файла для чтения:

FILE *f=fopen("c:\\data", "rb+");

Здесь, указатель f используется для дальнейших операций с потоком. Его передают функциям ввода/вывода в качестве параметра.

Ввод/вывод в поток можно осуществлять различными способами: в виде последовательности байтов, в виде символов и строк или с использованием форматных преобразований. Операции ввода/вывода выполняются начиная с текущей позиции потока, определяемой положением указателя потока. Текущее положение указателя можно получить с помощью функций ftell и fgetpos и задать явным образом с помощью функций fseek и fsetpos.

Чтение и запись потока байтов выполняют функции fread и fwrite; чтение символа из потока – getc, fgetc; запись символа в поток – putc, fputc; чтение строки из потока – fgets; запись строки в поток – fputs; форматированный ввод из потока – fscanf; форматированный вывод в поток – fprintf; закрытие потока явным образом – fclose.

Приведём пример программы на языке С, которая создаёт файл numbers.txt и записывает в него 5 введённых пользователем целых чисел.

#include <stdio.h>

#include <conio.h>

#include <iostream.h>

using namespace std;

int main() {

const int K=5; //кол-во чисел

int n;

char fname[] = "c:\\os\\numbers.txt";

FILE *fout;

if((fout=fopen(fname, "wt"))==NULL) { //если при открытии текст. файла произ. ошибка

cout << "\nOshibka otkrytiya faila dlya zapisi!";

getch(); return 1;

}

for(int i=0; i<K; i++) {

cout << "Vvedite " << i+1 << "-e chislo: "; cin >> n;

fprintf(fout, "%i", n); //запись введённого числа в файл

fputc(' ', fout);

}

cout << "\n Chisla zapisany v fail!";

fclose(fout); //закрыть файловый поток

getch(); return 0;

}

А теперь рассмотрим программу, позволяющую считывать данные из созданного файла numbers.txt и вычислять среднее арифметическое значение считанных чисел.

#include <stdio.h>

#include <conio.h>

#include <iostream.h>

using namespace std;

int main() {

int n, k=0, sum=0; //число, кол-во чисел, сумма чисел

float sr;

char fname[] = "c:\\os\\numbers.txt";

FILE *fin;

if((fin=fopen(fname, "rt"))==NULL) {

cout << "\nOshibka otkrytiya faila dlya zapisi!";

getch(); return 1;

}

cout << "Fail sodergit: ";

while(!feof(fin)) { //пока не конец файла

fscanf(fin, "%i", &n); //считать число

cout << " " << n;

sum = sum + n;

k++;

} //в файле после последней цифры не должно быть пробела

fclose(fin);

sr=(float)sum/n;

cout << "\nSumma chisel = " << sum;

cout << "\nSrednee arifm. = " << sr;

getch(); return 0;

}

В заключение хотел бы ещё раз отметить, что при работе с файлами лучше стараться применять потоковые классы С++, которые обеспечивают более надёжную работу как со стандартными, так и с определёнными пользователем типами данных, а также единообразный и понятный синтаксис.