Пример 8



/* Пример маленькой базы данных.

 * Данные хранятся БЕЗ дубликатов.

 * Надо заметить, что используется плохой (неэффективный)

 * алгоритм доступа - линейный поиск.

 */

#include <stdio.h>

/* Все записи в базе имеют фиксированный размер */

#define VLEN 20

#define KEY_FREE (-13)   /* ключ свободного места. Он выбран

произвольно, но не должен встречаться в качестве входных данных */

struct data{

	short b_key;            /* ключ */

	char  b_val[VLEN];      /* строка-значение */

};

char  BASEF[] = ".base" ;       /* имя файла базы */

FILE *fbase;                    /* pointer на базу */

struct data tmp;                /* вспомогательная переменная */

void

initBase (void){

	/* fopen: r  read  (чтение)

	 *        w  write (запись), файл пересоздается.

	 * (создается, если не было, если был - опустошается).

	 *        r+ чтение и запись (файл уже существует).

	 *        w+ чтение и запись (создается пустой файл).

	 *        a  append (запись в конец файла), создать если нет:

	 *           имеется в виду, что КАЖДАЯ операция записи сначала

	 *           ставит указатель записи на конец файла.

	 * В MS DOS нетекстовый файл НЕОБХОДИМО открывать как

	 *        rb wb rb+ wb+ ab+  иначе ничего не будет работать.

	 */

	if(( fbase = fopen( BASEF, "r+" )) == NULL ){

		if(( fbase = fopen( BASEF, "w+" )) == NULL ){

		     fprintf( stderr, "Не могу открыть базу данных %s\n",

			      BASEF );

		     exit(1);

		}

		fprintf( stderr, "База создана\n" );

	}

}

void

closeBase (void){

	fclose( fbase );

}

/* Учтите, что если вы записываете в файл структуры, то в файле

не будет разделения на строки - файл НЕТЕКСТОВЫЙ! Поэтому и

читать такой файл можно только структурами: read(), fread()

(но не scanf-ом и не fgets-ом)

 */

 

/* Поиск по ключу .

   Выдать (-1), если записи с данным ключом нет,

   иначе   - номер слота, где содержится запись с данным ключом.

 */

int

bget (int key)

{

	int n;

	/* последовательно просмотреть весь файл */

	rewind( fbase );

	/* в начало файла. Равно fseek(fbase, 0L, 0); */

	n = 0 ;

	/* int    сколько_элементов_массива_действительно_считано =

	 * fread( адрес_массива_куда_считывать,

	 *        размер_одного_элемента_массива,

	 *        сколько_элементов_считывать_в_массив, канал );

	 * Заметьте, что количество данных задается НЕ в байтах,

	 * а в 'штуках'

	 */

	while( fread( &tmp, sizeof( tmp ), 1, fbase ) == 1 ){

		if( tmp.b_key == key )

			return n;

		n++;

	}

	return (-1);    /* не найдено */

}

/* модифицировать запись с индексом ind */

void

bmod (

    int ind,

    int key,       /* новый ключ */

    char *val      /* новое значение */

)

{

	struct data new;

	fseek( fbase, (long) sizeof( struct data ) * ind, 0 );

	new.b_key = key;

	strncpy( new.b_val, val, VLEN );

	/* int    сколько_элементов_массива_действительно_записано =

	 * fwrite( адрес_массива_который_записывать,

	 *         размер_одного_элемента_массива,

	 *         сколько_элементов_массива_записывать, канал );

	 */

	if( fwrite( &new, sizeof new , 1, fbase ) != 1 )

	    fprintf( stderr, "Ошибка записи.\n" );

}

/* удаление записи по ключу */

int

bdel (int key){

	int ind = bget( key );

	if( ind == -1 )

		return (-1);        /* записи с таким ключом нет */

	bmod( ind, KEY_FREE, "" );  /* записать признак свободного места */

	return 0;

}

/* Служебная процедура дописи к концу файла */

void

bappend (int key, char *val)

{

		struct data new;

		/* встать на конец файла */

		fseek( fbase, 0L, 2 );

		/* и записать новую структуру в конец */

		new.b_key = key;

		strncpy( new.b_val, val, VLEN );

		fwrite( &new, sizeof( struct data ) , 1, fbase );

}

/* добавление новой записи. Если запись с таким ключом уже есть    выдать ошибку

 */

int

bput (int key, char *val)

{

	int i = bget( key );

	if( i != -1 )

		return (-1);    /* запись уже есть */

	/* найти свободное место */

	i = bget( KEY_FREE );

	if( i == -1 ) {         /* нет свободных мест */

		bappend( key, val );

		return 0;

	}

	/* иначе свободное место найдено.

	 * Заменяем дырку на полезную информацию */

	bmod( i, key, val );

}

/* распечатать всю базу данных подряд */

void

bprint (void){

	int n;

	int here = 0;

	rewind( fbase );

	n = 0;

	printf( "-номер--ключ-------значение-----------------\n" );

	while( fread( &tmp, sizeof tmp, 1, fbase ) == 1 ){

		if( tmp.b_key == KEY_FREE ){

			n++;

			continue;

		}

		printf( "#%-2d| %6d\t| %s\n", n, tmp.b_key, tmp.b_val );

		here ++; n++;

	}

	printf( "--------------------------------------------\n" );

	printf( "Длина базы:%d Занято:%d\n\n", n, here );

}

/* замена поля val у записи с ключом key */

int

bchange (int key, char *val)

{

	int ind;

	ind = bget( key );

	if( ind == -1 ){

		/* запись с таким ключом не существует */

		/* Добавить как новую запись */

		bput( key, val );

		return 0;

	}

	bmod( ind, key, val );

	return 1;

}

/* Аналогичная функция, но использующая другой способ.

 * Кроме того, если такой ключ отсутствует - ничего не делается

 */

int

bchg (int key, char *val)

{

	struct data d;

	rewind( fbase );        /* в начало файла */

	while( fread( &d, sizeof d, 1, fbase ) == 1 ){

		/* поиск ключа */

		if( d.b_key == key ){

			/* вернуться назад от текущей позиции */

			fseek( fbase, - (long) sizeof d, 1 );

			/* не годится   (long)-sizeof d !!! */

			d.b_key = key;

			strncpy( d.b_val, val, VLEN );

			fwrite( &d, sizeof d, 1, fbase );

			/* между fread и fwrite должен быть

			 * хоть один fseek. (магическое заклинание!)

			 */

			fseek( fbase, 0L, 1);  /* никуда не сдвигаться */

			return 0;              /* сделано */

		}

	}

	return (-1);    /* такого ключа не было */

}

/* Пример */

void

main (void){

	int i;

	initBase();

	bprint();

	bdel( 8 );

	printf( "Создаем базу данных\n" );

	bput( 1, "строка 1" );

	bput( 2, "строка 2" );

	bput( 3, "строка 3" );

	bput( 4, "строка 4" );

	bprint();

	printf( "Удаляем записи с ключами 1 и 3\n" );

	bdel( 1 );

	bdel( 3 );

	bprint();

	printf( "Добавляем записи 5, 6 и 7\n" );

	bput( 5, "строка 5" );

	bput( 6, "строка 6" );

	bput( 7, "строка 7" );

	bprint();

	printf( "Заменяем строку в записи с ключом 2\n" );

	bchange( 2, "новая строка 2" );

	bprint();

	printf( "Заменяем строку в записи с ключом 4\n" );

	bchg( 4, "новая строка 4" );

	bprint();

	printf( "Заменяем строку в записи с ключом 6 и ключ 6 на 8\n" );

	i = bget( 6 );

	printf( "Сейчас запись с ключом 6 содержит \"%s\"\n",

		tmp.b_val );

	bmod( i, 8, "Новая строка 6/8" );

	bprint();

	closeBase();

}

[Назад][Содержание][Вперед]

Используются технологии uCoz