- •Списки §1. Общие сведения о списках
- •§2. Создание списка
- •§3. Просмотр и анализ списка
- •3.1. Просмотр и анализ списка целых чисел.
- •3.2. Просмотр и анализ списка одномерных массивов.
- •§6. Сравнительный анализ списков.
- •§1. Порядок работы с файлом
- •1.1. Потоки и файлы
- •1.2. Объявление файла
- •1.3. Открытие файла.
- •1.4. Закрытие файла.
- •§2. Работа с текстовым файлом
- •2.1. Посимвольная работа с текстовым файлом
- •Int fputc(int ch, file *stream)
- •2.2. Построчная работа с текстовым файлом
- •§3. Функции блокового ввода/вывода
- •3.1. Экономические задачи с использованием файлов
- •3.2. Математические задачи с использованием файлов
- •§4. Прямой (произвольный) доступ к файлу
- •4.1. Функция fseek()
- •4.2. Замена записи. Функции ftell, fgetpos, fsetpos, rewind.
- •Пример. В файл записать координаты точек плоскости. Найти две (любые) точки с наибольшим расстоянием между ними. Массив для хранения координат всех точек не использовать.
- •Упражнения, тесты.
- •Функции (дополнительные возможности)
- •§1. Функции с переменным количеством параметров.
- •§2. Указатели на функции.
- •§3. Массив указателей на функции.
- •§4. Введение в рекурсивные функции.
- •Упражнения, тесты.
- •Void Fun1 (float); void Fun2(float); void Fun3(float);
- •Лабораторная работа № 12.
- •Команды препроцессора (директивы компиляции)
- •§1. Директива define (замены в тексте)
- •Простое макроопределение (макрос)
- •Макрос с аргументами.
- •Директива #undef.
- •§2. Директива #include (включение файлов).
- •§3. Директивы условной компиляции.
- •Директива #if.
- •Директивы #ifdef и #ifndef.
- •Упражнения, тесты
- •История развития технологий программирования
- •§1. Программирование в машинных кодах и на языках символического кодирования
- •§2. Языки высокого уровня. Структурное и модульное программирование
- •§3. Интегрированные системы программирования.
- •§4. История и идеи объектно-ориентированного программирования.
- •§5. Программирование для Windows. Визуальное программирование.
- •Литература
- •Оглавление Предисловие………………………………………………………….…………………3
- •Г л а в а 4. Структуры и другие типы, определяемые пользователем.84
- •Г л а в а 6. Файлы ………………………………………………………..154
- •Г л а в а 7. Функции (дополнительные возможности) ………………190
- •Г л а в а 9. История развития технологий программирования ……220
§4. Прямой (произвольный) доступ к файлу
Файл можно рассматривать как последовательность байтов. Каждому из них можно присвоить порядковый номер, начиная с нуля. Тогда любой байт файла можно найти по его номеру.
Как было сказано в 1.2, место, откуда выполняется чтение информации из файла, или куда происходит запись данных, определяется положением указателя чтения-записи файла. Его положение — это порядковый номер байта, который будет считан первым или который первым получит новое значение. Заметим, что здесь термин “указатель” никак не связан с типом переменной, значением которой является адрес. Начальная позиция этого “невидимого курсора” устанавливается при открытии потока и указывает на начало потока при создании и чтении файла (режимы “r” и “w”) или на его конец при добавлении данных (режим “a”).
При операции чтения или записи указатель автоматически сдвигается “вперёд”, а, точнее, к концу файла, на то число байтов, которое было прочитано или записано. Если при операции чтения был достигнут конец файла, возникнет ситуация EOF. Если конец файла был достигнут при операции записи, то конец файла автоматически перемещается на то число байтов, которое было записано за прежним концом файла.
Положением указателя в файле можно также управлять программно, используя стандартные функции. Благодаря такой возможности можно считывать из файла и записывать в файл информацию с любого места.
4.1. Функция fseek()
Наибольшими возможностями позиционирования указателя потока обладает функция 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;
}
}
}