Под файлом далее будем понимать поименованную часть памяти. В функциях, работающих с файлами, язык Си “рассматривает” файл как структуру. Эта структура описана в файле stdio.h. Наименование шаблона файла – FILE.
Поток – это файл данных или физическое устройство (принтер, дисплей и т.п.), с которым программист работает с помощью указателя на объект типа FILE. Так, функция, работающая с потоком данных, возвращает в качестве значения, значение указателя на объект типа FILE.
Открытие файла: fopen()
Фрагмент программы:
FILE *in;
in=fopen(“test.dat”,”r”);
Функцией fopen() управляют три основных параметра:
- Имя файла, который следует открыть (test.dat).
- Описание того, как должен использоваться файл
- “r” – чтение существующего файла;
- “w’ – запись;
- “a” – добавление в конец файла (если файла нет, он создается);
- “r+” – чтение и запись в файл (файл должен существовать);
- “w+” – чтение и запись в файл (если файл уже существует, то его содержимое уничтожается);
- “a+” – чтение и добавление в файл.
Кроме этого различают еще текстовый (t) и двоичный (b) потоки. Если при открытии файла не указан тип потока, то по умолчанию файл обрабатывается системой как текстовый файл.
|
|
3. Указатель на файл (in). Его значение возвращается функцией и с этого момента программа ссылается на файл при помощи указателя, а не по имени файла.
Закрытие файла: fclose()
Пример:
fclose(in);
Аргументом функции является указатель на файл, а не имя файла. Функция возвращает 0, если файл закрыт успешно, и -1 в противном случае.
Ввод и вывод символа из файла: getc(), putc()
Пример:
ch=getc(in); /* ввод символа */
putc(ch,out); /* вывод символа */
Пример:/* Иллюстрация работы функций fopen(), fclose() */
#include <stdio.h>
#include <string.h>
#include <windows.h>
void main(int argc,char *argv[])
{
char cStr1[]="Необходимо имя файла \n";
char cStr2[]="Невозможно открыть файл";
FILE *in,*out;
int ch;
char name[20];
int count=0;
CharToOem(cStr1,cStr1);
CharToOem(cStr2,cStr2);
if (argc<2)
printf("%sn",cStr1);
else
{
if ((in = fopen(argv[1],"r"))!= NULL)
{
strcpy(name,argv[1]);
strcat(name,".red");
out=fopen(name,"w");
while((ch=getc(in))!=EOF)
if (count++ %3 == 0)
putc(ch,out);
fclose(in);
fclose(out);
}
else
printf("%s %s\n",cStr2,argv[1]);
}
}
Замечание: Необходимо иметь текстовый файл, имя которого задается при запуске программы на выполнение. Содержимое файла в примере: “Даже Эдди нас опередил с детским хором”. В результате выполнения программы появляется новый файл с текстом:”Дед спел тихо”.
Функции ввода и вывода данных из файла: fscanf(), fprintf().
Эти две функции работают также как и функции printf(), scanf(), но не со стандартными устройствами ввода и вывода, а с файлами. При работе с этими функциями необходим еще один дополнительный аргумент – указатель на файл.
Пример:/* Нахождение выборочного мат. ожидания, стандартного отклонения, коэффициента корреляции, значений однофакторной линейной регрессии. Данные хранятся в файле dat.txt, результаты выполнения программы записываются в файл dat1.txt */
|
|
#include <stdio.h>
#include <math.h>
#include <windows.h>
void main()
{
FILE *in,*out;
int i,n;
char cStr0[]="Введите объем выборки: ";
CharToOem(cStr0,cStr0);
printf("%s",cStr0);
scanf("%d",&n);
float *x,*y,*yr;
x=new float[n];
y=new float[n];
yr=new float[n];
float mo1=0.0,mo2=0.0,sr1=0.0,sr2=0.0,r=0.0;
char cStr[]="Ошибка открытия файла!!!";
CharToOem(cStr,cStr);
if ((in=fopen("dat.txt","r"))!=NULL)
{ for(i=0;i<n;i++)
fscanf(in,"%f",&x[i]);
for(i=0;i<n;i++)
fscanf(in,"%f",&y[i]);
for(i=0;i<n;i++)
{
mo1+=x[i];
mo2+=y[i];
}
mo1/=n;
mo2/=n;
for(i=0;i<n;i++)
{ sr1+=(x[i]-mo1)*(x[i]-mo1);
sr2+=(y[i]-mo2)*(y[i]-mo2);}
sr1/=n;
sr2/=n;
for(i=0;i<n;i++)
r+=(x[i]-mo1)*(y[i]-mo2);
sr1=sqrt(sr1);
sr2=sqrt(sr2);
r/=(n*(sr1*sr2));
for(i=0;i<n;i++)
yr[i]=mo2+(sr2/sr1)*r*(x[i]-mo1);
out=fopen("dat1.txt","w");
fprintf(out,"M1=%6.2f M2=%6.2f Sr1=%6.2f Sr2=%6.2f R=%6.2f\n\n x:",mo1,mo2,sr1,sr2,r);
for(i=0;i<n;i++)
fprintf(out,"%6.2f ",x[i]);
fprintf(out,"\n y:");
for(i=0;i<n;i++)
fprintf(out,"%6.2f ",y[i]);
fprintf(out,"\nyr:");
for(i=0;i<n;i++)
fprintf(out,"%6.2f ",yr[i]);
fprintf(out,"\n");
fclose(in);
fclose(out);
}
else
printf("%s\n",cStr);
}
Пусть x – рост, y – вес, представленные выборочными значениями. Пусть в файле dat.txt хранятся выборки объемом n=10 для роста и веса соответственно:
155 170 175 182 177 183 169 180 177 168
59 74 80 87 83 90 75 94 85 77.
Тогда реультаты выполнения программы (фай dat1.txt):
M1 =173.60 M2 = 80.40 Sr1 = 7.98 Sr2 = 9.43 R = 0.96
x:155.00 170.00 175.00 182.00 177.00 183.00 169.00 180.00 177.00 168.00
y: 59.00 74.00 80.00 87.00 83.00 90.00 75.00 94.00 85.00 77.00
yr: 59.31 76.32 81.99 89.92 84.26 91.06 75.18 87.66 84.26 74.05
Функция произвольного доступа: fseek().
Эта функция позволяет обрабатывать файл подобно массиву и непосредственно достигать любого определенного байта в файле, открытом функцией fopen().
Функция fseek() имеет три аргумента и возвращает значение типа int.
Первый аргумент – это указатель типа FILE на файл, в котором ведется поиск. Файл следует открыть функцией fopen().
Второй аргумент показывает, как далеко следует передвинуться от начальной точки. Он имеет тип long и может принимать положительное (движение вперед) и отрицательное (движение назад) значение.
Третий аргумент является кодом, определяющим начальную точку:
Код | Положение в файле |
начало файла | |
текущая позиция | |
конец файла |
Функция fseek() возвращает 0, если все прошло хорошо, и -1, если есть ошибка (например, перемещение за границу файла).
Пример: /* Печать содержимого файла с заданного места до конца в другой файл */
#include <stdio.h >
#include <windows.h>
void main(int argc, char *argv[])
{
FILE *in, *out;
long num=20L;
char cStr1[]=”Нет файла в качестве аргумента ”;
char cStr2[]=”Не открыть файл ”;
CharToOem(cStr1,cStr1);
CharToOem(cStr2,cStr2);
if (argc<2)
printf(“%s\n”,cStr1);
else
{
if((in=fopen(argv[1],”r”))==0)
printf(“%s\n”,cStr2);
else
{
out=fopen("data1.txt","w");
fseek(in,num,0);
while(!feof(in))
fprintf(out,"%c",fgetc(in));
fclose(in);
fclose(out);
}
}
}
Приложение:
// Нахождение обратной матрицы
#include<stdio.h>
#include<windows.h>
#include<math.h>
#define n 3
float Det(float[][n]);
float Det1(float[][n-1]);
void main()
{
float a[n][n],d[n][n],det_a,b1[n-1][n],b2[n-1][n-1],a1[n][n],a2[n][n], a3[n][n];
int i,j,i2,j4;
char cStr[]="Введите матрицу n на n";
CharToOem(cStr,cStr);
printf("%s\n",cStr);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%f",&a[i][j]); //ввод матрицы
for(i=0;i<n;i++)
for(j=0;j<n;j++)
d[i][j]=a[i][j];
det_a=Det(d); // определитель матрицы системы
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
for(int i1=0;i1<n;i1++)
{
if (i1!=i)
{
for(int j2=0;j2<n;j2++)
{
if (i1>i) i2=i1-1;
else
i2=i1;
b1[i2][j2]=a[i1][j2];
}
}
}
for(int j3=0; j3<n;j3++)
{
if(j3!=j)
{
for(int i4=0;i4<n-1;i4++)
{
if(j3>j) j4=j3-1;
else
j4=j3;
b2[i4][j4]=b1[i4][j3];
}
}
}
// Вывод результатов
for(int i5=0;i5<n-1;i5++)
for(int j5=0;j5<n-1;j5++)
a1[i][j]=Det1(b2);
int st=pow(-1,i+j);
a1[i][j]*=st;
}
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
a2[j][i]=a1[i][j]/det_a;
printf("a2[%d][%d]=%f\n",j,i,a2[j][i]);
}
//Проверка
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
a3[i][j]=0;
for(int k=0;k<n;k++)
a3[i][j]+=a[i][k]*a2[k][j];
}
for(i=0;i<n;i++)
for(j=0;j<n;j++)
printf("a3[%d][%d]=%f\n",i,j,a3[i][j]);
}
// Функция нахождения определителя
float Det(float c[][n])
{
int i1,j1,k1;
float koef,det=1.0;
|
|
for(i1=0;i1<n;i1++){ //идем по строкам
for(j1=i1+1;j1<n;j1++){ // по столбцам
koef=c[j1][i1]/c[i1][i1];
for(k1=i1;k1<n;k1++) //по столбцам
c[j1][k1]-=c[i1][k1]*koef;}}
for(i1=0;i1<n;i1++)
det*=c[i1][i1];
return det;
}
float Det1(float c[][n-1])
{
int i1,j1,k1;
float koef,det=1.0;
for(i1=0;i1<n-1;i1++){
for(j1=i1+1;j1<n-1;j1++){
koef=c[j1][i1]/c[i1][i1];
for(k1=i1;k1<n-1;k1++)
c[j1][k1]-=c[i1][k1]*koef;}}
for(i1=0;i1<n-1;i1++)
det*=c[i1][i1];
return det;
}
// Работа с двумерными динамическими массивами
#include<stdio.h>
int main()
{
int i,j,i1,m,n,k;
char cStr1[]="Число строк матрицы А:\n";
char cStr2[]="Число столбцов матрицы А:\n";
char cStr3[]="Число столбцов матрицы В:\n";
CharToOem(cStr1,cStr1);
CharToOem(cStr2,cStr2);
CharToOem(cStr3,cStr3);
printf(cStr1); //число строк матрицы А
scanf("%d",&m);
printf(cStr2); // число столбцов матрицы А
scanf("%d",&n);
printf(cStr3); // число столбцов матрицы B
scanf("%d",&k);
float **A, **B,**C;
A=new float *[m]; // Массив из адресов строк матрицы А
B=new float *[n]; // Массив из адресов строк матрицы В
C=new float *[m]; // Массив из адресов строк матрицы С
for(i=0;i<m;i++)
{
A[i]=new float [n];
C[i]=new float [k];
}
for(i=0;i<n;i++)
{
B[i]=new float [k];
}
for(i=0;i<m;i++)
for(j=0;j<n;j++)
A[i][j]=(float)(i+j);
for(i=0;i<n;i++)
for(j=0;j<k;j++)
B[i][j]=(float)(i+j);
for(i=0;i<m;i++)
for(j=0;j<k;j++)
{
C[i][j]=0;
for(i1=0;i1<n;i1++)
C[i][j]+=A[i][i1]*B[i1][j];
}
for(i=0;i<m;i++){
for(j=0;j<k;j++){
printf("C[%d][%d]=%5.2f\t",i,j,C[i][j]);
}
printf("\n");
}
// Проверка адресов
for (i=0; i<m;i++)
printf("A[%d]=%p\t&A[%d][0]=%p\n",i,A[i],i,&A[i][0]);
return 0;
}