Запис інформації за кінцем файлу. Робота з текстовими файлами

Текстові файли

Розглянемо роботу з текстовим файлом Сі на прикладі. Створіть на диску текстовий файл з ім'ям TextFile.txt. Наберіть у цьому файлі такі рядки:

String_1 123 String_11, 456
String_2
String_3

Збережіть файл.

А це код програми на C, яка відкриває наш файл та зчитує з нього рядки:

/* *Author: @author Subbotin B.P..h> #include #define LEN 50 int main(void) ( puts("Text file operations"); char cArray; FILE *pTextFile = fopen("C:\\TextFile.txt", "r"); if(pTextFile == NULL) ( puts("Problems"); return EXIT_FAILURE; ) while(fgets(cArray, LEN, pTextFile) != NULL) ( printf("%s", cArray); ) fclose(pTextFile);

Щоб відкрити текстовий файл у C використовуємо функцію fopen:

FILE *pTextFile = fopen("C:\TextFile.txt", "r");

перший аргумент функції fopen вказує на файл, а другий каже, що файл відкритий для його читання.

Рядки зчитуємо за допомогою функції fgets:

fgets(cArray, LEN, pTextFile);

перший аргумент функції fgets вказує на масив символів, в якому будуть збережені отримані рядки, другий аргумент – це максимальна кількість символів для зчитування, третій – наш файл.

Після завершення роботи з файлом, його потрібно закрити:

fclose(pTextFile);

Отримуємо:

Російські літери у рядках теж проходять.

До речі, цю програму я зробив у Eclipse. Як працювати з C/C++ в Eclipse можна переглянути .

Отже, ми відкрили та рахували дані з текстового файлу.

Тепер навчимося програмно створювати текстовий файл та записувати в нього дані.

/* Author: @author Subbotin B.P..h> #include int main(void) ( FILE *pTextFile = fopen("C:\\TextFileW.txt", "w"); char *cString = "This is a string"; char cNewLine = "\n"; int nVal = 123 ; if(pTextFile == NULL) ( puts("Problems"); return EXIT_FAILURE; ) fprintf(pTextFile, "%s%c", cString, cNewLine); ;)

Створюємо текстовий файл для запису даних:

FILE *pTextFile = fopen("C:\TextFileW.txt", "w");

якщо файл вже є, то він буде відкритий, і всі дані будуть видалені.

C-рядок cString і число nVal записуються програмою в текстовий файл. cNewLine – це просто перехід на новий рядок.

Записуємо дані до текстового файлу за допомогою функції fprintf:

fprintf(pTextFile, "%s%c", cString, cNewLine);

перший аргумент тут – наш файл, другий – форматний рядок, третій і більше – необхідна для цього формату кількість аргументів.

У цьому розділі буде розглянуто два способи роботи з фійлами та стандартний клас MFC CFileDialog.


1. Робота з файлами в C (працює і в C ++).


    #include
    #include

Void main(void)
{
FILE *file;
char* file_name = "file.txt";
char load_string = "none";

File = fopen (file_name, "w");

Fputs("string", file);

File = fopen (file_name, "r");
if(file! = 0)
{
fgets(load_string, 50, file);
cout)
else
{
cout)
fclose(file);
) Опис функцій роботи з файлами знаходяться у бібліотеці stdio.h
Спочатку треба створити покажчик на змінну типу FILE ( FILE* file;).
Відкриття файлу здійснюється викликом функції fopen ( file = fopen (file_name, "w");)
Перший параметр цієї функції – ім'я файлу, другий – вказує в якому режимі має бути відкритий файл. "w"- Відкрити для запису, "r"- відкрити для читання, "a"- Доповнення файлу (це найбільш використовувані режими, хоча є й інші). Запис та зчитування даних із файлу здійснюється такими функціями: fputc, fputs, fgetc, fgets, fprintf, fscanf(опис цих функцій дивіться в stdio.h).
Закриття файлу здійснюється викликом функції fclose ( fclose(file);).

Робота з файлами за допомогою MFC (класи CFile, CStdioFile, ...) та стандартний клас MFC CFileDialog.


До бібліотеки MFC включено кілька класів для роботи з файлами. Розглянуті нижче класи успадковуються від базового класу

CFile.

Клас CF ile

CFileпризначений для забезпечення роботи із файлами. Він дозволяє спростити використання файлів, представляючи файл як об'єкт, який можна створити, читати, записувати тощо.

Щоб отримати доступ до файлу, спочатку необхідно створити об'єкт класу CFile. Конструктор класу дозволяє одразу після створення такого об'єкта відкрити файл. Але можна відкрити файл і пізніше, скориставшись методом

Open.

Відкриття та створення файлів

Після створення об'єкта класу CFileможна відкрити файл, викликавши методOpen. Методу треба вказати шлях до файлу, що відкривається, і режим його використання. Прототип методуOpenмає такий вигляд:

Virtual BOOL Open(LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError=NULL);

Як параметр lpszFileName треба вказати ім'я файлу, що відкривається. Можна вказати лише ім'я або повне ім'я файлу, що включає повний шлях до нього.

Другий параметр nOpenFlags визначає дію, що виконується методом Open із файлом, а також атрибути файлу. Нижче наведено деякі можливі значення параметра nOpenFlags:

  • CFile::modeCreate - Створюється новий файл. Якщо вказаний файл існує, його вміст стирається і довжина файлу встановлюється рівної нулю.
  • CFile::modeNoTruncate - Цей файл призначений для використання разом із файлом CFile::modeCreate. Якщо створюється вже існуючий файл, його вміст не буде видалено.

  • CFile::modeRea d - Файл відкривається лише для читання.
  • CFile::modeReadWrite - Файл відкривається для запису та читання.
  • CFile::modeWrite - Файл відкривається лише для запису.
  • CFile::typeText - Використовується класами, породженими від класу CFile, наприклад, CStdioFile, для роботи з файлами в текстовому режимі. Текстовий режим забезпечує перетворення комбінації символу повернення каретки та символу перекладу рядка.
  • CFile::Binary - Використовується класами, породженими від класу CFile, наприклад, CStdioFile, для роботи з файлами в двійковому режимі.
  • Необов'язковий параметр pError, який є вказівником на об'єкт класу CFileException, використовується лише у випадку, якщо виконання операції з файлом викликає помилку. При цьому об'єкт, що вказується pError, буде записана додаткова інформація.

    Метод Openповертає не нульове значення, якщо файл відкритий і нуль у разі помилки. Помилка при відкритті файлу може статися, наприклад, якщо методу Open вказаний для читання неіснуючий файл.

    Ідентифікатор відкритого файлу

    До складу класу CFile входить елемент даних m_hFile типу UINT. У ньому зберігається ідентифікатор відкритого файлу. Якщо об'єкт класу CFile вже створений, але файл ще не відкритий, то змінної m_hFile записана константа hFileNull.

    Звичайно, ідентифікатор відкритого файлу безпосередньо не використовується. Методи класу CFileдозволяють виконувати практично будь-які операції з файлами та не вимагають вказувати ідентифікатор файлу. Оскільки m_hFile є елементом класу, то реалізація його методів має вільний доступом до нього.

    Закриття файлів

    Після завершення роботи з файлом його треба закрити. Клас CFileмає при цьому спеціальний метод Close. Потрібно зауважити, що якщо був створений об'єкт класу CFile і відкритий файл, а потім об'єкт видаляється, то пов'язаний з ним файл автоматично закривається за допомогою деструктора.

    Читання та запис файлів

    Для доступу до файлів призначено кілька методів класу CFile: Read, ReadHuge, Write, WriteHuge, Flush. Методи Read та ReadHugeпризначені для читання даних із попередньо відкритого файлу. У 32-розрядних операційних системах обидва методи можуть одночасно рахувати з файлу більше 65535 байт. Специфікація ReadHuge вважається застарілою та залишена лише для сумісності з 16-розрядними операційними системами.

    Дані прочитані з файлу записуються в буфер lpBuf. Параметр nCount визначає кількість байт, яку треба рахувати з файлу. Фактично з файлу можна вважати менше байт, ніж запитано параметром nCount. Це відбувається, якщо під час читання досягнуто кінець файлу. Методи повертають кількість байт, прочитаних із файлу.

    Для запису файл призначені методи Write і WriteHuge. У 32-розрядних операційних системах обидва методи можуть одночасно записувати у файл більше 65 535 байт. Методи записує у відкритий файл nCount байт із буфера lpBuf. У разі помилки запису, наприклад переповнення диска, методи викликає обробку виключення.

    Метод Flush

    Коли використовується метод Write або WriteHuge для запису даних на диск, вони можуть бути певний час у тимчасовому буфері. Щоб переконатися, що необхідні зміни внесені у файл диску, потрібно скористатися методом Flush.

    Операції з файлами

    До складу класу входять методи, що дозволяють виконувати над файлами різні операції, наприклад, копіювання, перейменування, видалення, зміна атрибутів.

    Для зміни імені файлу клас CFile включає статичний метод Renameвиконує функції цієї команди. Метод не можна використовувати для перейменування каталогів. У разі помилки метод викликає виняток.

    Для видалення файлів у класі CFile включений статичний метод Remove, що дозволяє видалити вказаний файл. Цей метод не дозволяє видаляти каталоги. Якщо видалити файл неможливо, метод викликає виняток.

    Щоб визначити дату та час створення файлу, його довжину та атрибути, призначений статичний метод GetStatus. Існує два різновиди методу – перший визначений як віртуальний, а другий – як статичний метод.

    Віртуальна версія методу GetStatusвизначає стан відкритого файлу, пов'язаного з об'єктом класу CFile. Цей метод викликається лише тоді, коли об'єкт класу CFile створено та файл відкритий.

    Статична версія методу GetStatusдозволяє визначити параметри файлу, не пов'язаного з об'єктом класу CFile. Щоб скористатися цим методом, необов'язково попередньо відкривати файл.

    Блокування

    До складу класу включено методи LockRangeі UnlockRange, що дозволяє заблокувати один або кілька фрагментів даних файлу для доступу з інших процесів. Якщо програма намагається повторно блокувати дані, вже заблоковані раніше цією або іншою програмою, викликається виняток. Блокування є одним з механізмів, що дозволяють кільком додаткам або процесам одночасно працювати з одним файлом, не заважаючи один одному.

    Встановити блокування можна за допомогою методу LockRange. Щоб зняти встановлені блокування, треба скористатися методомUnlockRange. Якщо в одному файлі встановлено кілька блокувань, то кожне з них має зніматись окремим викликом методуUnlockRange.

    Позиціювання

    Щоб перемістити вказівник поточної позиції файлу в нове положення, можна скористатися одним із таких методів класу CFile - Seek, SeekToBegin, SeekToEnd.До складу класу CFileтакож входять методи, що дозволяють встановити та змінити довжину файлу, -GetLength, SetLength.

    При відкритті файлу покажчик поточної позиції файлу знаходиться на початку файлу. Коли порція даних прочитана або записана, то покажчик поточної позиції переміщається у бік кінця файлу і вказує на дані, які читатимуться або записуватимуться черговою операцією читання або запису у файл.

    Щоб перемістити вказівник поточної позиції файлу в будь-яке місце, можна скористатися універсальним методом

    Seek. Він дозволяє перемістити покажчик на кілька байт щодо початку, кінця чи поточної позиції покажчика.

    Щоб перемістити вказівник на початок або кінець файлу, найбільш зручно використовувати спеціальні методи. Метод

    SeekToBeginпереміщує покажчик на початок файлу, а методSeekToEnd- У його кінець.

    Але визначення довжини відкритого файлу зовсім необов'язково переміщати його покажчик. Можна скористатися методом

    GetLength. Цей метод також повертає довжину відкритого файлу в байтах. МетодSetLengthдозволяє змінити довжину відкритого файлу. Якщо за допомогою цього методу розмір файлу збільшується, значення останніх байт не визначено.

    Поточну позицію вказівника файлу можна визначити за допомогою методу

    GetPosition. Повертається методомGetPosition32-розрядне значення визначає зміщення покажчика з початку файла.

    Характеристики відкритого файлу

    Щоб визначити розташування відкритого файлу на диску, потрібно викликати метод GetFilePath. Цей метод повертає об'єкт класуCString, в якому міститься повний шлях файлу, включаючи ім'я диска, каталоги, ім'я файлу та його розширення.

    Якщо потрібно визначити лише ім'я та розширення відкритого файлу, можна скористатися методом GetFileName. Він повертає об'єкт класу CString, в якому міститься ім'я файлу. Якщо потрібно дізнатися тільки ім'я відкритого файлу без розширення, користуються методомGetFileTitle.

    Наступний метод класу CFile дозволяє встановити шлях файлу. Цей метод не створює, не копіює та не змінює імені файлу, він лише заповнює відповідний елемент даних в об'єкті класу CFile.

    Клас C

    MemFile

    До бібліотеки MFC входить клас

    CMemFile, успадкований від базового класуCFile. Клас CMemFileпредставляє файл, розміщений в оперативній пам'яті. З об'єктами класуCMemFileтак само, як і з об'єктами класуCFile. Відмінність полягає в тому, що файл, пов'язаний із об'єктомCMemFileрозташований не на диску, а в оперативній пам'яті комп'ютера. За рахунок цього операції з таким файлом відбуваються значно швидше, ніж із звичайними файлами.

    Працюючи з об'єктами класу

    CMemFile, можна використовувати практично всі методи класуCFile, що були описані вище. Можна записувати дані до такого файлу або зчитувати їх. Крім цих методів до складу класуCMemFileвключено додаткові методи.

    Для створення об'єктів класу CMemFile призначено два різні конструктори. Перший конструктор CMemFile має лише один необов'язковий параметр nGrowBytes:

    CMemFile(UINT nGrowBytes=1024);

    Цей конструктор створює в пам'яті порожній файл. Після створення файл автоматично відкривається (не потрібно викликати метод Ope

    n).

    Коли починається запис у такий файл, автоматично виділяється блок пам'яті. Для отримання пам'яті методи класу

    CMemFileвикликають стандартні функціїmalloc, reallocі free. Якщо виділеного блоку пам'яті недостатньо, його розмір збільшується. Збільшення блоку пам'яті файлу відбувається частинами nGrowBytes байт. Після видалення об'єкта класуCMemFileпам'ять, що використовується автоматично повертається системі.

    Другий конструктор класу CMemFile має складніший прототип. Це конструктор використовується у тих випадках, коли програміст сам виділяє пам'ять для файлу:

    CMemFile(BYTE* lpBuffer, UINT nBufferSize, UINT nGrowBytes=0);

    Параметр lpBuffer вказує на буфер, який використовуватиметься для файлу. Розмір буфера визначається параметром nBufferSize.

    Необов'язковий параметр nGrowBytes використовується комплексніше, ніж у першому конструкторі класу. Якщо nGrowBytes містить нуль, створений файл буде містити дані з буфера lpBuffer. Довжина такого файлу дорівнюватиме nBufferSize.

    Якщо nGrowBytes більше за нуль, то вміст буфера lpBuffer ігнорується. Крім того, якщо в такий файл записується більше даних, ніж міститься у відведеному буфері, його розмір автоматично збільшується. Збільшення блоку пам'яті файлу відбувається частинами nGrowBytes байт.

    CMemFileдозволяє отримати вказівник на область пам'яті, що використовується файлом. Через цей покажчик можна безпосередньо працювати із вмістом файлу, не обмежуючи себе методами класуCFile. Для отримання вказівника на буфер файлу можна скористатися методом Detach. Перед цим корисно визначити довжину файлу (і відповідно розмір буфера пам'яті), викликавши методGetLength. Detachзакриває даний файл і повертає покажчик на блок пам'яті, що використовується. Якщо знову потрібно відкрити файл і зв'язати з ним оперативний блок пам'яті, потрібно викликати методAttach.

    Слід зазначити, що з управління буфером файлу клас

    CMemFileвикликає стандартні функціїmalloc, reallocі free. Тому, щоб не порушувати механізм управління пам'яттю, буфер lpBuffer має бути створений функціямиmallocабо calloc.

    Клас CStdioFile

    Тим, хто звик користуватися функціями потокового введення/виводу зі стандартної бібліотеки C та C++, слід звернути увагу на клас

    CStdioFile, успадкований від базового класуCFile. Цей клас дозволяє виконувати буферизоване введення/виведення в текстовому та двійковому режимі. Для об'єктів класуCStdioFileможна викликати майже всі методи класу CFile.CStdioFileвходить елемент даних m_pStream, що містить покажчик на відкритий файл. Якщо об'єкт класуCStdioFileстворено, але файл ще відкритий, або закритий, то m_pStream містить константу NULL.CStdioFileмає три різні конструктори. Перший конструктор класу CStdioFile не має параметрів. Цей конструктор лише створює об'єкт класу, але не відкриває жодних файлів. Щоб відкрити файл, потрібно викликати методOpenбазового класуCFile.

    Другий конструктор класу

    CStdioFileможна викликати, якщо файл вже відкритий і потрібно створити новий об'єкт класу CStdioFile та зв'язати з ним відкритий файл. Цей конструктор можна використовувати, якщо файл був відкритий стандартною функцієюfopen. Параметр методу повинен містити вказівник на файл, отриманий викликом стандартної функціїfopen.

    Третій конструктор можна використати, якщо треба створити об'єкт класу

    CStdioFileвідкрити новий файл і зв'язати його з щойно створеним об'єктом.

    Для читання та запису в текстовий файл клас CStdioFile включає два нові методи:

    ReadStringі WriteString. Перший метод дозволяє прочитати з файлу рядок символів, а другий метод – записати.

    Приклади запису та читання з файлу

    Наведемо фрагменти коду, в яких демонструється використання стандартних діалогових панелей вибору файлу та процедури читання та запису у файл.

    Відкриття файлу та читання з нього

    CString m_Text; ……// Створення стандартної панелі вибору файлу Open CFileDialog DlgOpen(TRUE,(LPCSTR)"txt",NULL, OFN_HIDEREADONLY,(LPCSTR)" Text Files (*.txt) |*.txt||");// Відображення стандартної панелі вибору файлу Open if(DlgOpen.DoModal()==IDOK) (// створення об'єкта та відкриття файлу для читання CStdioFile File(DlgOpen.GetPathName(),CFile::modeRead|CFile::typeBinary);// Читання з файлу рядка CString& ref=m_Text; File.ReadString(ref

    ); // Передається посилання на рядок

    CString m_Text; m_Text)Відкриття файлу та запис із нього // Створення стандартної панелі вибору файлу SaveAs CFileDialog DlgSaveAs(FALSE,(LPCSTR)"txt",NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, (LPCSTR)" Text Files (*.txt) |*.txt||"); // Відображення стандартної панелі вибору файлу SaveAs if(DlgSaveAs.DoModal()==IDOK) ( // створення об'єкта та відкриття файлу для запису CStdioFile File(DlgSaveAs.GetPathName(), CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);
      // запис у файл рядка

      File.WriteString((LPCTSTR)m_Text);

    )

    знаходиться робочий код програми, виконаної для простоти у вигляді консольної програми під MFC. Щоб програма працювала не забудьте зробити таке:
    Запустіть програму - Build / Rebuild all (будуть помилки), виберіть Build / Set active configuration - Win 32 Realise, виберіть пункт меню "Project", далі "Settings...", закладку "C/C++", Category - Code Generation та у пункті "Use run-time library" виберіть "Multithreaded". Після цього зробіть знову Build/Rebuild all і програма працюватиме.

    До цього під час введення-виведення даних ми працювали зі стандартними потоками - клавіатурою та монітором. Тепер розглянемо, як у мові C реалізовано отримання даних із файлів та запис їх туди. Перед тим, як виконувати ці операції, потрібно відкрити файл та отримати доступ до нього.
    У мові програмування C покажчик файл має тип FILE і його оголошення виглядає так:

    FILE * myfile;

    Якщо через ті чи інші причини (немає файлу за вказаною адресою, заборонено доступ до нього) функція fopen() не може відкрити файл, то вона повертає NULL. У реальних програмах майже завжди обробляють помилку відкриття файлу у гілці if, ми ж далі опустимо це.

    Оголошення функції fopen() міститься в заголовку stdio.h, тому потрібне його підключення. Також у stdio.h оголошено тип-структуру FILE.

    Після того, як робота з файлом закінчена, прийнято його закривати, щоб звільнити буфер від даних та з інших причин. Це особливо важливо, якщо після роботи з файлом програма продовжує виконуватись. Розрив зв'язку між зовнішнім файлом та вказівником на нього із програми виконується за допомогою функції fclose() . Як параметр їй передається покажчик на файл:
    fclose(myfile);

    У програмі можна відкрити не один файл. У такому разі кожен файл повинен бути пов'язаний зі своїм файловим покажчиком. Однак, якщо програма спочатку працює з одним файлом, потім закриває його, то вказівник можна використовувати для відкриття другого файлу.

    Читання з текстового файлу та запис до нього

    fscanf()

    Функція fscanf() аналогічна за змістом функції scanf() , але на відміну від неї здійснює форматоване введення файлу, а не стандартного потоку введення. Функція fscanf() приймає параметри: файловий покажчик, рядок формату, адреси областей пам'яті для запису даних:
    fscanf (myfile, "%s%d", str, &a);

    Повертає кількість вдало лічених даних чи EOF. Пробіли, символи переходу до нового рядка враховуються як роздільники даних.

    Припустимо, у нас є файл, який містить такий опис об'єктів:

    Apples 10 23.4 bananas 5 25.0 bread 1 10.3

    #include main () (FILE * file; struct food (char name [20]; unsigned qty; float price;); struct food shop [10]; char i = 0; file = fopen ("fscanf.txt", "r" ) ; while (fscanf (file, "%s%u%f" , shop[ i] .name , & (shop[ i] .qty ) , & (shop[ i] .price ) ) != EOF) ( printf ("%s%u%.2f \n ", shop[i].name, shop[i].qty, shop[i].price);

    i++;

    )

    Функція fgets() аналогічна функції gets() і здійснює рядкове введення з файлу. Один виклик fgets() дозволить прочитати один рядок. При цьому можна прочитати не весь рядок, а лише її частину від початку. Параметри fgets() виглядають таким чином:
    fgets (масив_символів, кількість_зчитуваних_символів, покажчик_на_файл)

    Наприклад:
    fgets (str, 50, myfile)

    Такий виклик функції прочитає з файлу, пов'язаного з покажчиком myfile, один рядок тексту повністю, якщо його довжина менше 50 символів з урахуванням символу \n, який функція також збереже в масиві. Останнім (50) елементом масиву str буде символ "\0", доданий fgets() . Якщо рядок виявиться довшим, функція прочитає 49 символів і в кінці запише "\0". У такому разі "\n" у ліченому рядку не утримуватиметься.

    #include #define N 80 main () ( FILE * file; char arr [ N] ; file = fopen ("fscanf.txt" , "r") ; while (fgets (arr, N, file) != NULL) printf (" %s" , arr) ; printf (" \n ");

    fclose (file);

    )

    У цій програмі на відміну від попередньої дані зчитуються рядок за рядком масив arr. Коли зчитується наступний рядок, попередній втрачається. Функція fgets() повертає NULL, якщо не може прочитати наступний рядок.

    getc() або fgetc() \n "Функція getc() або fgetc() (працює і те, й інше) дозволяє отримати з файлу черговий один символ. \0 " while ((arr[ i] = fgetc (file) ) != EOF) ( if (arr [ i] == " \n ") ( arr [ i] = " \0 " while ((arr[ i] = fgetc (file) ) != EOF) ( if (arr [ i] == " \n ";

    printf ("%s

    , arr);

    i = 0;

    • ) else i++;
    • ) arr [i] = "
    • , arr);

    Наведений як приклад код виводить дані із файлу на екран.

    Запис до текстового файлу

    Також як і введення, виведення файл може бути різним. \n "Форматований висновок. Функція fprintf (файловий_покажчик, рядок_формату, змінні) .

    Посточный висновок. Функція fputs (рядок, файловий_покажчик) .

    Символьний висновок. Функція fputc() або putc(символ, файловий_покажчик) . \n "Нижче наводяться приклади коду, в яких використовуються три способи виведення даних у файл.

    Запис у кожний рядок файлу полів однієї структури:

    while ((i = getchar ())! = EOF) putc (i, file);

    Читання з двійкового файлу та запис до нього

    З файлом можна працювати як з послідовністю символів, бо як із послідовністю байтів. В принципі, з нетекстовими файлами працювати по-іншому неможливо. Однак так можна читати і писати і текстові файли. Перевага такого способу доступу до файлу полягає у швидкості читання-запису: за одне звернення можна рахувати/записати суттєвий блок інформації.

    При відкритті файлу для двійкового доступу другим параметром функції fopen() є рядок "rb" або "wb".

    Тема роботи з двійковими файлами досить складна, її вивчення потрібен окремий урок. Тут будуть відзначені лише особливості функцій читання-запису до файлу, який сприймається як потік байтів.

    Функції fread() і fwrite() приймають як параметри:

    1. адресу області пам'яті, куди дані записуються або звідки зчитуються,
    2. розмір одного даного будь-якого типу,
    3. кількість даних, що зчитуються зазначеного розміру,
    4. файловий покажчик.

    Ці функції повертають кількість успішно прочитаних чи записаних даних. Тобто. можна замовити зчитування 50 елементів даних, а отримати тільки 10. Помилки при цьому не виникне.

    Приклад використання функцій fread() та fwrite() :

    #include #include main () (FILE * file; char shelf1 [50], shelf2 [100]; int n, m; file = fopen ("shelf1.txt", "rb"); n = fread (shelf1, sizeof (char) 50 , файл) ; fclose (file ) ; = " \0 " ; \n " shelf2 [m] = " \0 " ;

    shelf2 [m + 1] = "

    ;

    1. file = fopen ("shop.txt", "wb");
    2. fwrite (strcat (shelf2, shelf1), sizeof (char), n + m, file);

    Записувати інформацію до текстового файлу ми вже навчилися. – Якщо не навчилися, дивіться минулу статтю. Там розповідається та докладно описано

    Але якщо файл вже існує і нам потрібно рахувати з нього інформацію для обробки? На щастя, це теж досить просто. Нагадую, що варіантів для реалізації цього завдання існує кілька, мною описаний лише один. Описаний той, який особисто мені чомусь здається найпростішим для сприйняття.

    #include

    int main()
    {
    char s1 //Змінна зчитуватиме рядок
    ifstream in (“C:\FromC\myfile.txt”); //Відкриваємо файл для зчитування інформації
    in >> s1; //зчитуємо рядок
    in .close () //Закриваємо файл

    cout<Виводимо значення s1на екран
    return 0;
    }

    Ось найпростіша програма для зчитування першого рядка з текстового файлу, який знаходиться на шляху
    C:\FromC\myfile.txt –
    Так як це продовження минулої статті, то я вирішив використовувати файл, який ми там створювали. Проблем з цим, напевно, виникнути не повинно.
    Але повернемось до коду. Спочатку ми відкриваємо файл для зчитування інформації, для цього використовуємо команду ifstream ,у дужках вказуємо або назву файлу, або шлях до файлу, як зроблено в мене. (“C:\FromC\myfile.txt”);
    Коли ми відкрили файл, щоб рахувати щось із нього, ми оголосили одну змінну типу char –
    char s1
    Тепер нам залишилося лише присвоїти змінної значення рядка з файлу. Це ми робимо командою in
    Звертаємо увагу на кутові дужки in >>
    Власне, як має бути видно з коментарів до коду програми, то щоб змінна надала зчитуване значення, ми повинні написати її після in >>
    in >> s1;

    Ніяким особливо складним завданням це не представляється, особливо якщо ви вже чудово освоїли та навчилися використовувати матеріал минулої статті – все абсолютно аналогічно, тільки 2 команди інші

    Створення файлу та запис у нього інформації С++

    ofstream out (ім'я файлу );
    out<< (Записуваний рядок);
    out. close ();
    =============================

    Читання тексту з файлу та виведення тексту на екран C++

    ifstream in (Ім'я файлу );
    in>> (Зчитуємо рядок);
    in. close ();(Закриваємо файл)
    ============================
    Напишемо просту програму, яка зчитуватиме введення з клавіатури тексту та записуватиме його у файл:

    #include
    #include

    int main()
    {
    \\ 3 майбутні рядки
    clrscsr(); //Очищаємо екран

    cout<<“Wwedi pervuu stroku” ; cin >>a; endl;
    cout<<“Wwedi wtoruu stroku” ; cin >> b; endl;
    cout<<“Wwedi tretuu stroku” ; cin >>c; endl;
    clrscr(); //

    /*Починаємо роботу з файлом*/
    ofstream out (“C:\FromC\myfile.txt”); //Відкриваємо файл для запису
    out<Записуємо перший рядок
    out<Записуємо другий рядок
    out<Записуємо третій рядок
    out .close(); //Закриваємо файл

    //Обнуляємо змінні

    for (int i = 0; i<=255 ;i ++)
    (a =*“” ; b =*“” ; c =*“” ;)


    ifstream in ("C:\FromC\myfile.txt");
    in >>a >>b >>c; //Зчитуємо кожну нову сходинку в нову змінну
    in .close (); //Закриваємо файл

    /* */

    for (i = 0 ;a !=*“” ;i ++)
    {
    if (i >sizeof(a )) break;
    cout<

    }
    cout<<“\n” ; \\

    /* */


    {
    if (i > sizeof(b )) break;
    cout<
    }
    cout<<“\n” ; \\ Перевели курсор на новий рядок

    /* */

    for (i = 0 ;с !=*“” ;i ++)
    {
    if (i > sizeof(c )) break;
    cout<<с ;
    }

    return 0;
    }
    ===================

    У наведених вище прикладах є один такий ВЕЛИЧЕЗНИЙ нестача. Якщо ми намагатимемося ввести рядок, що містить прогалини, то програма спрацьовуватиме не так, як нам потрібно. Напевно, на цю помилку натрапив не лише я, а й багато інших людей. Тому я залишаю невірно наведений код, щоб було видно, з чим можна зіткнутися.

    Оскільки книжок удома немає, я знову почав нишпорити в інтернеті і знайшов багато всякої складної нісенітниці. Але таки якось підібрав вирішення своєї проблеми.
    Допомогло те, що читав про те, що coutпідтримує свої способи. І в інтернеті всі поради йдуть на використання функції getlineНа моє щастя, як використовувати цю функцію я знайшов дуже швидко і потім використовував її в коді.
    Взагалі варто згадати і описати цю функцію, але поки що я не особливо її розумію, просто розумію, що її потрібно використовувати і розумію як, тому наводжу правильніший приклад нашої програми, що розробляється:

    #include
    #include

    int main()
    {
    char a, b, c; \\ 3 майбутні рядки
    clrscsr(); //Очищаємо екран

    /* Вводимо значення для змінних*/

    cout<<“Wwedi pervuu stroku” ; cin.getline(a,sizeof(a)); endl;
    cout<<“Wwedi wtoruu stroku” ; cin.getline(a,sizeof(b)); endl;
    cout<<“Wwedi tretuu stroku” ; cin.getline(a,sizeof(c)); endl;
    clrscr(); //Після введення значень очистили екран

    /*Починаємо роботу з файлом*/
    ofstream out (“C:\FromC\myfile.txt”); //Відкриваємо файл для запису
    out<
    Записуємо перший рядок
    out<Записуємо другий рядок
    out<Записуємо третій рядок
    out .close(); //Закриваємо файл

    //Обнуляємо змінні

    for (int i = 0; i<=255 ;i ++)
    (a =*“” ; b =*“” ; c=*“” ;)

    /*Продовжуємо роботу з файлом*/

    if stream in ("C:\FromC\myfile.txt");
    in.getline(a,sizeof(a));// а
    in.getline(b,sizeof(b));// Зчитуємо рядок у змінну b
    in.getline(c,sizeof(c)); // Зчитуємо рядок у змінну c
    in .close (); //Закриваємо файл

    /* Зчитуємо посимвольно перший рядок та виводимо його на екран */

    for (i =0 ;a !=*“” ;i++)
    {
    if (i >sizeof(a )) break;
    cout<

    }
    cout<<“\n” ; \\ Перевели курсор на новий рядок

    /* Зчитуємо посимвольно другий рядок та виводимо його на екран */

    for (i =0 ;b !=*“” ;i ++)
    {
    if (i > sizeof(b )) break;
    cout<
    }
    cout<<“\n” ; \\ Перевели курсор на новий рядок

    /* Зчитуємо посимвольно третій рядок та виводимо його на екран */

    for (i =0 ;с !=*“” ;i++)
    {
    if (i>sizeof (c)) break;
    cout<<с[i];
    }

    getch(); \\Очікуємо натискання клавіші Enter
    return 0;
    }
    ===================

    У цьому матеріалі розібрано приклад посимвольного читання інформації. Так як я не описував роботу зі змінними типу char, то у початківців можуть виникнути деякі незручності сприйняття коду. Просто я не знав, що тип charмає якісь особливості та думав все простіше. Тому деякі незрозумілі моменти наведеної програми можна прочитати у наступній статті робота з charв C++ для початківців

    В іншому, наведений приклад, як у C++ рахувати рядки з текстового файлу має бути доступним і цілком зрозумілим. Це зараз не оптимальний варіант реалізації, і я упустив деякі важливі моменти, але так як у нас початок вивчення мови C++, то цього поки що цілком достатньо. Пізніше я, напевно, дійду до втраченого, а зараз треба сприймати тільки найнеобхідніше.

    Якщо ми разом з вами зрозуміли цей матеріал, значить просунулися на маленький крок до свого професіоналізму.

    Примітка:
    break;– Це команда, яка виконує вихід із циклу. У нас якщо лічильник циклу forстає більше ніж оголошений розмір змінної char,то ми примусово виходимо із циклу
    != – це поставлена ​​нами умова. Позначає таку умову нерівність
    if(a !=b )- Читається як якщо aне дорівнює b

    endl; -Це переведення курсору на новий рядок усередині консолі (наскільки я зрозумів)
    Ця команда схожа на "\n"

    Робота з текстовими файлами C++.

    Існують два основні типи файлів: текстові та двійкові. Файли дозволяють користувачеві зчитувати великі обсяги даних безпосередньо з диска, не вводячи їх із клавіатури.

      Текстовиминазиваються файли, які з будь-яких символів. Вони організуються по рядках, кожен із яких закінчується символом «кінець рядка». Кінець файлу позначається символом «кінець файлу». При записі інформації в текстовий файл, який можна переглянути за допомогою будь-якого текстового редактора, всі дані перетворюються до символьного типу і зберігаються в символьному вигляді.

      У двійковихВ файлах інформація зчитується і записується у вигляді блоків певного розміру, в яких можуть зберігатися дані будь-якого виду та структури.

    Для роботи з файлами використовуються спеціальні типи даних, звані потоками. Потік ifstreamслужить до роботи з файлами як читання, а ofstreamв режимі зйомки. Для роботи з файлами як записи, так і читання служить потік fstream.

    У програмах на C++ під час роботи з текстовими файлами необхідно підключати бібліотеки iostream і fstream.

    Для того щоб записуватидані в текстовий файл, необхідно:

      описати змінну типу ofstream.

      вивести інформацію у файл.

      обов'язково закрити файл.

    Для зчитуванняданих із текстового файлу, необхідно:

      описати змінну типу ifstream.

      відкрити файл за допомогою функції Open.

      закрити файл.

    Записінформації в текстовий файл

      Як було сказано раніше, щоб почати працювати з текстовим файлом, необхідно описати змінну типу ofstream. Наприклад, так:

      Буде створено змінну F для запису інформації у файл.

      На наступному етапі файлу необхідно відкрити для запису. У загальному випадку оператор відкриття потоку матиме вигляд:

    F.open("file", mode);

    Тут F - змінна, описана як ofstream,

    file - повне ім'я файлу на диску,

    mode - режим роботи з файлом, що відкривається.

    Зверніть увагу, що при вказівці повного імені файлу потрібно ставити подвійний слєш. Наприклад, повне ім'я файлу noobs.txt, що знаходиться в папці game на диску D:, потрібно буде записати так:

    D:\\game\\noobs.txt.

    Файл може бути відкритий в одному з таких режимів:

    ios::in - відкрити файл у режимі читання даних, цей режим є стандартним режимом для потоків ifstream;

    ios::out - відкрити файл в режимі запису даних (при цьому інформація про існуючий файл знищується), цей режим є стандартним режимом для потоків ofstream;

    ios::app - відкрити файл у режимі запису даних на кінець файлу;

    ios::ate - пересунутись на кінець вже відкритого файлу;

    ios::trunc - очистити файл, це відбувається в режимі ios::out;

    ios::nocreate - не виконувати операцію відкриття файлу, якщо він не існує;

    ios::noreplace - не відкривати існуючий файл.

    Параметр mode може бути відсутнім, у цьому випадку файл відкривається в режимі за промовчанням для цього потоку.

    Після вдалого відкриття файлу (у будь-якому режимі) у змінній F зберігатиметься true, інакше false. Це дозволить перевірити коректність операції відкриття файлу.

    Відкрити файл (як приклад візьмемо файл D:\game\\noobs.txt) в режимі запису можна одним з наступних способів:

    // перший спосіб

    ofstream F;

    F.open("D:\game\noobs.txt", ios::out);

    //другий спосіб, режим ios::out є стандартним режимом

    // для потокуofstream

    ofstream F;

    //третій спосіб поєднує опис змінної та типу потік

    //і відкриття файлу в одному операторі

    ofstream F ("D:\game\noobs.txt", ios::out);

    Після відкриття файлу в режимі запису буде створено порожній файл, який можна буде записувати інформацію.

    Якщо ви хочете відкрити існуючий файл у режимі до запису, то як режим слід використовувати значення ios::app.

    Після відкриття файлу в режимі запису, в нього можна писати так само, як і на екран, тільки замість стандартного пристрою виводуcoutпотрібно вказати ім'я відкритого файлу.

    Наприклад, для запису в потік F змінної a оператор виведення буде мати вигляд:

    Для послідовного виведення потік G змінних b, c, d оператор виведення стане таким:

    G<

    Закриття потоку здійснюється за допомогою оператора:

    ПРИКЛАД:

    Створити текстовий файл D:\game\noobs.txt і записати в нього n дійсних чисел.

    #include "stdafx.h"

    #include

    #include

    #include

    using namespace std;

    int main()

    setlocale (LC_ALL, "RUS");

    int i, n;

    double a;

    //описує потік для запису даних у файл

    ofstream f;

    //відкриваємо файл у режимі запису,

    //режимios:: outвстановлюється за умовчанням

    f.open("D:\game\noobs.txt", ios::out);

    //вводимо кількість дійсних чисел

    cout<<" n="; cin>> n;

    //цикл для введення дійсних чисел

    //і записи їх у файл

    for (i=0; i

    cout<<"a=";

    //введення числа

    cin>>a;

    f<

    //закриття потоку

    f.close();

    system("pause");

    return 0;

    _______________________________________________________________

    Для того, щоб прочитати інформацію з текстового файлу, необхідно описати змінну типу ifstream. Після цього потрібно відкрити файл для читання оператором open. Якщо змінну назвати F, то перші два оператори будуть такими:

    F.open("D:\game\noobs.txt", ios::in);

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

    Наприклад, для читання з потоку F в змінну a, оператор введення виглядатиме так:

    Два числа в текстовому редакторі вважаються розділеними, якщо між ними є хоча б один із символів: пробіл, табуляція, символ кінця рядка. Добре, якщо програмісту заздалегідь відомо, скільки та яких значень зберігатиметься у текстовому файлі. Однак часто просто відомий тип значень, що зберігаються у файлі, при цьому їх кількість може бути різною. При вирішенні подібної проблеми необхідно зчитувати значення з файлу по одному, а перед кожним зчитуванням перевіряти, чи кінець файлу досягнуто. Для цього існує функція F. eof().

    Тут F - ім'я потоку функція повертає логічне значення: true чи false, залежно від цього досягнуто кінець файла. Отже, цикл для читання вмісту всього файлу можна записати так:

    //організуємо для читання значень із файлу, виконання

    //цикла перерветься, коли досягнемо кінець файлу,

    //у цьому випадку F.eof() поверне істину

    while (!F.eof())

    ПРИКЛАД:

    У текстовому файлі D:\game\noobs.txt зберігаються речові числа, вивести їх на екран і обчислити їх кількість.

    #include "stdafx.h"

    #include

    #include

    #include

    #include

    using namespace std;

    int main()

    setlocale (LC_ALL, "RUS");

    int n=0;

    float a;

    fstream F;

    //відкриваємо файл у режимі читання

    F.open("D:\game\noobs.txt");

    //якщо відкриття файлу пройшло коректно, то

    //цикл для читання значень із файлу; виконання циклу перерветься,

    //Коли досягнемо кінця файлу, у разі F.eof() поверне істину.

    while (!F.eof())

    //читання чергового значення з потоку F змінну a

    F>>a;

    //Виведення значення змінної a на екран

    cout<

    //збільшення кількості лічених чисел

    //закриття потоку

    F.close();

    //Вовод на екран кількості лічених чисел

    cout<<"n="<

    //якщо відкриття файлу пройшло некоректно, висновок

    //повідомлення про відсутність такого файлу

    else cout<<" Файл не существует"<

    system("pause");

    return 0;

    C++. Обробка двійкових файлів

    При записі інформації у двійковий файл символи та числа записуються у вигляді послідовності байт.

    Для того щоб записатидані в двійковий файл, необхідно:

      описати файлову змінну типу FAIL* за допомогою оператора FILE *filename; Тут filename - ім'я змінної, де зберігатиметься покажчик на файл.

      записати інформацію у файл за допомогою функції fwrite

    Для того щоб рахуютьь дані з двійкового файлу, необхідно:

      описати змінну типу FILE *

      відкрити файл за допомогою функції fopen

      закрити файл за допомогою функції fclose

    Основні функції, необхідних роботи з двійковими файлами.

    Для відкриттяфайлу призначено функцію fopen.

    FILE *fopen(const *filename, const char *mode)

    Тут filename - рядок, в якому зберігається повне ім'я файлу, що відкривається, mode - рядок, що визначає режим роботи з файлом; можливі такі значення:

    "rb" - відкриваємо двійковий файл у режимі читання;

    "wb" - створюємо двійковий файл для запису; якщо він існує, його вміст очищається;

    "ab" - створюємо або відкриваємо двійковий файл для дозапису в кінець файлу;

    "rb+" - відкриваємо існуючий двійковий файл у режимі читання та запису;

    "wb+" - відкриваємо двійковий файл у режимі читання та запису, існуючий файл очищається;

    "ab+" - двійковий файл відкривається або створюється для виправлення існуючої інформації та додавання нової до кінця файлу.

    Функція повертає у файловій змінній f значення NULL у разі невдалого відкриття файлу. Після відкриття файлу доступний 0-й байт, покажчик файлу дорівнює 0, значення якого в міру читання або запису зміщується на лічену (записану) кількість байт. Поточне значення покажчика файлу - номер байта, з якого буде відбуватися операція читання чи записи.

    Для закриттяфайлу призначена функція fclose

    int fclose(FILE *filename);

    Повертає 0 при успішному закриття файлу та NULL в іншому випадку.

    Функція remove призначена для видаленняфайлів.

    int remove(const char *filename);

    Ця функція видаляє з диска файл з ім'ям файланема. Файл, що видаляється, повинен бути закритий. Функція повертає ненульове значення, якщо не вдалося видалити файл.

    Для перейменуванняфайлів призначена функція rename:

    int rename(const char *oldfilename, const char *newfilename);

    Перший параметр – старе ім'я файлу, другий – нове. Повертає 0 при успішному завершенні програми.

    Читанняіз двійкового файлу здійснюється за допомогою функції fread:

    fread(void *ptr, size, n, FILE *filename);

    Функція fread зчитує з файлу filename масив ptr n елементів розміру size. Функція повертає кількість лічених елементів. Після прочитання з файлу його покажчик зміщується на n*size байт.

    Запису двійковий файл здійснюється за допомогою функції fwrite:

    fwrite(const void *ptr, size, n, FILE *filename);

    Функція fwrite записує файл filename з масиву ptr n елементів розміру size. Функція повертає кількість записаних елементів. Після запису інформації у файл покажчик зміщується на n*size байт.

    Для контролю досягнення кінця файлує функція feof:

    int feof(FILE *filename);

    Вона повертає ненульове значення, якщо досягнуто кінець файлу.

    ПРИКЛАД:

    Створити двійковий файл D:\game\noobs.dat і записати в нього ціле число n і n дійсних чисел.

    #include "stdafx.h"

    #include

    using namespace std;

    int main()

    setlocale (LC_ALL, "RUS");

    int n, i;

    double a;

    //Створюємо двійковий файл у режимі запису

    f=fopen("D:\game\noobs.dat", "wb");

    // введення числаn

    cout<<"n="; cin>>n;

    fwrite(&n, sizeof(int), 1, f);

    //цикл для введення n дійсних чисел

    for (i=0; i

    //введення чергового речового числа

    cout<<"a=";

    cin>>a;

    //запис вешаного числа в двійковий файл

    fwrite(&a, sizeof(double), 1, f);

    // закриваємо файл

    fclose(f);

    system("pause");

    return 0;

    ПРИКЛАД:

    Вивести на екран вмісту створеного в минулому задачі двійкового файлу D:\game\noobs.dat

    #include "stdafx.h"

    #include

    using namespace std;

    int main()

    setlocale (LC_ALL, "RUS");

    int n, i;

    double *a;

    FILE *f; //описуємо файлову змінну

    //відкриваємо існуючий двійковий файл у режимі читання

    //зчитуємо з файлу одне ціле число змінну n

    //Виведення n на екран

    cout<<"n="<

    //Виділення пам'яті для масиву з n чисел

    a=new double[n];

    //Читання n дійсних чисел з файлу в масив a

    //Виведення масиву на екран

    for (i=0; i

    cout<

    cout<

    // закриваємо файл

    fclose(f);

    system("pause");

    return 0;

    Двійковий файл- Послідовна структура даних, після відкриття файлу доступний перший байт, що зберігається в ньому. Можна послідовно записувати чи зчитувати дані з файлу. Допустимо, необхідно вважати п'ятнадцяте число, а потім перше. За допомогою послідовного доступу це можна зробити у такий спосіб:

    int n, i;

    double a;

    FILE *f;

    f=fopen("D:\game\noobs.dat", "rb");

    for (i=0; i<15; i++)

    fclose(f);

    f=fopen("D:\game\noobs.dat", "rb");

    fread(&a, sizeof(double), 1, f);

    fclose(f);

    Як видно, таке читання чисел із файлу, а потім повторне відкриття файлу – не найзручніший спосіб. Набагато зручніше буде використовувати функцію fseek для переміщення покажчика файлу до заданого байта.

    int fseek(FILE *filename, long int offset, int origin);

    Функція встановлює покажчик поточної позиції файлу F відповідно до значення початку відліку origin і зміщення offset. Параметр offset дорівнює кількості байтів, на які буде зміщено покажчик файлу щодо початку відліку, заданого параметром origin. Як значення для параметра origin має бути взято одне з наступних значень відліку зсуву offset, визначених у заголовку stdio.h:

    SEEK_SET – з початку файлу;

    SEEK_CUR – з поточної позиції;

    SEEK_END – з кінця файлу.

    Функція повертає нульове значення при успішному виконанні операції, ненульове - при виникненні збою при виконанні зміщення

    Функція fseek фактично реалізує прямий доступ до будь-якого значення файлу. Необхідно тільки знати розташування (номер байта) значення у файлі. Розглянемо використання прямого доступу в двійкових файлах з прикладу вирішення наступного завдання.

    ПРИКЛАД

    У створеному раннє двійковому файлі D:\game\noobs.dat, поміняти місцями найбільше і найменше з дійсних чисел.

    Алгоритм розв'язання задачі складається з наступних етапів:

      читання речових із файлу в масив a.

      пошук у масиві а максимального (max) та мінімального (min) значення та їх номерів (imax, imin).

      переміщення покажчика файлу до максимального значення та запис min.

      переміщення покажчика файлу до мінімального значення та запис max.

    Нижче наведено текст програми вирішення завдання з коментарями.

    #include "stdafx.h"

    #include

    using namespace std;

    int main()

    setlocale (LC_ALL, "RUS");

    int n, i, imax, imin;

    double *a, max, min;

    FILE *f;

    //відкриття файлу в режимі читання та запису

    f=fopen("D:\game\noobs.dat", "rb+");

    //зчитуємо з файлу змінну n кількість

    //речевих чисел у файлі

    fread(&n, sizeof(int), 1, f);

    cout<<"n="<

    //виділяємо пам'ять для зберігання дійсних чисел,

    //які зберігатимуться в масиві a

    a=new double[n];

    //зчитуємо з файлу в масив а речові числа

    fread(a, sizeof(double), n, f);

    //Пошук максимального та мінімального елементів

    //В масиві а та їх індексів

    for (imax=imin=0, max=min=a, i=1; i

    if (a[i]>max)

    max = a [i];

    if (a[i]

    min = a [i];

    // переміщення покажчика до максимальному елементу

    fseek(f, sizeof(int)+imax*sizeof(double), SEEK_SET);

    //запис min замість максимального елемента файлу

    fwrite(&min, sizeof(double), 1, f);

    // переміщення покажчика до мінімальному елементу

    fseek(f, sizeof(int)+imin*sizeof(double), SEEK_SET);

    //запис max замість мінімального елемента файлу

    fwrite(&max, sizeof(double), 1, f);

    //закриття файлу

    fclose(f);

    //звільнення пам'яті

    delete [ ]a;

    system("pause");