Рейтинговые книги
Читем онлайн Основы программирования в Linux - Нейл Мэтью

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 80 81 82 83 84 85 86 87 88 ... 200

  default:

   fprintf(stderr, "Usage: %s [-i]n", prog_name);

   result = EXIT_FAILURE;

   break;

  } /* switch */

 } /* while */

 return(result);

}

Упражнение 7.16. Файл cd_access.c

Теперь переходите к функциям доступа к базе данных dbm.

1. Как обычно, начните с нескольких файлов #include. Далее примените директивы #define для задания файлов, которые будут использоваться для хранения данных:

#define _XOPEN_SOURCE

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <fcntl.h>

#include <string.h>

#include <ndbm.h>

/* В некоторых дистрибутивах файл в предыдущей строке может быть придется заменить на gdbm-ndbm.h */

#include "cd_data.h"

#define CDC_FILE_BASE "cdc_data"

#define CDT_FILE_BASE "cdt_data"

#define CDC_FILE_DIR "cdc_data.dir"

#define CDC_FILE_PAG "cdc_data.pag"

#define CDT_FILE_DIR "cdt_data.dir"

#define CDT_FILE_PAG "cdt_data.pag"

2. Используйте эти две переменные области действия файла для отслеживания текущей базы данных:

static DBM *cdc_dbm_ptr = NULL;

static DBM *cdt_dbm_ptr = NULL;

3. По умолчанию функция database_initialize открывает существующую базу данных, но передав ненулевой (т.е. true) параметр new_database, вы можете заставить ее создать новую (пустую) базу данных, при этом существующая база данных удаляется. Если база данных успешно инициализирована, также инициализированы и два ее указателя, указывающие на то, что база данных открыта.

int database_initialize(const int new_database) {

 int open_mode = O_CREAT | O_RDWR;

 /* Если открыта какая-либо имеющаяся база данных, закрывает ее */

 if (cdc_dbm_ptr) dbm_close(cdc_dbm_ptr);

 if (cdt_dbm_ptr) dbm_close(cdt_dbm_ptr);

 if (new_database) {

  /* Удаляет старые файлы */

  (void)unlink(CDC_FILE_PAG);

  (void)unlink(CDC_FILE_DIR);

  (void)unlink(CDT_FILE_PAG);

  (void)unlink(CDT_FILE_DIR);

 }

 /* Открывает несколько новых файлов, создавая их при необходимости */

 cdc_dbm_ptr = dbm_open(CDC_FILE_BASE, open_mode, 0644);

 cdt_dbm_ptr = dbm_open(CDT_FILE_BASE, open_mode, 0644);

 if (!cdc_dbm_ptr || !cdt_dbm_ptr) {

  fprintf(stderr, "Unable to create databasen");

  cdc_dbm_ptr = cdt_dbm_ptr = NULL;

  return (0);

 }

 return (1);

}

4. Функция database_close просто закрывает базу данных, если она была открыта и устанавливает указатели базы данных в null, чтобы показать, что нет открытой базы данных:

void database_close(void) {

 if (cdc_dbm_ptr) dbm_close(cdc_dbm_ptr);

 if (cdt_dbm_ptr) dbm_close(cdt_dbm_ptr);

 cdc_dbm_ptr = cdt_dbm_ptr = NULL;

}

5. Далее у вас появляется функция, извлекающая единственный элемент каталога, когда передан указатель на строку текста из каталога. Если элемент не найден, у возвращенных данных пустое поле каталога:

cdc_entry get_cdc_entry(const char *cd_catalog_ptr) {

 cdc_entry entry_to_return;

 char entry_to_find[CAT_CAT_LEN + 1];

 datum local data datum;

 datum local_key_datum;

 memset(&entry_to_return, '', sizeof(entry_to_return));

6. Начните с некоторых имеющих смысл проверок, чтобы убедиться в том, что база данных открыта, и вы передали приемлемые параметры, т.е. ключ поиска содержит только допустимую строку и значения null:

 if (!cdc_dbm_ptr || !cdt_dbm_ptr) return (entry_to_return);

 if (!cd_catalog_ptr) return (entry_to_return);

 if (strlen(cd_catalog_ptr) >= CAT_CAT_LEN) return (entry_to_return);

 memset(&entry_to_find, '', sizeof(entry_to_find));

 strcpy(entry_to_find, cd_catalog_ptr);

7. Задайте структуру datum, нужную функциям базы данных dbm, и используйте функцию dbm_fetch для извлечения данных. Если не извлечены никакие данные, вы возвращаете пустую структуру entry_to_return, которая была инициализирована ранее:

 local_key_datum.dptr = (void *) entry_to_find;

 local_key_datum.dsize = sizeof(entry_to_find);

 memset(&local_data_datum, '', sizeof(local_data_datum));

 local_data_datum = dbm_fetch(cdc_dbm_ptr, local_key_datum);

 if (local_data_datum.dptr) {

  memcpy(&entry_to_return, (char*)local_data_datum.dptr, local_data_datum.dsize);

 }

 return (entry_to_return);

} /* get_cdc_entry */

8. Было бы неплохо иметь возможность получать также и одиночный элемент-дорожку, именно этим занимается следующая функция аналогично функции get_cdc_entry, но с указателем на строку каталога и номер дорожки в качестве параметров:

cdt_entry get_cdt_entry(const char *cd_catalog_ptr, const int track_no) {

 cdt_entry entry_to_return;

 char entry_to_find[CAT_CAT_LEN + 10];

 datum local_data_datum;

 datum local_key_datum;

 memset(&entry_to_return, '', sizeof(entry_to_return));

 if (!cdc_dbm_ptr || !cdt_dbm_ptr) return (entry_to_return);

 if (!cd_catalog_ptr) return (entry_to_return);

 if (strlen(cd_catalog_ptr) >= CAT_CAT_LEN) return (entry_to_return);

 /* Устанавливает ключ поиска, представляющий собой комбинацию

    элемента каталога и номера дорожки */

 memset(&entry_to_find, '', sizeof(entry_to_find));

 sprintf(entry_to_find, "%s %d", cd_catalog_ptr, track_no);

 local_key_datum.dptr = (void*)entry_to_find;

 local_key_datum.dsize = sizeof(entry_to_find);

 memset(&local_data_datum, '', sizeof(local_data_datum));

 local_data_datum = dbm_fetch(cdt_dbm_ptr, local_key_datum);

 if (local_data_datum.dptr) {

  memcpy(&entry_to_return, (char*)local_data_datum.dptr, local_data_datum.dsize);

 }

 return (entry_to_return);

}

9. Следующая функция add_cdc_entry добавляет новый элемент каталога:

int add_cdc_entry(const cdc_entry entry_to_add) {

 char key_to_add[CAT_CAT_LEN + 1];

 datum local_data_datum;

 datum local_key_datum;

 int result;

 /* Проверяет инициализацию базы данных и корректность параметров */

 if (!cdc_dbm_ptr || !cdt_dbm_ptr) return (0);

 if (strlen(entry_to_add.catalog) >= CAT_CAT_LEN) return (0);

 /* Гарантирует включение в ключ поиска только корректной строки

    и значений null */

 memset(&key_to_add, '', sizeof(key_to_add));

 strcpy(key_to_add, entry_to_add.catalog);

 local_key_datum.dptr = (void*)key_to_add;

 local_key_datum.dsize = sizeof(key_to_add);

 local_data_datum.dptr = (void*)&entry_to_add;

 local_data_datum.dsize = sizeof(entry_to_add);

 result = dbm_store(cdc_dbm_ptr, local_key_datum, local_data_datum, DBM_REPLACE);

 /* dbm_store() применяет 0 для успешного завершения */

 if (result == 0) return (1);

 return (0);

}

10. Функция add_cdt_entry добавляет новый элемент-дорожку. Ключ доступа — это комбинация строки из каталога и номера дорожки:

int add_cdt_entry(const cdt_entry entry_to_add) {

 char key_to_add[CAT_CAT_LEN + 10];

 datum local_data_datum;

 datum local_key_datum;

 int result;

 if (!cdc_dbm_ptr || !cdt_dbm_ptr) return (0);

 if (strlen(entry_to_add.catalog) >= CAT_CAT_LEN) return (0);

 memset(&key_to_add, ' ', sizeof(key_to_add));

 sprintf(key_to_add, "%s %d", entry_to_add.catalog, entry_to_add.track_no);

 local_key_datum.dptr = (void*)key_to_add;

 local_key_datum.dsize = sizeof(key_to_add);

 local_data_daturn.dptr = (void*)&entry_to_add;

 local_data_datum.dsize = sizeof(entry_to_add);

 result = dbm_store(cdt_dbm_ptr, local_key_datum, local_data_datum, DBM_REPLACE);

 /* dbm_store() применяет 0 в случае успешного завершения

    и отрицательные числа для обозначения ошибок */

 if (result == 0) return (1);

 return (0);

}

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

int del_cdc_entry(const char *cd_catalog_ptr) {

 char key_to_del[CAT_CAT_LEN +1];

 datum local_key_datum;

 int result;

 if (!cdc_dbm_ptr || !cdt_dbm_ptr) return (0);

 if (strlen(cd_catalog_ptr) >= CAT_CAT_LEN) return (0);

 memset(&key_to_del, '', sizeof(key_to_del));

 strcpy(key_to_del, cd_catalog_ptr);

 local_key_datum.dptr = (void*)key_to_del;

 local_key_datum.dsize = sizeof(key_to_del);

 result = dbm_delete(cdc_dbm_ptr, local_key_datum);

 /* dbm_delete() применяет 0 в случае успешного завершения */

 if (result == 0) return (1);

 return (0);

}

12. Далее приведена аналогичная функция для удаления дорожки. Помните о том, что ключ дорожки — это сложный индекс, состоящий из строки, принадлежащей элементу каталога, и номера дорожки:

int del_cdt_entry(const char *cd_catalog_ptr, const int track_no) {

 char key_to_del[CAT_CAT_LEN + 10];

 datum local_key_datum;

 int result;

 if (!cdc_dbm_ptr || !cdt_dbm_ptr) return (0);

 if (strlen(cd_catalog_ptr) >= CAT_CAT_LEN) return (0);

 memset(&key_to_del, '', sizeof(key_to_del));

 sprintf(key_to_del, "%s %d", cd_catalog_ptr, track_no);

 local_key_datum.dptr = (void*)key_to_del;

 local_key_datum.dsize = sizeof(key_to_del);

 result = dbm_delete(cdt_dbm_ptr, local_key_datum);

 /* dbm_delete() применяет 0 в случае успешного завершения */

 if (result == 0) return (1);

 return (0);

13. И последнее, но не по значимости, у вас есть простая функция поиска. Она не очень замысловата, но, тем не менее, показывает, как просматривать элементы dbm, если ключи заранее неизвестны.

1 ... 80 81 82 83 84 85 86 87 88 ... 200
На этой странице вы можете бесплатно читать книгу Основы программирования в Linux - Нейл Мэтью бесплатно.
Похожие на Основы программирования в Linux - Нейл Мэтью книги

Оставить комментарий