
C _Учебник_МОНУ
.pdf
Файли |
419 |
Приклад 12.14 Створити бінарний файл, що містить інформацію про товари: найменування товару, ціна і кількість. Відібрати товари, кількість яких є менше за 30 одиниць. Відредагувати один із записів. Вилучити один із записів. Номер запису для редагування й вилучення ввести з клавіатури.
Розв‟язок. Окрім зазначених алгоритмів опрацювання бінарного файла у цій програмі наведено засоби редагування і вилучення певного запису з файла. Номер такого запису вводиться за допомогою вікна введення InputBox(), синтаксис та приклад роботи якого розглядались у прикладі 6.7. Вікно введення, створене у цій програмі командою
AnsiString snom=InputBox("Який рядок бажаєте вилучити?", "Введіть номер рядка", "1");
матиме вигляд:
Вікно форми проекту з результатами роботи програми:
Текст програми: int n, flag;
//При дописуванні даних у кінець файла flag становитиме 0,
//а при редагуванні даних flag буде мати значення 1;
//n визначатиме номер запису у файлі, причому номер рахуватиметься за кількістю
//рядків, відбитих у компоненті StringGrid, хоча у файлі відлік розпочинається з 0
FILE *f;
char s[]="товар.dat"; // Ім‟я файла struct tovar
{ char N[20]; |
float price; int kol; }; |
tovar t; |
|
Файли |
421 |
i++;
}
fclose(f);
}
// Кнопка “Товари, кількість яких є менше за 30”
void __fastcall TForm1::Button3Click(TObject *Sender)
{if((f=fopen(s,"rb+"))==NULL)
{ShowMessage("Файла немає!"); return; } Memo1->Lines->Clear( ); while(fread(&t,sizeof(tovar),1,f))
if(t.kol<30) Memo1->Lines->Add(AnsiString(t.N)+" "+
FormatFloat("0.00",t.price)+" "+IntToStr(t.kol)); fclose(f);
}
// Кнопка “Видалити запис”
void __fastcall TForm1::Button4Click(TObject *Sender)
{if ((f=fopen(s,"rb"))==NULL)
{ShowMessage("Файла немає!"); return; }
FILE* tmp; // Оголошення вказівника на тимчасовий файл if((tmp=fopen("tmp.dat","wb+"))==NULL) //і створення його.
{ ShowMessage("Файла немає!"); return; }
AnsiString snom=InputBox("Який рядок бажаєте вилучити?", "Введіть номер рядка", "1");
if(snom=="") { ShowMessage("Ви не ввели дані"); return; } int kk, k=StrToInt(snom); while((fread(&t,sizeof(tovar),1,f)))
{kk=ftell(f)/sizeof(tovar); // Функція ftell(f) визначає кількість
// прочитаних байтів, а в змінній kk обчислюється поточний номер запису
if(k==kk) continue; // Пропуск зазначеного запису fwrite(&t,sizeof(tovar),1,tmp);
}
fclose(f);
fseek(tmp,0,0); // Перехід на початок тимчасового файла f=fopen(s, "wb+"); // і нове створення файла для зчитування і записування while((fread(&t,sizeof(tovar),1,tmp))) fwrite(&t,sizeof(tovar),1,f);
fclose(tmp); fclose(f);
remove("tmp.dat"); |
// Видалення допоміжного файла |
Button2Click(NULL); |
// Переглядання даних після видалення |
}
// Кнопка “ Редагувати запис”
void __fastcall TForm1::Button5Click(TObject *Sender) { if((f=fopen(s,"rb+"))==NULL)
{ ShowMessage("Файла немає!"); return; }
AnsiString snom=InputBox("Який рядок бажаєте коригувати?", "Введіть номер рядка.\nНові значення вводитимуться \n
з відповідних компонентів Edit", "");
if(snom=="") {ShowMessage("Ви не ввели дані"); return;} n=StrToInt(snom);

Файли |
423 |
Вікно форми проекту з результатами роботи програми:
Текст програми:
#include <fstream.h> fstream f;
char *filename=new char[30]; struct student
{ char name[30], surname[20]; int inf, mat, fiz; };
student A;
void __fastcall TForm1::FormCreate(TObject *Sender)
{ AnsiString fn=InputBox("Відкриття файла", "Введіть ім'я файла","stud.dat");
if(fn=="") { ShowMessage("Ви не ввели дані"); return; } strcpy(filename,fn.c_str());
// Створення чи відкриття файла f.open(filename,ios::out|ios::app|ios::binary); f.clear(); // Очищення потоку
if(!f) { ShowMessage("Помилка відкриття файла"); return; } f.close();
}
// Кнопка “Записати дані до файла”
void __fastcall TForm1::Button1Click(TObject *Sender)
{f.open(filename,ios::out|ios::app|ios::binary);
f.clear();
if(!f) { ShowMessage("Помилка відкриття файла "); return; } f.seekp(0,ios::end); // Позиціонування на кінець файла strcpy(A.name, Edit1->Text.c_str());
strcpy(A.surname, Edit2->Text.c_str()); A.inf=StrToInt(Edit3->Text); A.mat=StrToInt(Edit4->Text); A.fiz=StrToInt(Edit5->Text);
f.write((char*)&A, sizeof(A)); // Записування даних до файла f.close();
}
Файли |
425 |
12.3.3 Опрацювання бінарних файлів за допомогою дескрипторів
Для опрацювання бінарних файлів через дескриптори застосовуються функції, які розглянуто в п. 12.2.6.
Нагадаємо порядок дій для записування даних у файл на такому прикладі:
int f; //Оголошення дескриптора f=FileOpen("a.dat",fmOpenWrite);// Відкриття файла для записування
int kb=FileSeek(f, 0, 2); |
// Встановлення позиції на кінець файла |
|
//і одночасне визначення розміру файла |
int k=25; |
|
//Записування до файла значення k |
цілого типу розміром sizeof(int) |
FileWrite(f, &k, sizeof(int)); |
|
FileClose(f); |
// Закриття файла |
Відкриття файла і зчитування даних з нього виконуватиметься в такий спосіб:
f=FileOpen("a.dat", fmOpenRead); FileRead(f, (int*)&k, sizeof(int)); FileClose(f);
Відкриття файла для зчитування-записування здійснюватиметься наступною послідовністю команд:
f=FileOpen("a.dat",fmOpenReadWrite); if(f != -1)
/* Далі можна опрацьовувати файл: читати чи записувати данні, встановивши потрібну позицію за допомогою функції FileSeek(). */
Ще раз зауважимо, що за допомогою дескрипторів можна створювати і опрацьовувати файли з даними будь-якого типу.
Розглянемо приклад роботи з бінарним файлом через дескриптор.
Приклад 12.16 Створити файл з інформацією про авіарейси: номер рейсу, маршрут руху, час відправлення (за шаблоном ЧЧ:ММ), час прибуття в пункт призначення (за шаблоном ЧЧ:ММ), при чому з клавіатури мають вводитися: номер рейсу, маршрут руху, час відправлення і тривалість польоту, а час прибуття в пункт призначення слід обчислити. Передбачити можливість вилучення даних про нічні рейси (з 00:00 по 5:00). Відсортувати данні за часом відправлення літаків.
Розв‟язок. У програмі за вибором користувача передбачено можливість виведення даних у компонент Memo1 чи то у компонент StringGrid1, який у програмі перейменовано для зручності на SG1. Тут спеціально наведено засоби виведення даних в обидва компоненти, хоча вочевидь, що в цьому прикладі зовні краще сприймається інформація у StringGrid.

426 |
Розділ 12 |
При перегляданні даних обома способами вікно форми матиме вигляд
Форма після сортування авіарейсів за часом відправлення літаків:
Для розв‟язування завдання вилучення нічних рейсів запропоновано два способи. У першому – організовано допоміжний динамічний масив, до якого обираються відомості про авіарейси, за винятком нічних. Початковий файл вилучається і створюється заново, після чого до нього записуються відомості з динамічного масиву, а пам‟ять від динамічного масиву звільнюється. Порівняно з першим способом, другий має більш компактний програмний код. У ньому організовано допоміжний файл, в який обираються авіарейси, окрім нічних. Після цього початковий файл вилучається, а допоміжний перейменовується на ім‟я початкового файла. Результати обох способів є аналогічні і на формі вони мають такий вигляд:
Файли |
427 |
Окрім зазначених алгоритмів опрацювання бінарного файла через дескриптор, у програмі наведено засоби вилучення всіх даних файла, тобто обнуління файла. Перед вилученням даних у програмі передбачено виведення діалогового повідомлення MessageDlg(). На відміну від повідомлення ShowMessage(), яке виводить лише вікно з відповідним текстом повідомлення та однією командною кнопкою з надписом ОК, при натисканні на яку вікно повідомлення зникає, діалогове повідомлення MessageDlg() може моделювати кількість кнопок із зазначеними надписами і передбачає можливість програмного реагування залежно від того, яку саме кнопку було натиснуто.
Синтаксис функції MessageDlg()є такий:
int MessageDlg( const AnsiString Msg, TMsgDlgType DlgType, TMsgDlgButtons Buttons, int HelpCtx);
де Msg – текст повідомлення;
DlgType задає характер повідомлення, а саме вигляд піктограми ліворуч від тексту повідомлення. Існують такі можливі значення цього параметра:
mtWarning – зауваження , mtError – помилка
, mtInformation – інформа-
ційне повідомлення , mtConfirmation – запит підтвердження
, mtCustom – без рисунка;
Buttons задає кількість і вигляд кнопок. Можливі значення цього парамет-
ра: mbYesNoCancel, mbYesNoAllCancel, mbOKCancel, mbAbortRetryIgnore, mbAbortIgnore. Тобто кожна кнопка має відповідне константне значення. Після натискання певної кнопки відповідне константне значення повертається функцією як результат виконання;
HelpCtx визначає екран контекстної довідки, що буде з‟являтися за натискання клавіші <F1>. Якщо така довідка не планується, слід задати значення 0.
Значення параметра Buttons |
Відповідне значення, яке повертається |
mbOK |
mrOk |
mbCancel |
mrCancel |
mbYes |
mrYes |
mbNo |
mrNo |
mbAbort |
mrAbort |
mbRetry |
mrRetry |
mbIgnore |
mrIgnore |
mbAll |
mrAll |
mbNoToAll |
mrNoToAll |
mbYesToAll |
mrYesToAll |
Діалогове повідомлення, створене у програмі командою
int btn = MessageDlg("Ви дійсно хочете вилучити всю інформацію з файла?", mtConfirmation, mbOKCancel, 0);
матиме вигляд:
