ЗВІТ
про виконання лабораторної роботи №1
на тему: «Послідовний метод доступу до файлів на зовнішніх запам’ятовуючих пристроях»
з курсу «Організація баз даних і знань»
для студентів напряму «Комп’ютерні науки»
Мета роботи
Мета роботи – розглянути органiзацiю i ведення файлiв послiдовного доступу; набути практичнi навички у програмуваннi алгоритмiв роботи з файлами послiдовного доступу.
Теоретичні відомості
Записи у простому послiдовному файлi доступнi лише послiдовно один за одним. Наприклад, можна звернутися до n-го запису тiльки пiсля звертання до 1, 2 , ... , n-1 записiв.
для того, щоб видалити запис з файлу, необхiдно створити копiю файлу, у якiй цей запис є вiдсутнiм;
для того, щоб помiстити запис у файл, також необхiдно створити копiю файлу, у яку цей новий запис входить;
щоб змiнити хоча б одне з полiв у записi, необхiдно створити копiю файлу, який мiститиме модифiкований запис.
При послiдовному методi доступу значення ключiв фiзичних записiв знаходяться у логiчнiй послiдовностi.
Ефективність доступу – нехай вибрано один фiзичний запис, i належить вибрати iнший з бiльшим значенням ключа. У найгiршому випадку для вибору потрiбного запису необхiдно переглянути всi записи бази даних, а у кращому достатньо вибрати наступний запис. Для того, щоб виявити необхiдний запис у послiдовному файлi, який складається з N записiв, необхiдно переглянути у середньому N/2 записiв.
Ефективність використання пам'ятi близька до 100%. Зберiгання фiзичних записiв у логiчнiй послiдовностi можна використовувати для прискорення доступу, якщо перед звертанням до власне записiв бази даних перевiряти значення ключiв.
Завдання
Створити програму для підтримки послідовного методу доступу до файлу бази даних на тему «Магазин будівельних матеріалів», яка реалізовує наступні функції:
Створення файлу бази даних
Друк бази даних
Пошук запису за введеним ключем
Видалення запису за введеним ключем
Вставлення запису
Модифікація запису
Оптимізувати розроблену програму шляхом створення файлу групової обробки та реалізацією наступних додаткових функцій:
Створення файлу групової обробки
Внесення змін у файл бази даних
Текст програми
Код файлу «Main.cpp»:
#include<iostream>
#include<Windows.h>
#include"BuildingDatabase.h"
using namespace std;
int main()
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
short choice, M;
while (1)
{
/*Головне Меню*/
system("cls");
cout << "\n\t1.Створити базу даних"
<< "\n\n\t2.Додати дані про новий товар"
<< "\n\t3.Редагувати дані про товар"
<< "\n\t4.Видалити дані про товар"
<< "\n\n\t5.Пошук"
<< "\n\t6.Вивести на екран"
<< "\n\t7.Друкувати у файл"
<< "\n\n\t8.Застосувати зміни"
<< "\n\n\t9.Вивести файл групової обробки"
<< "\n\t10.Видалити файл групової обробки"
<< "\n\n\t0.Вихід";
cout << "\n\n\tОберіть операцію:\n";
M: cout << "\t -> "; cin >> choice;
switch (choice)
{
case 1: BuildingDatabase::CreateDatabase(); break;
case 2: BuildingDatabase::Insert(); break;
case 3: BuildingDatabase::Edit(); break;
case 4: BuildingDatabase::Delete(); break;
case 5: BuildingDatabase::Search(); break;
case 6: BuildingDatabase::Print(); break;
case 7: BuildingDatabase::PrintToFile(); break;
case 8: BuildingDatabase::ApplyHandler(); break;
case 9: BuildingDatabase::PrintHandler(); break;
case 10: BuildingDatabase::DeleteHandler(); break;
case 0: exit(1); break;
default: cout << "\nБудь ласка, повторіть спробу...\n"; goto M; break;
}
}
cout << "\n\n";
return 1;
}
Код файлу «Building.h»:
#pragma once
class Building
{
public:
int id;
char name[30];
char category[30];
char manufacturer[20];
char size[15];
double weight;
double price;
int count;
char describe[40];
bool is_discount;
short operation;
};
Код файлу «BuildingDatabase.h»:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <algorithm>
#include "Building.h"
using namespace std;
static Building building;
static fstream database;
static fstream tmp;
class BuildingDatabase
{
public:
static void CreateDatabase();
static void Insert();
static void Edit();
static void Delete();
static void Search();
static void Print();
static void PrintToFile();
static void ApplyHandler();
static void PrintHandler();
static void DeleteHandler();
private:
static bool Exist(int);
static void PrintExact(Building);
static void InsertToHandler();
static void InsertToDatabase();
static void EditInDatabase();
static void DeleteFromDatabase();
static void RemoveColize();
};
Код файлу «BuildingDatabase.cpp»:
#include "BuildingDatabase.h"
void BuildingDatabase::CreateDatabase()
{
char p;
system("cls");
cout << "\nВи впевнені, що хочете створити нову базу даних? Стара база даних буде знищена.";
cout << "\n\n (1 - ТАК, 0 - НІ) -> "; cin >> p;
if (p == '1')
{
database.open("database", ios_base::out);
database.clear();
database.close();
}
}
void BuildingDatabase::Insert()
{
system("cls");
cout << "Будь ласка, введіть інформацію про новий товар...";
cout << "\nID -> "; cin >> building.id;
if (Exist(building.id))
{
cout << "\nТовар з таким ID вже існує...\n\n";
system("pause");
return;
}
getchar();
cout << "\nНазва товару -> "; gets_s(building.name);
cout << "Категорія товару -> "; gets_s(building.category);
cout << "Виробник -> "; gets_s(building.manufacturer);
cout << "\nРозмірність товару -> "; gets_s(building.size);
cout << "Вага (г) -> "; cin >> building.weight;
cout << "Ціна за одиницю (грн) -> "; cin >> building.price;
cout << "Кількість -> "; cin >> building.count;
getchar();
cout << "\nОпис -> "; gets_s(building.describe);
cout << "\nЧи діє акція (1 - ТАК, 0 - НІ) -> "; cin>>building.is_discount;
building.operation = 1;
char choice;
cout << "\nОберіть спосіб внесення даних:"
<< "\n1.Внести в базу даних"
<< "\n2.Внести в файл групової обробки"
<< "\n\n -> ";
cin >> choice;
if (choice == '1')
InsertToDatabase();
else if (choice == '2')
InsertToHandler();
}
void BuildingDatabase::Edit()
{
system("cls");
cout << "Введіть ID товару, дані про який ви хочете змінити...";
cout << "\n\nID -> "; cin >> building.id;
if (!Exist(building.id))
{
cout << "\nТовару з таким ID в базі даних не виявлено...\n\n";
system("pause");
return;
}
cout << "\nБудь ласка, введіть нову інформацію про товар...\n";
getchar();
cout << "\nНазва товару -> "; gets_s(building.name);
cout << "Категорія товару -> "; gets_s(building.category);
cout << "Виробник -> "; gets_s(building.manufacturer);
cout << "\nРозмірність товару -> "; gets_s(building.size);
cout << "Вага (г) -> "; cin >> building.weight;
cout << "Ціна за одиницю (грн) -> "; cin >> building.price;
cout << "Кількість -> "; cin >> building.count;
getchar();
cout << "\nОпис -> "; gets_s(building.describe);
cout << "\nЧи діє акція (1 - ТАК, 0 - НІ) -> "; cin >> building.is_discount;
building.operation = 2;
char choice;
cout << "\nОберіть спосіб внесення змін:"
<< "\n1.Редагувати в базі даних"
<< "\n2.Внести в файл групової обробки"
<< "\n\n -> ";
cin >> choice;
if (choice == '1')
EditInDatabase();
else if (choice == '2')
InsertToHandler();
}
void BuildingDatabase::Delete()
{
system("cls");
cout << "Введіть ID товару, дані про який ви хочете видалити...";
cout << "\n\nID -> "; cin >> building.id;
if (!Exist(building.id))
{
cout << "\nТовару з таким ID в базі даних не виявлено...\n\n";
system("pause");
return;
}
building.operation = 3;
char choice;
cout << "\nОберіть спосіб видалення даних:"
<< "\n1.Видалити з бази даних"
<< "\n2.Внести в файл групової обробки"
<< "\n\n -> ";
cin >> choice;
if (choice == '1')
DeleteFromDatabase();
else if (choice == '2')
InsertToHandler();
}
void BuildingDatabase::InsertToHandler()
{
database.open("handler", ios_base::in);
if (!database)
{
database.open("handler", ios_base::out);
database.write((char*)&building, sizeof(building));
database.close();
return;
}
tmp.open("tmp", ios_base::out);
Building temp_building;
bool p = false;
database.read((char*)&temp_building, sizeof(temp_building));
while (!database.eof())
{
if (temp_building.id <= building.id)
tmp.write((char*)&temp_building, sizeof(temp_building));
else
{
p = true;
tmp.write((char*)&building, sizeof(building));
tmp.write((char*)&temp_building, sizeof(temp_building));
database.read((char*)&temp_building, sizeof(temp_building));
while (!database.eof())
{
tmp.write((char*)&temp_building, sizeof(temp_building));
database.read((char*)&temp_building, sizeof(temp_building));
}
break;
}
database.read((char*)&temp_building, sizeof(temp_building));
}
if (!p) tmp.write((char*)&building, sizeof(building));
database.close();
tmp.close();
system("del handler");
system("rename tmp handler");
}
void BuildingDatabase::InsertToDatabase()
{
database.open("database", ios_base::in);
tmp.open("tmp", ios_base::out);
Building temp_building;
bool p = false;
database.read((char*)&temp_building, sizeof(temp_building));
if (database.eof())
tmp.write((char*)&building, sizeof(building));
else
{
while (!database.eof())
{
if (temp_building.id < building.id)
tmp.write((char*)&temp_building, sizeof(temp_building));
else
{
p = true;
tmp.write((char*)&building, sizeof(building));
tmp.write((char*)&temp_building, sizeof(temp_building));
database.read((char*)&temp_building, sizeof(temp_building));
while (!database.eof())
{
tmp.write((char*)&temp_building, sizeof(temp_building));
database.read((char*)&temp_building, sizeof(temp_building));
}
break;
}
database.read((char*)&temp_building, sizeof(temp_building));
}
if (!p) tmp.write((char*)&building, sizeof(building));
}
database.close();
tmp.close();
system("del database");
system("rename tmp database");
}
void BuildingDatabase::EditInDatabase()
{
Building temp_building;
database.open("database", ios_base::in);
tmp.open("tmp", ios_base::out);
database.read((char*)&temp_building, sizeof(temp_building));
while (!database.eof())
{
if (temp_building.id == building.id)
{
tmp.write((char*)&building, sizeof(building));
database.read((char*)&building, sizeof(building));
while (!database.eof())
{
tmp.write((char*)&building, sizeof(building));
database.read((char*)&building, sizeof(building));
}
break;
}
tmp.write((char*)&temp_building, sizeof(temp_building));
database.read((char*)&temp_building, sizeof(temp_building));
}
database.close();
tmp.close();
system("del database");
system("rename tmp database");
}
void BuildingDatabase::DeleteFromDatabase()
{
Building temp_building;
database.open("database", ios_base::in);
tmp.open("tmp", ios_base::out);
database.read((char*)&temp_building, sizeof(temp_building));
while (!database.eof())
{
if (temp_building.id != building.id)
{
tmp.write((char*)&temp_building, sizeof(temp_building));
}
database.read((char*)&temp_building, sizeof(temp_building));
}
database.close();
tmp.close();
system("del database");
system("rename tmp database");
}
void BuildingDatabase::Search()
{
system("cls");
short choice;
cout << "\n Оберіть поле, по якому ви хочете здійснювати пошук...\n";
cout << "\n1.ID\t\t\t6.Вага"
<< "\n2.Назва товару\t\t7.Ціна за одиницю"
<< "\n3.Категорія товару\t8.Кількість"
<< "\n4.Виробник\t\t9.Опис"
<< "\n5.Розмірність\t\t10.Дійсність акції"
<<"\n\n0.Відміна\n";
cout << "\n -> "; cin >> choice;
if (choice == 0) return;
char tmp[40];
cout << "\n\nВведіть пошуковий запит -> ";
if((choice < 2 || choice > 5) && choice != 9) cin >> tmp;
else {
getchar();
gets_s(tmp);
}
database.open("database", ios_base::in);
database.read((char*)&building, sizeof(building));
while (!database.eof())
{
switch (choice)
{
case 1:
if (atoi(tmp) == building.id)
PrintExact(building);
break;
case 2:
if (strcmp(tmp, building.name) == 0)
PrintExact(building);
break;
case 3:
if (strcmp(tmp, building.category) == 0)
PrintExact(building);
break;
case 4:
if (strcmp(tmp, building.manufacturer) == 0)
PrintExact(building);
break;
case 5:
if (strcmp(tmp, building.size) == 0)
PrintExact(building);
break;
case 6:
if (atof(tmp) == building.weight)
PrintExact(building);
break;
case 7:
if (atof(tmp) == building.price)
PrintExact(building);
break;
case 8:
if (atoi(tmp) == building.count)
PrintExact(building);
break;
case 9:
if (strcmp(tmp, building.describe) == 0)
PrintExact(building);
break;
case 10:
if (atoi(tmp) == building.is_discount)
PrintExact(building);
break;
}
database.read((char*)&building, sizeof(building));
}
database.close();
cout << "\n\n";
system("pause");
}
void BuildingDatabase::ApplyHandler()
{
system("cls");
tmp.open("handler", ios_base::in);
if (!tmp) {
cout << "Файл групової обробки відсутній...\n\n";
system("pause");
return;
}
tmp.close();
cout << "\nТриває застосування...\n";
RemoveColize();
fstream result;
Building temp_building;
database.open("database", ios_base::in);
tmp.open("handler", ios_base::in);
result.open("tmp", ios_base::out);
database.read((char*)&building, sizeof(building));
tmp.read((char*)&temp_building, sizeof(temp_building));
while (!database.eof() || !tmp.eof())
{
while (temp_building.operation == 1 && !tmp.eof())
{
if (database.eof())
{
result.write((char*)&temp_building, sizeof(temp_building));
tmp.read((char*)&temp_building, sizeof(temp_building));
break;
}
if (building.id < temp_building.id)
{
result.write((char*)&building, sizeof(building));
database.read((char*)&building, sizeof(building));
}
else
{
result.write((char*)&temp_building, sizeof(temp_building));
tmp.read((char*)&temp_building, sizeof(temp_building));
}
}
while (temp_building.operation == 2 && !tmp.eof())
{
if (temp_building.id == building.id)
{
result.write((char*)&temp_building, sizeof(temp_building));
tmp.read((char*)&temp_building, sizeof(temp_building));
database.read((char*)&building, sizeof(building));
}
else
{
result.write((char*)&building, sizeof(building));
database.read((char*)&building, sizeof(building));
}
}
while (temp_building.operation == 3 && (!tmp.eof() || !database.eof()))
{
if (temp_building.id != building.id)
{
result.write((char*)&building, sizeof(building));
database.read((char*)&building, sizeof(building));
}
else
{
database.read((char*)&building, sizeof(building));
tmp.read((char*)&temp_building, sizeof(temp_building));
}
}
if (tmp.eof() && !database.eof())
{
result.write((char*)&building, sizeof(building));
database.read((char*)&building, sizeof(building));
}
}
database.close();
tmp.close();
result.close();
system("del database");
system("del handler");
system("rename tmp database");
cout << "\nГотово...";
system("pause");
}
void BuildingDatabase::RemoveColize()
{
vector<Building> v;
tmp.open("handler", ios_base::in);
tmp.read((char*)&building, sizeof(building));
while (!tmp.eof())
{
v.push_back(building);
tmp.read((char*)&building, sizeof(building));
}
tmp.close();
int j = 0, tmp_id;
for (int i = v.size() - 1; i >= 0; i--)
{
tmp_id = v[i].id;
if (i != 0) {
j = i;
while (v[j - 1].id == tmp_id)
{
v.erase(v.begin() + j - 1);
j--;
if (j == 0) break;
}
i = j;
}
}
tmp.open("tmp", ios_base::out);
for (int i = 0; i < v.size(); i++) {
tmp.write((char*)&v[i], sizeof(v[i]));
}
tmp.close();
system("del handler");
system("rename tmp handler");
}
bool BuildingDatabase::Exist(int id)
{
bool p = false;
database.open("database", ios_base::in);
database.read((char*)&building, sizeof(building));
while (!database.eof())
{
if (id == building.id)
{
database.close();
p = true;
break;
}
database.read((char*)&building, sizeof(building));
}
database.close();
building.id = id;
return p;
}
void BuildingDatabase::Print()
{
system("cls");
database.open("database", ios_base::in);
database.read((char*)&building, sizeof(building));
if (database.eof()) cout << "База даних порожня...";
while (!database.eof())
{
PrintExact(building);
database.read((char*)&building, sizeof(building));
}
database.close();
cout << "\n\n";
system("pause");
}
void BuildingDatabase::PrintToFile()
{
tmp.open("database.txt", ios_base::out);
tmp.clear();
tmp << left << setw(4) << "ID"
<< left << setw(30) << "Назва товару"
<< left << setw(30) << "Категорія товару"
<< left << setw(20) << "Виробник"
<< left << setw(15) << "Розмірність"
<< left << setw(6) << "Вага"
<< left << setw(16) << "Ціна за одиницю"
<< left << setw(10) << "Кількість"
<< left << setw(40) << "Опис"
<< left << setw(5) << "Акції\n\n";
database.open("database", ios_base::in);
database.read((char*)&building, sizeof(building));
while (!database.eof())
{
tmp << left << setw(4) << building.id
<< left << setw(30) << building.name
<< left << setw(30) << building.category
<< left << setw(20) << building.manufacturer
<< left << setw(15) << building.size
<< left << setw(6) << building.weight
<< left << setw(16) << building.price
<< left << setw(10) << building.count
<< left << setw(40) << building.describe
<< left << setw(5) << building.is_discount
<< "\n";
database.read((char*)&building, sizeof(building));
}
tmp.close();
database.close();
system("explorer.exe database.txt");
}
void BuildingDatabase::PrintExact(Building building)
{
cout << "\nID:\t\t" << building.id
<< "\nНазва товару:\t"; puts(building.name);
cout << "Категорія товару: " << building.category
<< "\nВиробник:\t" << building.manufacturer
<< "\nРозмірність:\t" << building.size
<< "\nВага:\t\t" << building.weight << " г"
<< "\nЦіна за одиницю:" << building.price << " грн"
<< "\nКількість:\t" << building.count
<< "\nОпис:\t\t"; puts(building.describe);
cout << "Акції:\t\t" << building.is_discount;
cout << "\n";
}
void BuildingDatabase::PrintHandler()
{
system("cls");
tmp.open("handler", ios_base::in);
if (!tmp) {
cout << "Файл групової обробки відсутній...\n\n";
tmp.close();
system("pause");
return;
}
tmp.read((char*)&building, sizeof(building));
if (tmp.eof()) cout << "Файл групової обробки порожній...";
while (!tmp.eof())
{
PrintExact(building);
cout << "Операція:\t" << building.operation << "\n";
tmp.read((char*)&building, sizeof(building));
}
tmp.close();
cout << "\n\n";
system("pause");
}
void BuildingDatabase::DeleteHandler()
{
system("cls");
tmp.open("handler", ios_base::in);
if (tmp) {
cout << "\nВидалення...";
tmp.close();
system("del handler");
cout << "\n\nГотово...";
}
else
{
tmp.close();
cout << "Файл групової обробки відсутній...\n\n";
}
system("pause");
}
Скріншот
/
Висновки
На даній лабораторній роботі було ознайомлено з основними принципами послідовного методу доступу до файлів на зовнішніх запам’ятовуючих пристроях, а також реалізовано консольну програму мовою програмування C++ для створення та роботи з базою даних з використанням файлу групової обробки.
В ході розробки програми було розроблено алгоритми для реалізації основних операцій, які можна здійснювати над базою даних, а саме:
Створення файлу бази даних;
Друк бази даних;