Работа с текстовыми файлами
Для работы с файлами в языке С++ имеется набор функций из библиотек stdio.h., cstdio.h. : fopen( ), fclose( ), fwrite ( ), fread ( ), рutc( ), getc() , fputs ( ), fgets(), fprintf(), fscanf(), fseek(), ftell() – см.ниже.
Открытие файла fopen().
Перед началом работы с файлом его следует открыть, с помощью функции открытия fopen(),с неё начинается работа с файлом.
Формат (синтаксис) функции открытия fopen():
FILE *fopen( const char *filename, const char *mode );
Здесь:
filename –первый параметр в виде С-строки, содержащей путь и имя файла;
mode – второй параметр в виде строки, определяющий режим открытия файла, а именно:
"r" - на чтение ( или открытие для чтения);
"w" - на запись (или открытие для записи),если файл существует - он стирается;
"r +" - для чтения и записи;
"w+" - для записи и чтения( если файл существует - он стирается);
"а" - для добавления информации в конец файла;
"а+" - для чтения и добавления информации в конец файла;
mode также может содержать символы : t-текстовый режим или b -двоичный режим. Эти режимы отличаются обработкой символов перехода на новую строку.
По умолчанию файл открывается в текстовом режиме.
FILE – специальный тип данных для работы с файлами (структура типа FILE).
Функция fopen() при успешном открытии файла возвращает указатель на FILE , а если файл не был успешно открыт – значение NULL (0).
Пример: FILE* fp=fopen(“my_file.txt”,”w”);
Указатель fp на FILE инициализируется функцией fopen() и используется в дальнейших операциях: его передают функциям ввода/вывода в качестве параметра.
Закрытие файла fclose(). Перед завершением программы открытый файл рекомендуется закрыть с помощью fclose() во избежание в нем потери данных.
Формат (синтаксис) функции открытия fclose():
fclose(FILE *fp);
Например:
fclose(fp);
fclose() принимает указатель на файл fp и возвращает значение 0 при успешном закрытии файла, иначе значение EOF.
Основной набор функций ввода/вывода
fread ( ) –чтение из файла(потока) блоками (порциями) количеством n по size байт;
Формат (синтаксис) функции чтения fread () :
fread (void *buf, size, n, fp);
n- количество считываемых блоков (порций),
Buf – буфер чтения,
Size – размер буфера в байтах.
fwrite (void *buf, size, n, fp) - запись в файл ;
int fgetc (FILE *fp ) - чтение символа из файла;
fрutc(int c, FILE *fp) - запись символа c в файл;
char *fgets (char *string, int n, FILE fp) - чтение не более n-1 символов из файла в string.
fputs (const char *string, FILE fp) - запись строки string в файл;
fscanf( ) – форматированный ввод (считывание) из потока(файла);
fprintf( fp, …) - форматированный вывод (запись) в поток (файла);
При вводе/выводе данные рассматриваются как поток ( последовательность ) байтов.
Физически поток представляет собой файл или устройство(клавиатуру, дисплей).
После открытия файла с ним связывается область памяти, называемая буфером.
При выводе или считывании вся информация направляется в буфер и накапливается там до заполнения буфера или до закрытия файла(потока).Чтение осуществляется блоками (порциями),равными размеру буфера или кратными количеству байтов. Буферизация позволяет более эффективно обмениваться информацией с внешними устройствами .
Функции setbuf, setvbuf позволяет управлять размерами и наличием буферов.
Задача 1. Создание (открытие и запись) простого текстового файла на языке C++ и запись текстовой информации в файл.
#include “stdafx.h”
#include <string.h>
#include <iostream>
#include <fstream>
using namespace std;
int main() { char str[100]; setlocale(LC_ALL,”Russian”);
cout<<”Введите предложение:”;
gets(str);
FILE* fp = fopen(“output.txt”,”w”); //открытие файла в режиме запись. if(fp != NULL) . { cout <<“Идет запись информации в файл…\n”; for(int i=0;i < strlen(str);i++) fputc(str[i],fp); // запись символов в файл } else cout << “Невозможно открыть файл на запись.\n”; fclose(fp); return 0; }
В данном примере задается специализированный указатель fp типа FILE, который инициализируется функцией fopen( ) и используется в дальнейших операциях: его передают функциям ввода/вывода в качестве параметра. Функция fopen() в качестве первого аргумента принимает строку, в которой задан путь и имя файла. Второй параметр- значение “w” определяет способ обработки файла и означает открытие файла на запись с удалением всей прежней информации из него. Если файл открыт успешно,то указатель fp не будет равен NULL и с ним возможна работа. В этом случае с помощью функции fputc() выполняется запись символов в файл, на который указывает указатель fp. .
Задача 2 Считывание текстовой информации из существующего файла. #include “stdafx.h”
#include <string.h>
#include <iostream>
using namespace std;
int main() { char str[100];
int i;
char ch; setlocale(LC_ALL,”Russian”);
FILE* fp = fopen(“my_file.txt”,”r”); //открытие файла для чтения if(fp != NULL) // Если файл открылся { i=0; // Пока не встретим “Конец файла”, читаем символ в ch while((ch = fgetc(fp)) != EOF) str[i++]=ch; str[i] = ‘\0’; // Символ “Конец строки” cout << str; } else cout << “Невозможно открыть файл на чтение.\n”; fclose(fp); return 0; }
В приведенном листинге функция fopen() открывает файл на чтение, что определяется значением второго аргумента равного «r». Это значит: в него невозможно произвести запись данных, а только считывание.
Сначала выполняется цикл while, в котором из файла считывается символ с помощью функции fgetc() и выполняется проверка: если считанное значение не равно символу конца файла EOF, то значение переменной ch записывается в массив str. Данный цикл будет выполняться до тех пор, пока не будут считаны все символы из файла, т.е. пока не будет достигнут символ EOF. Константа EOF -отрицательное целое число - сообщает об окончании файла.
После завершения цикла формируется строка str, которая выводится на экран. Перед завершением программы выполняется функция закрытия файла fclose().
Работа с текстовыми файлами через функции fputc и fgetc не эффективна, не всегда удобна. Например, если необходимо записать или считать строку целиком, то удобнее использовать функции fputs() и fgets() .
Использование функций fputs() и fgets().
Задача 3 Создаётся текстовый файл,в который записывается текстовая строка. Затем эта строка читается из файла и выводится на экран.
include “stdafx.h”
#include <string.h>
#include <iostream>
using namespace std; int main() { setlocale(LC_ALL,”Russian”);
char str[]=”Эта строка запишется в файл”; FILE* fp = fopen(“my_file.txt”,”w”); if(fp != NULL) fputs(str,fp); // Запись строки в файл else
{
cout << “Невозможно открыть файл на запись.\n”;
return 0;
} fclose(fp); fp = fopen(“my_file.txt”,”r”); if(fp != NULL) { fgets(str,sizeof(str),fp); // Чтение строки из файла cout << str; } fclose(fp); return 0; }
Задача4 Использование функций fprintf() и fscanf().
Имеется структура, хранящая информацию о книге: название, автор, год издания. Написать программу сохранения этой информации в текстовый файл и её считывания.
include “stdafx.h”
#include <string.h>
#include <iostream>
using namespace std; #define N 10 //Структура book содержит поля:name(название),author(автор),year(год изд-я) struct book { char name[100]; char author[100]; int year; } books[N]; // Массив структур books содержит данные о N книгах int main(void) { setlocale(LC_ALL,”Russian”);
cout<<”Введите данные о книгах :”;
for(int i=0;i < N;i++) { cout << “Название:”;
cin>>books[i].name;
cout<<”Автор”; cin>>books[i].author;
cout << “Год издания”; cin >> books[i].year; } for(i=0;i < N;i++) fprintf(fp,"%s %s %d\n",books[i].name,books[i].author,books[i].year); fclose(fp); // Чтение данных из файла и вывод на экран
fp = fopen("my_file.txt","r"); for(i=0;i < N;i++) fscanf(fp,"%s %s %d\n",books[i].name,books[i].author,&books[i].year); fclose(fp); cout<<”Информация о книгах:<<endl; for(i=0;i < N;i++) { cout <<books[i].name<<” ”; cout << books[i].author<<” “; cout << books[i].year<<endl; } return 0; }
В программе вводится информация по книгам в массив структур books и выводится введенная информация на экран. Затем открывается файл my_file.txt на запись, в который заносится информация по книгам в порядке: наименование, автор, год издания.
Т.к. число книг в данном случае равно 5 (#define N 5), то выходной файл будет иметь вид:
Onegin Pushkin 2007 Oblomov Griboedov 2010
Mciri Lermontov 2009
Faust Gete 2006
Chemodan Dovlatov 20011 Затем, файл my_file.txt открывается на чтение и с помощью функции fscanf() осуществляется считывание информации в элементы структуры. В заключении считанная информация выводится на экран монитора.
Представленный пример показывает возможность структурированной записи информации в файл и ее считывания. Это позволяет относительно просто сохранять разнородные данные в файле для их дальнейшего использования в программах.
Задача 5 Использование функций fseek() и ftell(). Пример считывания символов из файла в обратном порядке #include int main(void) { FILE* fp = fopen("my_file.txt","w"); if(fp != NULL) { fprintf(fp,"It is an example using fseek and ftell functions."); } fclose(fp); fp = fopen("my_file.txt","r"); if(fp != NULL) { char ch; fseek(fp,0L,SEEK_END); long length = ftell(fp); printf("length = %ld\n",length); for(int i = 1;i <= length;i++) { fseek(fp,-i,SEEK_END); ch = getc(fp); putchar(ch); } } fclose(fp); return 0; }
В примере сначала создается файл, в который записывается строка “It is an example using fseek and ftell functions.”. Затем этот файл открывается на чтение и с помощью функции fseek(fp,0L,SEEK_END) указатель позиции помещается в конец файла. Это достигается за счет установки флага SEEK_END, который перемещает позицию в конец файла при нулевом смещении. В результате функция ftell(fp) возвратит число символов в открытом файле. В цикле функция fseek(fp,-i,SEEK_END) смещает указатель позиции на –i символов относительно конца файла, после чего считывается символ функцией getc(), стоящий на i-й позиции с конца. Так как переменная i пробегает значения от 1 до length, то на экран будут выведены символы из файла в обратном порядке.
Задания:
Из входного текстового файла прочитать данные о книгах, имеющихся в библиотеке (название, автор, год издания, количество экземпляров). Вывести на экран количество книг по определённому автору ( фамилия автора задаётся с клавиатуры).
#include "stdafx.h"
#include <string.h>
#include <iostream>
using namespace std;
struct book
{
char name[30];
char author[30];