Файлы данных и функции ввода – вывода

Под файлом далее будем понимать поименованную часть памяти. В функциях, работающих с файлами, язык Си “рассматривает” файл как структуру. Эта структура описана в файле stdio.h. Наименование шаблона файла – FILE.

Поток – это файл данных или физическое устройство (принтер, дисплей и т.п.), с которым программист работает с помощью указателя на объект типа FILE. Так, функция, работающая с потоком данных, возвращает в качестве значения, значение указателя на объект типа FILE.

Открытие файла: fopen()

Фрагмент программы:

FILE *in;

in=fopen(“test.dat”,”r”);

Функцией fopen() управляют три основных параметра:

  1. Имя файла, который следует открыть (test.dat).
  2. Описание того, как должен использоваться файл
    • “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;

}



Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: