Табличные структуры
[Оглавление] [<< страница] [>>страница]


   3.3. Некоторые рекомендации по работе с линейными таблицами
 

При решении задач, связанных с обработкой таблиц, число элементов таблицы обычно заранее неизвестно. Кроме того, свойство массовости алгоритма требует возможности применения программы для таблиц с произвольным числом элементов, таблицы же могут содержать многие сотни и тысячи записей. Естественно, при каждом применении программы создавать такие большие таблицы нет необходимости, они должны быть сохранены в файлах до следующей обработки. С течением времени может возникнуть необходимость добавления и удаления отдельных элементов таблицы.

Такие потребности могут быть удовлетворены следующим образом. Первоначально таблица создается не в оперативной памяти, а в файле на ВЗУ. Для обработки таблица считывается в динамически полученную векторную память в виде одномерного массива. Возникает проблема определения размера запрашиваемой динамической памяти, т.е. определения числа элементов таблицы. Казалось бы, что для этого достаточно извлечь информацию о длине файла, хранимую системой управления файлами операционной системы:
FILE •fin;
long len;      /* размер файла в байтах */
char name[ ];    /* для имени файла */
fin = fopen(name, »r»);
len = filelength(fileno(fin));

Однако это допустимо только тогда, когда записи таблицы хранятся в файле в двоичном виде и, следовательно, размеры таблицы в оперативной памяти и на ВЗУ совпадают. Если же данные записей хранятся в файле в форматированном виде, то эти размеры не совпадают, так как размер записи в оперативной памяти определяется структурой записи, а размер форматированной записи на ВЗУ будет другим. Действительно, число int a = 31570 занимает в ОП 2 байта, а на ВЗУ — все 5 и то без учета пробелов между отдельными данными. Или char name[20] =»qq.txt» в ОП занимает все 20 байт, а на ВЗУ — только действительную длину строки. Таким образом, при хранении записей таблицы в файле в форматированном виде необходимо знать число записей т. Тогда для размещения таблицы в ОП получают динамическую память, размер которой будет определяться как произведение числа элементов т на длину каждого элемента. Например:
struct Rec *T1;
Т1 = (Rec*) calloc(m, sizeof(Rec)); или
Т1 = (Rec*) malloc(m*sizeof(Rec));

В приведенном ниже примере в начале файла находится число записей таблицы m, затем следуют т записей таблицы. Это достигается следующим образом. После открытия файла в режиме записи "w+" fout=fopen(name,"w") сразу же записываем в файл число m= 0, резервируя место для записи действительной длины. При этом необходимо учитывать возможности расширения поля при больших значениях т.

Далее ведем подсчет числа i выводимых в файл записей, уста¬навливаем указатель файла в его начало и записываем в файл число i:
/* fpostj POS; */
fseek(fout, 0L, 0);
/* или fgetpos(fout, &POS); */
fprintf(fout, " %5d ", /);     /* 5 — размер поля для числа записей i*/
fclose(fout);

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

Расширение таблицы за счет новых элементов осуществляется добавлением записей в конец файла и последующей коррекцией числа записей в начале файла. Удаление записей из таблицы можно выполнить по схеме: чтение таблицы из файла в оперативную память — последовательная запись элементов таблицы в файл, исключая удаляемые записи — коррекция числа элементов в начале файла.

[Оглавление] [<<страница] [>>страница] [В начало ]