русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Функция fseek()


Дата добавления: 2015-06-12; просмотров: 1291; Нарушение авторских прав


 

Наибольшими возможностями позиционирования указателя потока обладает функция int fseek (FILE *f, long offset, int from). Она сдвигает указатель в файле f на offset байт от положения, указанного третьим параметром from.

Чаще всего from принимает значение SEEK_SET или, что то же самое, нулевое значение. Тогда указатель файла перемещается на offset байт “вперёд” от начала потока в сторону конца файла, если offset>=0. В этом случае offset задаёт порядковый номер байта, на который надо установить указатель чтения-записи. При таком нулевом значении параметра from параметр offset не должен быть отрицательным. Например,

int a; fseek(f, 20, SEEK_SET); a=fgetc(f); // ??????

прочитает информацию, начиная с 20-го байта двоичного файла, который желательно открывать с режимом “rb”.

Если from=SEEK_END, что соответствует целому числу 2,то при неположительном значении параметра offset указатель файла перемещается на |offset| байт “назад” от конца потока в сторону начала файла. При таком значении параметра from параметр offset не должен быть положительным. В противном случае мы “выйдем” за границу файла.

Если from=SEEK_CUR, что соответствует целому числу 1, то можно “продвигаться” на offset байт “вперёд” от текущей позиции указателя при offset>0, или “назад” к началу файла, если offset<0.

Функция fseek() возвращает 0 в случае успешного выполнения и ненулевое значение в случае ошибки.

Пример 1.Прямой доступ к файлу. Прочитать и вывести на экран n-й одномерный массив фиксированной размерности m, (n-2)-й массив, (n-4)-й массив и т. д. до начала файла.

const m=5,

n=8;

FILE *arf;

// Создание файла. Объяснение смотри в 3.2

void MyCr()

{ int a[m];

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

printf("\n");



for (int i=0; i<n;i++)

{ cout<<endl;

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

{ a[j]=(i+1)*(j+1);

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

}

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

}

fclose(arf); cout<<"\nFile was created"; }

// Просмотр файла. Объяснение смотри в 3.2

void MyRead()

{ int a[m];

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

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

while (!feof(arf))

{

printf("\n");



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

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

fread(a,m*sizeof(int),1,arf);

}

fclose(arf);

}

/* Вариант 1. Указатель файла перемещаем, используя в функции fseek () позицию начала файла, т. е. в качестве последнего параметра этой функции используем SEEK_SET */

void MyRead1()

{ int a[m];

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

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

{ fseek(arf, (n-i)*sizeof(a),SEEK_SET);

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

printf("\n");



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

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

}

fclose(arf);

}

/* Вариант 2. Указатель файла перемещаем, используя в функции fseek () позицию конца файла SEEK_END */

void MyRead2()

{ int a[m];

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

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

{ fseek(arf, -i*sizeof(a),SEEK_END);

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

printf("\n");



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

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

}

fclose(arf); }

/* Вариант 3. Указатель файла перемещаем, используя в функции fseek () текущую позицию файла SEEK_CUR */

void MyRead3()

{ int a[m];

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

fseek(arf, -1*sizeof(a), SEEK_END);

for (int i=0; i<n/2;i++)

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

printf("\n");



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

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

fseek(arf, -3*sizeof(a),SEEK_CUR);

}

fclose(arf); }

int main()

{ int flag; while (1)

{ cout << "\n1 -- CREATE"<<endl<<

"2 -- READ"<<endl<<

"3 -- Read1"<<endl<<

"4 -- Read2"<<endl<<

"5 -- Read3"<<endl<<

"0 -- EXIT"<<endl;

cin>>flag;

switch (flag)

{ case 1: MyCr(); break;

case 2: MyRead(); break;

case 3: MyRead1(); break;

case 4: MyRead2(); break;

case 5: MyRead3(); break;

case 0: return 0;

}

}

}

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;

}

}

}

 

Упражнения, тесты.

1. Пусть в программе записано следующее объявление: FILE *f; Что объявлено?

Варианты ответа:

1) указатель на область оперативной памяти для данных, хранящихся в файле на внешнем устройстве;

2) указатель на область оперативной памяти для структуры, поля которой зависят от конкретной задачи;

3) указатель на область оперативной памяти для характеристик (параметров) файла в виде структуры со стандартным именем FILE;

4) указатель на область внешней памяти для характеристик (параметров) файла в виде структуры со стандартным именем FILE;

2. С каким режимом (типом доступа к файлу), который записывается в функции fopen, можно создать новый файл?

Варианты ответа:

1) только “w”; 2) только “w+”; 3) “w”и “w+”; 4) только “a”; 5) только “a+”; 6) “a” и “a+”; 7) “w”, “w+”,“a”и “a+”; 8) “w”и “a”;

9) “w+”и “a+”;

3. Даны следующие варианты кода:

1) FILE * f; fp=fopen("d:\\ANA\\cpp\\2005_06\\ bf1.dat","rb");

if (fp==NULL) { cout<<”Error “; exit(1); }

else cout<<”File is opened”;

2) if((fp=fopen("d:\\ANA\\cpp\\2005_06\\ bf1.dat","rb"))==NULL)

{ cout<<”Error “; exit(1); }

else cout<<”File is opened”;

3) FILE * f; fp=fopen("d:\\ANA\\cpp\\2005_06\\ bf1.dat","rb");

if (!fp) cout<<”File is opened”; else { cout<<”Error “; exit(1); }

4) FILE * f; if (fp=fopen("d:\\ANA\\cpp\\2005_06\\ bf1.dat","rb"))

{ cout<<”Error “; exit(1); }

else cout<<”File is opened”;

5) FILE * f; if (fp=fopen("d:\\ANA\\cpp\\2005_06\\ bf1.dat","rb"))

cout<<”File is opened”; else { cout<<”Error “; exit(1); }

6) FILE * f; if (fp==fopen("d:\\ANA\\cpp\\2005_06\\ bf1.dat","rb"))

cout<<”File is opened”; else { cout<<”Error “; exit(1); }

Какие из предложенных вариантов правильно открывают файл для чтения?

4. Пусть в программе записаны следующие объявления:

FILE *f; const m=5; int a[m]={10,-22, 30, 4,-50};

и открыт файл:

f=fopen(“…”, “w”);

Какие из следующих операторов (последовательностей операторов) из предоженнных правильно записывают все пять чисел массива a в файл?

1) fwrite (a, 5, 1, f);

2) fwrite (a, 20, 1, f);

3) fwrite (a, 10, 2,f);

4) fwrite(&a[0], sizeof(a), 1, f);

5) for(int i=0; i<n; i++) fwrite(a[i], sizeof(int), 1, f);

6) for(int i=0; i<n; i++) fwrite(a[i], sizeof(a), 1, f);

7) for(int i=0; i<n; i++) fwrite(&a[i], sizeof(int), 1, f);

8) for(int i=0; i<n; i++) fwrite(&a[i], sizeof(a), 1, f);

5. Пусть в программе записаны следующие объявления:

FILE *f; const m=20;

int a[m]={10,-22, 30, 4,-50, 6, 7,8,9, 100, 110, 12, 13, 14, 15};

и открыт файл:

f=fopen(“…”, “w”);

Сколько и какие целые числа запишем в файл с помощью одного вызова функции fwrite(a, 20, 2, f); ?

Варианты ответа:

1) 10 первых чисел массива a;

2) 20 чисел: 15 записанных при объявлении массива и пять нулей;

3) 15 записанных при объявлении массива;

4) 10 чисел из второй половины массива а, то есть

110, 12, 13, 14, 15, 0, 0, 0, 0, 0 ;

5) Ошибка в fwrite, так как нет в массиве 20*2=40 чисел, которые функция пытается записать.

6. Как надо объявить массив а с элементами типа short, чтобы с помощью функции fwrite(a, 40, 1, f); весь этот массив был записан в файл?

Варианты ответа:

1) short a[10]; 2) short a[20]; 3) short a[80]; 4) short a[40]; 5) short a[5];

7. Пусть в программе записаны следующие объявления:

FILE *f;

struct ts { char fio[15]; int tel; } vs;

открыт файл (f=fopen(“…”, “w”);) и определены поля структуры.Какие из следующих операторов (последовательностей операторов) правильно записывают одну структуру (ФИО и телефон) в файл?

Варианты ответа:

1)fwrite(&ts, sizeof(vs),1,f); 2) fwrite(&vs, sizeof(ts),1,f);

3) fwrite(vs, sizeof(vs),1,f); 4) fwrite(vs, sizeof(ts),1,f);

5) fwrite(&vs, 20, 1, f); 6) fwrite(&vs, 15, 1, f);

7) fwrite(vs, 20, 1, f); 8) fwrite(vs, 15, 1, f);

8. Пусть в программе записаны следующие объявления:

FILE *f; const m=10; int a[m], b;

Пусть с помощью функции fwrite в файл записали 10 целых чисел типа int и файл открыт для чтения. Даны следующие варианты фрагмента программы:

1) for (int i=1; i<= m; i++)

{ fseek(f, (m-i)*sizeof(int), SEEK_SET);

fread(&b, sizeof(b), 1, arf);

// использование числа b …}

2) for (int i=m-1; i>=0; i--)

{ fseek(f, i*sizeof(int), 0);

fread(&b, sizeof(b), 1, arf);

// использование числа b …}

3) for (int i=1; i<= m; i++)

{ fseek(f, (m-i)*sizeof(int),1);

fread(&b, sizeof(b), 1, arf);

// использование числа b …}

4) for (int i=1; i<= m; i++)

{ fseek(f, -i*sizeof(b), SEEK_END);

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

// использование числа b …}

5) for (int i=1; i<= m; i++)

{ fseek(f, -i*sizeof(int), 0);

fread(&b, sizeof(b), 1, arf);

// использование числа b …}

6) for (int i=1; i<=m;i++)

{ fseek(arf, (m-i)*sizeof(a), SEEK_SET);

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

// использование a …}

Какие из предложенных вариантов читают эти 10 чисел из файла в обратном порядке?

9. Пусть int p; FILE *f; Какие из следующих вызовов функции правильно определяют положение указателя чтения-записи созданного файла и запоминают его?

1) fgetpos (f, p); 2) fgetpos (f, &p); 3) fsetpos (f, p); 4) fsetpos (f, &p);

10. Пусть int *p=new int; FILE *f; Какие из следующих вызовов функции правильно устанавливают положение указателя чтения-записи созданного файла?

1) fgetpos (f, p); 2) fgetpos (f, &p); 3) fsetpos (f, p); 4) fsetpos (f, &p);

11. Пусть FILE *f; Какие из следующих вызовов функции правильно устанавливают положение указателя чтения-записи созданного файла на его начало?

1) rewind (f); 2) rewind (*f); 3) fseek(f, 0, 0); 4) fseek(f, 0, SEEK_END);

5) fseek(f, 0, 1); 6) ftell(f); 7) int p=0; fsetpos(f, &p); 8) int p=0; fsetpos(f, p);

 



<== предыдущая лекция | следующая лекция ==>
Прямой (произвольный) доступ к файлу | B. Задачи второго среднего уровня.


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.105 сек.