- •Списки §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
3.2. Математические задачи с использованием файлов
Во многих пособиях при рассмотрении fwite и fread ограничиваются задачами, в которых эти функции используются только для работы со структурой. Но ничто не мешает их применять, например, в матричных, геометрических и других математических задачах, в которых информацию необходимо хранить на внешнем устройстве.
Здесь будет рассмотрена работа с файлом, содержащим “матрицу”, т. е. несколько одномерных массивов фиксированной одинаковой размерности. Количество таких массивов вводим в виде переменной n, а не константы.
Важным требованием к таким задачам является следующее. В оперативной памяти будем хранить только одну строку “матрицы” в виде статического одномерного массива, как показано в примере. Одномерный массив может быть и динамическим. Вся “матрица” в оперативной памяти храниться не будет, поэтому ни статически, ни динамически память для неё не резервируется. Заметим, что не любой матричный алгоритм можно так запрограммировать. Как правило, такой метод программирования можно использовать при обработке матрицы по строкам.
Кроме работы с файлами здесь показано, что задачу можно разбить на независимо разрабатываемые проекты (программы). Один из них создаёт файл, другой читает его, третий анализирует и так далее. Связь между ними осуществляется за счёт того, что в функции fopen() в разных программах записываем один и тот же физический файл. Каждая из таких программ может быть оформлена не функцией одного проекта, как это было в предыдущих пунктах, а в виде отдельного проекта, то есть для простоты, например, в виде одной основной функции main.
Создание файла одномерных массивом. Другими словами, “матрицу”, то есть несколько одномерных массивов записываем на внешнее устройство в файл.
// Определяем количество элементов в каждой строке матрицы.
#define m 5
main()
{
// В оперативной памяти будем хранить одну строку ”матрицы” размерности m.
int a[m];
FILE *arf;
arf= fopen("d:\\ANA\\cpp\\C++Lections2Semestr\\files\\farr.dat","wb");
// Объявляем переменную для количества строк “матрицы” и определяем её
int n; printf("\n");
cout<<"n="; cin>>n;
/* Внешний цикл для записи в файл n одномерных массивов, каждый из которых размерности m, то есть 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);
//fwrite(&a[0],m*sizeof(int),1,arf);
//fwrite(a,m*4,1,arf);
}
fclose(arf); cout<<"\nFile was created";
getch(); return 0;
}
Описание функции fwrite смотри в 3.1.
Независимо от варианта использования функции fwrite() она выполняется столько раз, сколько одномерных массивов мы записываем. За один вызов функция записывает в файл, связанный с потоком arf, одну порцию информации из m целых чисел. Размер этого блока sizeof(a), или m*sizeof(int), или m*4 байт. Записываемые в файл данные выбираются из области оперативной памяти, начиная с адреса a, или &a[0], то есть с начала расположения одномерного массива.
Добавление в конец файла одномерных массивов фиксированной размерности (строк “матрицы” ) аналогично созданию файла. Только при открытии файла вместо режима “wb” необходимо указать “ab”. Кроме этого, в предложенном варианте элементы массива формируются случайным образом. Количество добавляемых одномерных массивов (строк “матрицы “) не определяется. Массивы добавляем, пока не введём символ ‘*’. При этом введённые символы (‘*’) в файл не записываются.
#define m 5
main()
{ int a[m],i; char ch; FILE *arf;
randomize();
arf= fopen("d:\\ANA\\cpp\\C++Lections2Semestr\\files\\farr.dat","ab");
do { cout<<endl;
for (i=0;i<m;i++)
{a[i]=random(100)-50;
cout<<a[i]<<" ";
}
fwrite(a,sizeof a,1,arf);
cout<<"\n * -- exit" ;
ch=getch();
} while (ch!='*');
fclose(arf);
return 0;
}
Чтение файла одномерных массивов. Читаем из файла записанные в предыдущих программах одномерные массивы размерности m. Другими словами, читаем “матрицу” с фиксированным (одинаковым) количеством элементов в каждой строке и произвольным количеством строк.
Так как мы могли добавлять одномерные массивы, то их количество, т. е. количество строк “матрицы”, не обязательно должно совпадать с тем, которое было при создании файла. Поэтому цикл для чтения всех массивов организован с помощью функции feof().
#define m 5
main()
{
/*Как и при создании файла, в оперативной памяти будем хранить одну строку ”матрицы”, то есть один одномерный массив фиксированной размерности m. */
int a[m];
FILE *arf;
arf= fopen("d:\\ANA\\cpp\\C++Lections2Semestr\\files\\farr.dat","rb");
clrscr();
/* Вне цикла читаем первый одномерный массив (первую строку “матрицы”) из файла в оперативную память. */
//fread(a, m*sizeof(int), 1, arf); или
// fread(a, m*4, 1, arf); или
fread(a, sizeof(a), 1, arf);
while (!feof(arf))
/* Цикл будет выполняться, пока не достигнем конца файла. Использование цикла for (int i=0; i<n; i++) неправильно, так как кроме создания файла предусмотрено добавление одномерных массивов. Поэтому их количество могло измениться и мы, вообще говоря, не знаем его.*/
{
/* Использование прочитанного одномерного массива. В этом примере ограничились его выводом. Реально на этом этапе возникает необходимость в алгоритмизации и программировании задач по теме “одномерные массивы”*/
printf("\n");
for (int j=0; j<m; j++)
printf("%5d",a[j]);
/* Читаем следующий одномерный массив (строку “матрицы”) из файла в оперативную память. Как и вне цикла, возможны разные варианты использования функции fread */
fread(a, sizeof(a),1,arf);
}
fclose(arf); getch(); return 0;
}
Описание функции fread смотри в 3.1.
Независимо от варианта использования функции fread() она выполняется столько раз, сколько одномерных массивов есть в файле. За один вызов функция читает из файла, связанного с потоком arf, одну порцию информации из m целых чисел, т. е. sizeof(a) (или m*sizeof(int), или m*4 байт). Эти прочитанные данные записываются в область оперативной памяти, начиная с адреса a (или &a[0]).