Работа с файлами.
С++ воспринимает ввод вывод как поток данных. Поэтому в С++ отсутствует понятие внутреннего файла, в отличие от Паскаль.
Функции для работы с файлами, которые содержаться в стнд. Библиотеки <stdio.h>
1) Необходимо объявить указатель на поток. (указатель файла)
FILE *Имя указателя;
FILE – это указатель типа, который содержится в библиотеки <stdio.h>
FILE *fp;
2) Открытие файла вызовом функции fopen:
Общий вид:
Имя указателя=fopen(имя внешнего файла, режим доступа);
Все параметры данной функции являются строками, поэтому записываются в “”
fp=fopen(“pr.txt”,”r”);
fp=fopen(“C:\\temp\\pr.txt”,”w”);
Режимы открытия потоков.
1) Открыть для чтения: r
При отсутствии файла функция возвращает NULL(нулевой указатель). Следовательно в программе должна быть проверка открытия файлов.
If (fp!=NULL)
{…}
Else puts(“файла не существует”);
2) Создать для записи: w
Если файла не существует, то он создаётся, если существует, то он перезапишется.
3) Открыть для добавления: a
Если файла нет, то он создается, если существует, то информация добавляется к исходному.
4) Открыть для чтения с последующей записью: r+
Если файла нет, то возвращается нулевой указатель(NULL), если существует, то информация записывается поверх существующей, начиная с первой позиции файла.
5) Для записи с последующим чтением: w+
Если файла нет, то он создаётся, если существует, то перезаписывается.
6) Открыть для добавления, или создать для чтения и записи: a+
Если файла нет, то он создается, если есть, то информация добавиться в конец файла.
Чтение из файла и запись в файл, осуществляется с помощью функции.
fprintf, fputs, fscanf, fgets и т.д.
1) Запись данных в файл(формирование на диске текстового файла).
fprintf(Имя указателя на файл, форматная строка, список переменных);
fprintf(fp,”x1=%d\tx2=%.2f”, x1,x2);
fprintf(fp,”%d”,x);
2) Чтение данных из файла.
fscanf(имя указателя на файл, форматная строка, список адресов переменных);
fscanf(fp,”%d”,&x);
fscanf(fp,”%d%f”,&x1,&x2);
3) Закрытие файла.
fclose(имя указателя на файл);
fclose(fp);
Пример: Составить программу вывода в файл, и рассчета таблицы квадратных корней для чисел от 1 до 10.
…
main()
{ FILE *p;
p=fopen(“test.txt”, “w”);
int i;
for (i=1;i<=10;i++)
{ fprintf(p, “%d\t %.2f\n”, i,sqrt(float(i)));
}
fclose(p);
return 0;
}
Пример: Составить программу, которая результат предыдущей программы будет считывать в массивы x,y и выводить значения массивов на экран.
…
main()
{ FILE *f;
f=fopen(“test.txt”,”r”);
int i,x[10];
float y[10];
for (i=1;i<=10;i++)
{ fscanf (f, “%d %f”,&x[i],&y[i]);
printf(“%d\t%f”, x[i],y[i]);
}
fclose(f);
return 0;
}
Существуют 2 типа файлов:
-текстовые
-двоичные
Текстовыми называют файлы состоящие из любых символов, которые отформатированы по строкам.
Двоичные файлы – это последовательная структура данных, после открытия файла доступен первый байт, хранящиеся в нем данные можно последовательно считывать и записывать.
При записи информации в текстовый файл все данные преобразуются к символьному типу, и хранятся в символьном виде. При чтении происходит автоматическое преобразование информации к нужному типу данных. При работе с двоичным файлом никаких преобразование не происходит вся информация в двоичном файле записывается в виде последовательности байт.
Работа с двоичными файлами:
1) Создаем указатель: FILE *имя указателя;
2) Устанавливаем связь с внешним файлом: Имя указателя = fopen(“путь”,”…b”);
При написании режимов доступа для двоичных файлов добавляется буква b.
Например: wb, rd, wd+
3) Запись информации в файл: fwrite(указатель на адрес данных записанных в файл, длина в байтах одной единицы записи(блоками), число элементов(блоков), имя указателя);
fwrite(&x,sizeof(int),1,fp);
4) Чтение необходимой информации из файла: fread(указатель на адрес данных, размер блока, число блоков, имя указателя);
5) Закрытие файла: fclose(имя указателя);
При считывании информации нужно следить за тем достигнут ли конец файла. Функция feof(имя указателя) возвращает не нулевое значение, если не достигнут конец файла, и нулевое если достигнут. Для использования удобно применить цикл while
while(!feof(fp))
{ //считываем из файла
}
Задание 1: Создать двоичный файл и записать в него целое число n, и n – вещественных чисел.
…
main()
{ FILE *prim;
int i,n;
float a;
fp=fopen(“C:\\temp\\abc.dat”,”wb”);
cout<<”n=”;
cin>>n;
fwrite(&n,sizeof(int),1,fp);
for (i=0;i<n;i++)
{cout<<”a”<<i<<”=”;
cin>>a;
frite(&a,sizeof(float),1,fp);
}
fclose(fp);
return 0;
}
Задание 2: Вывести на экран содержимое файла из задания 1.
…
main()
{FILE *fp;
int i,n;
float *a;
fp=fopen(“C:\\temp\\abc.dat”,”rb”);
fread(&n,sizeof(int),1,fp);
cout<<”n=”<<n;
a=new float[n];
fread(a,sizeof(float),n,fp);
for (i=0;i<n;i++);
cout<<”a[“<<i+1<<”]=”<<a[i]<<endl;
delete[] a;
fclose(fp);
return 0;
}
Т.к. двоичные файлы это последовательная структура файлов, удобно использовать ф-ю fseek, которая осуществляет перемещение указателя файла к заданному байту.
Общий вид:
fseek(имя указателя, смещение, начало отсчета);
Смещение – это целое число, указывающее количество байт на которое будет происходить смещение указателя. Может быть положительным или отрицательным, если + то смещение вперед, если – то смещение назад.
Точка отсчета:
0 – начало файла
1 – от текущей позиции
2 – от конца файла
Если функция выполнилась без ошибок, т.е. смещение произошло, возвращается значение 0.
Например:
fseek(fp,3,0); //смещение на 3 байта вперед от начала файла.
fseek(fp,0,0); //установка на начало файла.
Задание 3: В созданном файлу из задания 1 поменять местами наибольшее и наименьшее из вещественных чисел, т.е. дописать программу из задания 2.
…
main()
{FILE *fp;
int i,n;
float *a;
fp=fopen(“C:\\temp\\abc.dat”,”rb”);
fread(&n,sizeof(int),1,fp);
cout<<”n=”<<n;
a=new float[n];
fread(a,sizeof(float),n,fp);
for (i=0;i<n;i++);
cout<<”a[“<<i+1<<”]=”<<a[i]<<endl;
float min,max;
int nmin,nmax;
min=a[0];
max=a[0];
for (i=0;i<n;i++)
{
if (a[i]<min) {min=a[i];
min=i;
}
If (a[i]>max) {max=a[i];
min=i;
}
}
fseek(fp,sizeof(int)+nmax*sizeof(float),0);
fwrite(&min,sizeof(float),1,fp);
fseek(fp,sizeof(int)+nmin*sizeof(float),0);
fwrite(&nmax,sizeof(float),1,fp);
delete[] a;
fclose(fp);
return 0;
}
Операторы потоков для работы с текстовыми файлами в С++
1) Подключить библиотеку #include <fsstream>
usingnamespace std;
2) Создание объектов с определением для них имен.
a) Для чтения из файлов
Ifstream имя(имя внешнего файла);
Например:
if stream inf(“test.txt”);
b) Для записи
ofstream имя(имя внешнего файла);
ofstream outf(“test.txt”);
3) Работа с потоками
Например: для записи данных в файл
outf<<данные;
Например: для чтения данных из файла
inf>>переменная;
Задание: Что будет на экране в результате выполнения следующих команд:
…
main()
{ ofstream out(“test.txt”);
out<<”1 2 3 4”;
return 0;
}
На экран информация не выводится, создается файл, в котором числа разделены пробелом.
…
main()
{char S[80];
ifstream out(“test.txt”);
while (inf)
{ inf>>S;
cout<<S<<endl;
}
return 0;
}
На экран выводиться столбец из чисел 1,2,3,4.
Вывод: Вся информация в файле храниться в том же формате как если бы она была выведена н экран, следовательно файл созданный с помощью оператора < < является отформатированным файлом, т.е. текстовым. Любой файл, который считывается с помощью оператора >> должен содержать отформатированный текст, следовательно должен быть текстовым. При работе с потоками вывода в файл, вывод осуществляется через буфер, поэтому правильно прочитать новое содержимое файла можно только после инструкции закрытия потока. Это можно сделать 2 способами:
out<<flush или out.close();
Д/З: Практическая. Работа с файлами.
Цель: сформировать навыки создания работы с файлами средствами языка C/C++
1) Напишите программу, которая создает файл и записывает в него 5 введенных пользователем целых чисел. Причем каждое число должно находиться в отдельной строке.
2) Напишите программу, которая дописывает в файл из 1 программы 5 целых чисел полученных с помощью датчика случайных чисел. Вывести на экран содержимое файла.
3) Написать программу, которая в файле из 2 задания находит наибольшее и наименьшее значение и вычисляет среднее арифметическое чисел в файле.
Задача 1-3 без потоков, а потом задачу 3 через потоки.