Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛекцииЛаб(Часть_2_Книги).doc
Скачиваний:
4
Добавлен:
03.05.2019
Размер:
988.16 Кб
Скачать

4.2. Замена записи. Функции ftell, fgetpos, fsetpos, rewind.

В предыдущий проект (п. 4.1) добавим ещё одну функцию, которая в файле одномерных массивов меняет массив с номером nChange. Замена выполняется в следующей последовательности:

void MyChange(int nChange)

{

// nChange — номер массива (записи), который меняем

// 1) Открываем в режиме "rb+".

arf= fopen("d:\\ANA\\cpp\\2004_05\\farr2.dat ", "rb+");

// 2) Переходим на начало массива с номером nChange

fseek(arf, (nChange-1) * sizeof(a), 0 );

/* 3) Запоминаем номер первого байта начала массива c номером nChange Нумерация байт с начала файла */

long p; p=ftell(arf); // or fgetpos(arf,&p);

cout<<endl<<"p="<<p<<endl; // p=20, если nChange=2

// 4) Читаем массив c номером nChange в оперативную память

fread(a, sizeof(a), 1, arf ) ;

printf("\n Массив, который будем менять");

/* 5) Выводим прочитанный массив и меняем его по заданному алгоритму */

for(j=0;j<m;j++)

{ printf("%d ",a[j]);

a[j]=a[j]*10;

}

/* 6) После выполнения функции fread указатель чтения-записи переместился “вперёд” к концу файла на один массив, т. е. на начало следующего массива с номером nChange+1. Поэтому устанавливаем позицию указателя чтения-записи на начало того же уже прочитанного массива c номером nChange, чтобы на это место записать изменённый массив. В нашем примере для наглядности при выводе каждый элемент увеличили в 10 раз.*/

fsetpos(arf,&p);

/* 7) На место старого массива записываем новый, изменённый массив. */

fwrite(a,sizeof(a),1, arf);

/* Запоминаем номер первого байта массива, следующего после изменённого, т.е. 40, если. nChange=2 Заметим, что в этом простом примере это можно не делать.*/

fgetpos(arf,&p); // или p=ftell(arf);

// Переходим на начало файла для дальнейшего его чтения

rewind(arf);

fread(a,sizeof(a),1,lf);

while (!feof(lf))

{ printf("\n"); for(j=0;j<m;j++) printf("%d ",a[j]);

fread(a,sizeof(a),1,lf);

}

/* Чтение файла, а, значит, и переход в его начало можно здесь опустить, так как в предыдущем пункте 4.1 была составлена функция для чтения. Её можно вызвать при необходимости. */

fclose(lf);

}

Пример. В файл записать координаты точек плоскости. Найти две (любые) точки с наибольшим расстоянием между ними. Массив для хранения координат всех точек не использовать.

struct TPoint {

float x,y;

} Point;

FILE *fP;

// Вычисление расстояния между двумя точками

float MyDist(TPoint p1, TPoint p2)

{ return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));

}

// Создание файла

void MyCREATE()

{ clrscr(); int k=0;

if((fP=fopen ("d:\\ana\\cpp\\C++Lections2semestr\\files\\fPoints.dat","wb"))==NULL)

{ printf("Error\n");

return ;

}

else printf("File was opened for creating\n");

cout<<"x=1000 -- exit\n";

do {

printf("x="); scanf ("%f",&Point.x);

if (Point.x==1000) break;

printf("y="); scanf("%f", &Point.y);

fwrite(&Point,sizeof(Point),1,fP);

k++; // Счётчик количества точек

}

while (1);

printf("\n Writed %3d records\n",k);

fclose(fP);

}

/* Просмотр файла. Кроме этого, функция находит количество точек, координаты которых записаны в файле. Это количество затем будет передано в функцию поиска MyFind. Поэтому функцию MyRead надо выполнить (вызвать) перед MyFind. */

long MyREAD()

{ int n=0; clrscr();

if ((fP=fopen

("d:\\ana\\cpp\\C++Lections2semestr\\files\\fPoints.dat","rb"))==NULL)

{ printf("Error\n");

return -1;

}

else printf("File was opened for reading\n");

fread (&Point, sizeof(Point),1,fP);

while (!feof(fP))

{ n++; // Счётчик количества точек

printf("%6.1f",Point.x);

printf("%6.1f",Point.y);

fread (&Point, sizeof(Point),1,fP);

} fclose(fP);

printf("\n Read %d records\n ",n);

return n;

}

/* Функция находит две (любые) точки с наибольшим расстоянием между ними. В функцию передаём найденное в предыдущей функции количество точек. Функция возвращает координаты двух найденных точек (переменные типа структуры p1 и p2) и расстояние между ними (dres). */

void MyFIND(int n,TPoint &p1, TPoint &p2, float &dres)

{ TPoint Point1, Point2; float d; clrscr();

if((fP=fopen ("d:\\ana\\cpp\\C++Lections2semestr\\files\\fPoints.dat","rb"))==NULL)

{ printf("Error\n");

return ;

}

else printf("File was opened for finding\n");

long pos=0; dres=0;

for (int i=1; i<=n-1; i++)

{

/* Устанавливаем указатель чтения-записи в позицию, начиная с которой будем читать структуру (координаты одной точки) для сравнения со всеми далее расположенными точками в файле. Первый раз должны читать координаты первой точки. Поэтому pos =0. Далее будем использовать позицию, полученную с помощью функции fgetpos. */

fsetpos(fP,&pos);

fread (&Point1, sizeof(Point1),1,fP);

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

fgetpos(fP,&pos);

/* Читаем координаты точек до конца файла*/

fread (&Point2, sizeof(Point2),1,fP);

while (!feof(fP))

{

/* Находим расстояние от прочитанной точки до ранее фиксированной точки Point1… */

d=MyDist(Point1, Point2);

cout<<d<<" "; // … для контроля выводим его…

// … и сравниваем его с наибольшим расстоянием.

if (d>dres)

// Запоминаем координаты двух точек и расстояние между ними

{dres=d; p1=Point1; p2=Point2;

}

fread (&Point2, sizeof(Point2),1,fP);

}

}

fclose(fP);

}

int main()

{ int flag=1; long n=0; TPoint P1,P2; float D;

while (flag)

{ cout << "\n 1 -- CREATE"<<

"\n 2 -- LOOK"<<

"\n 3 -- FIND"<<

"\n 0 -- EXIT"<<endl;

cin>>flag;

switch (flag)

{ case 1: MyCREATE(); break;

case 2: n=MyREAD(); break;

case 3:

/* Напоминаем, что если не читали файл, то и не получили количество точек в файле. В таком случае необходимо выполнить второй пункт меню */

if (n==0) printf("\n n=0. Do number 2");

else { MyFIND(n,P1,P2, D);

printf("\n Result: x1=%6.1f y1=%6.1f",

P1.x, P1.y);

printf(" x2=%6.1f y2=%6.1f Dist=%8.3f",

P2.x, P2.y, D); break;

case 0: return 0;

}

}

}