Компьютеры
и программирование

База данных на файлах: запись с уникальным идентификатором

Задача: разработать на C++ справочно-информационную систему, в базу данных которой (в файле) данные записываются с уникальным идентификационным номером (ID). Вариант с ручным внесением идентификационного номера исключается как неуважительный к пользователю. Да и запутаться легко, внося ID вручную.

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

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

Рассмотрим подробнее, как реализуется запись даннных с уникальным идентификационным номером. Наиболее важны два момента.

1. Происходит открытие файла данных о читателях. Данные считываются из файла. Из вновь созданного массива принимаются данные о номере идентификатора читалеля. Если этот номер превышает количество элементов (записях о читателях), то данные о новом читателе в базу данных записываются с номером, на 1 больше последнего номера из базы данных. Если не превышает, то номер присваивается на единицу больше числа элементов массива (читателей).

Код C++

Reader* reader_arr = new Reader[n];

FILE * ff;

 

int b = 0;

int c = 0;

 

fstream fs;

fs.open ("Reader.dat");

if (fs.is_open())

{

ff = fopen("Reader.dat","rb");

int fsize;

fseek(ff,0,SEEK_END);

fsize = ftell(ff);

b = fsize / sizeof(Reader);

 

Reader* start_arr2 = new Reader[b]; //создаётся новый массив из данных структуры

fseek(ff,0,SEEK_SET);

fread(start_arr2,sizeof(Reader),b,ff);

c = start_arr2[b - 1].id + 1; //присваиваются данные об ID последней записи масссива

fclose( ff);

fs.close();

}

 

for (int i = 0; i < n; i++)

{

if (c >= b)

reader_arr[i].id = c + i;

else

reader_arr[i].id = b + i;

cout << "Enter name and surname: "; //далее записываются все

cin.getline(reader_arr[i].name_surname, 30); //необходимые данные о читателях

cout << "Enter day of birth: ";

cin >> reader_arr[i].birth_date.date;

cout << "Enter month of birth: ";

cin >> reader_arr[i].birth_date.month;

cout << "Enter year of birth: ";

cin >> reader_arr[i].birth_date.year;

cin.get();

cout << "Enter profession: ";

cin.getline(reader_arr[i].profession, 20);

cout << "Enter education: ";

cin.getline(reader_arr[i].education, 16);

cout << "Enter address: ";

cin.getline(reader_arr[i].address, 50);

cout << "Enter phone: ";

cin >> reader_arr[i].phone;

cin.get();

cout << endl;

}

ff = fopen("Reader.dat","a");

fwrite(reader_arr,sizeof(Reader),n,ff); //все внесённые данные записываются

fclose( ff);

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

Код C++

if (t == 2)

{

int b;

int count1 = 0;

int count2 = 0;

char Slogin[16];

char Spassw[16];

cout << "Enter login: ";

cin >> Slogin;

cin.get();

 

FILE * fn;

 

fn = fopen("Lib.dat","rb");

int fsize;

fseek(fn,0,SEEK_END);

fsize = ftell(fn);

b = fsize / sizeof(Librarian);

 

Librarian* librarian_arr2 = new Librarian[b];

 

fseek(fn,0,SEEK_SET);

fread(librarian_arr2,sizeof(Librarian),b,fn);

 

fclose(fn);

for (int i = 0; i < b; i++)

{

while (strstr(librarian_arr2[i].login, Slogin))

{

cout << "Enter password: ";

cin >> Spassw;

while (strstr(librarian_arr2[i].password, Spassw))

{

menu();

count2++;

break;

}

count1++;

break;

}

}

Внимание! Закрытие файла с данными о библиотекарях должно произойти сразу же после считывания массива данных о библиотекарях. Если задать закрыте ниже, например, после кода, отвечающего за ввод и приём данных логина и пароля, то файл уже при внесении или редактировании данных о библиотекарях будет открытым и новые данные в него не запишутся.

Весь раздел "Программирование С++"