Сортировка и поиск записей в ОЗУ и в файлах


Сортировка и поиск записей в массивах не представляет каких-либо затруднений. Необходимо предусмотреть в массивах дополнительные ячейки для размещения записей, если записи будут добавляться в массив. Для сортировки и поиска в массивах можно предварительно прочитать все записи в массив и затем применить к массиву необходимые библиотечные функции. После сортировки массив может быть «сброшен» обратно в файл.

Пример

В программе выполняется сортировка и поиск элемента в массиве структурных переменных.

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define MAX_BOOKS 1500

#define NAME 32

#define TITLE 64

typedef struct { char author [NAME];

char title [TITLE];

int year;

float price;

} BOOKS;

#include “myf.h”

void main(void)

{

int index, ret, func_number, i = 0;

BOOKS new; // переменная-ключ или новая запись

BOOKS *start, *ptr, *work; // память под массив, указатель текущей записи, рабочий

// указатель

int (*fcmp[5])() = // массив указателей на функции сравнения

{cmp_name, cmp_title, cmp_year, cmp_price, cmp_totally};

 

// Выделение памяти под массив и ввод записей из файла или в диалоге

start = (BOOKS *) calloc(MAX_BOOKS, sizeof(BOOKS));

if(start == NULL)

{

printf(“Память под массив не может быть выделена!\n”);

(void)getchar();

return;

};

…………………………………………………………………………………………………..

// начальный адрес массива записей хранится в start, в index – порядковый номер

// последнего введенного элемента, на последний элемент ссылается ptr,

// максимальный размер буфера для размещения записей не должен

// превышать MAX_BOOKS элементов

…………………………………………………………………………………………………

// сортировка по критерию, который запрашивается в диалоге и код критерия

// помещается в переменную func_number: 0 – по имени автора, 1 – по заголовку,

// 2 – по году издания, 3 – по цене

func_number = input_criteria();

qsort(start, index +1, sizeof(BOOKS), fcmp[func_number]);

…………………………………………………………………………………………………...

// добавление нового элемента в массив, элемент извне вводится в переменную new

// если элемента нет в массиве, то он добавляется, иначе – вывод сообщения

work = start;

input_book(&new); // ввод нового элемента

work = lfind(&new, work, &index, sizeof(BOOKS), fcmp[4]);

if(work == NULL) // нет совпадения по всем полям

{

index++;

if(index < MAX_BOOKS) // места достаточно

start[index – 1] = new;

else

{

puts(“База заполнена до предела!\n”);

index--;

break;

}

}

else

puts(“В базе уже есть этот элемент!\n”);

…………………………………………………………………………………………………

// Поиск в массиве элемента по заданному ключу, автору, названию и т.д.

// критерий поиска вводится в переменную func_number

func_number = search_criteria();

input_key(func_number, &new);

work = start;

for(; work != ptr;)

{

work = lfind(&new, work, &index, sizeof(BOOKS), fcmp[func_number]);

if(work != NULL)

{

puts(“Элемент найден:\n”);

output_book(work); // вывод результатов

break;

}

else

puts(“”);

}

…………………………………………………………………………………………………

}

Комментарий. #include “myf.h” указывает файл, где содержатся прототипы используемых функций. Если указано – “…”, то поиск файла выполняется в текущем каталоге, где расположен основной текст программы, затем поиск будет продолжен на основе пути, указанного в опции компилятора –l и только потом в стандартном INCLUDE. Если файл указан в форме <…>, то поиск выполняется сразу в стандартном каталоге. Прототипы в файле myf.h выглядят следующим образом:

int comp_name(const BOOKS *, const BOOKS *);

int comp_price(const BOOKS *, const BOOKS *);

int comp_title(const BOOKS *, const BOOKS *);

int comp_year(const BOOKS *, const BOOKS *);

int comp_totally(const BOOKS *, const BOOKS *);

int input_criteria(void);

int search_criteria(void);

void input_key(int, BOOKS *);

void input_book(BOOKS *);

 

Файл с определениями функций компилируется отдельно:

#include <string.h>

#define NAME 32

#define TITLE 64

typedef struct { char author[NAME];

char title[TITLE];

int year;

float price;

} BOOKS;

………………………………………………….

 

int comp_name(const BOOKS *one, const BOOKS *two)

{

return (strnicmp(one -> author, two -> author, strlen(one -> author)));

}

int comp_price(const BOOKS *one, const BOOKS *two)

{

return (one -> price – two -> price);

}

int comp_title(const BOOKS *one, const BOOKS *two)

{

return (strnicmp(one -> title, two -> title, strlen(one -> title)));

}

int comp_year(const BOOKS *one, const BOOKS *two)

{

return (one -> year – two -> year);

}

int comp_totally(const BOOKS *one, const BOOKS *two)

{

if(!strnicmp(one -> author, two -> author, strlen(one -> author)) &&

!strnicmp(one -> title, two -> title, strlen(one -> title)) &&

(one -> year == two -> year) &&

(one -> price == two -> price))

return 0;

else

return -1;

}

………………………………………………………………

// прочие функции

………………………………………………………………

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

int strnicmp(const char *s1, const char *s2, size_t maxlen),

которая преобразует все буквы в ASCIIZ-строках s1 и s2 в строчные и сравнивает их в лексикографическом порядке. Возвращает значения меньше 0 (s1 < s2), равное 0 (s1 == s2) или больше 0 (s1 < s2) в соответствующих случаях. Сравнение ограничивается maxlen числом символов.

 

Пример

Вначале можно выяснить количество записей в файле. После этого можно выделить место для размещения записей из файла в heap-памяти, выполнить необходимую обработку и сбросить записи из массива в файл. (В лекции 14 рассмотрены режимы открытия файлов и функции позиционирования указателя записей и его контроля).

#include <stdio.h>

#include <conio.h>

…………………………………………………………...

typedef struct BOOK TBOOK;

FILE *stream;

long length, k;

TBOOK *arr;

……………………………………………………………

stream = fopen(“…”, “r+b”);

if(stream == NULL)

{

printf(“Can’t open file!\n”);

return;

}

…………………………………………………………..

fseek(stream, 0L, SEEK_END);

length = ftell(stream);

k = length/sizeof(TBOOK);

arr = (TBOOK *)calloc(k, sizeof(TBOOK));

fseek(stream, 0L, SEEK_SET);

fread(arr, sizeof(TBOOK), k, stream);

// применение qsort

…………………………………………………………….

 

 

Вопросы для самоконтроля

  • Чем отличаются аргументы функций malloc() и calloc()?
  • Как выполняется «освобождение» heap-памяти?
  • Как рассчитывается доступ к элементам не одномерных массивов через указатели?
  • Опишите основные характеристики функций поиска и сортировки для структурных массивов!
  • Как можно вычислить число записей в файле не считывая записи в основную память?

Вопросы для самостоятельного изучения

  • Назначение и спецификации функций ftell() и fseek()?

 

 



Дата добавления: 2016-05-26; просмотров: 1496;


Поиск по сайту:

Воспользовавшись поиском можно найти нужную информацию на сайте.

Поделитесь с друзьями:

Считаете данную информацию полезной, тогда расскажите друзьям в соц. сетях.
Poznayka.org - Познайка.Орг - 2016-2024 год. Материал предоставляется для ознакомительных и учебных целей.
Генерация страницы за: 0.017 сек.