Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекція 9 (Файли).docx
Скачиваний:
29
Добавлен:
16.05.2015
Размер:
64.85 Кб
Скачать

Функції fprinf () і fscanf ()

Крім основних функцій введення/виведення, про які йшла мова, в системі введення/виведення мови С також є функції fprintf() і fscanf(). Ці дві функції, за винятком того, що призначені для роботи з файлами, ведуть себе точно так само, як і printf() і scanf(). Прототипи функцій fprintf() іfscanf () наступні:

int fprintf (FILE * pf, const char * управляющая_строка, ...); int fscanf (FILE * pf, const char * управляющая_строка, ...);

де pf – покажчик файлу, що повертається в результаті виклику fopen(). Операції введення/виведення fprintf() і fscanf() виконують з тим файлом, на який вказує pf.

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

int main (void) {   FILE * fp;   char s [80];   int t;   if ((fp = fopen ("test", "w")) == NULL) {     printf ("Помилка відкриття файлу. \ n");     exit (1);   }   printf ("Введіть рядок і число:");   fscanf (stdin, "% s% d", s, & t); / * читати з клавіатури * /   fprintf (fp, "% s% d", s, t); / * писати в файл * /   fclose (fp);   if ((fp = fopen ("test", "r")) == NULL) {     printf ("Помилка при відкритті файлу. \ n");     exit (1);   }   fscanf (fp, "% s% d", s, & t); / * читання з файлу * /   fprintf (stdout, "% s% d", s, t); / * виведення на екран * /   return 0; }

Зауваження. Хоча читати різносортні дані з файлів на дисках і писати їх у файли, розташовані також на дисках, часто найлегше саме з допомогою функцій fprintf() і fscanf(), але це не завжди найефективніший спосіб виконання операцій читання і запису. Оскільки дані в форматі ASCII записуються так, як вони повинні з'явитися на екрані (а не в двійковому вигляді), то кожен виклик цих функцій пов'язаний з певними накладними витратами. Тому, якщо треба дбати про розмір файлу або швидкість, то, швидше за все, доведеться використовувати fread() і fwrite().

Введення-виведення при прямому доступі: функція fseek ()

При прямому доступі можна виконувати операції введення/виведення, використовуючи систему введення/виведення мови С і функцію fseek(), яка встановлює покажчик поточної позиції у файлі. Ось прототип цієї функції:

Int fseek (file * pf, long int коліч_байт, int начало_отсчета);

Тут pf - це покажчик файлу, що повертається в результаті виклику функції fopen(), коліч_байт - кількість байтів, рахуючи від начало_отсчета, воно визначає нове значення покажчика поточної позиції, а початок відліку - це один з таких макросів:

Початок файлу - SEEK_SET Поточна позиція - SEEK_CUR Кінець файлу - SEEK_END

Тому, щоб отримати у файлі доступ на відстані коліч_байт байтів від початку файлу, начало_отсчета повинна дорівнювати SEEK_SET. Щоб при доступі відстань відраховується від поточної позиції, використовуйте макрос SEEK_CUR, а щоб при доступі відстань відраховується від кінця файлу, потрібно вказувати макрос SEEK_END. При успішному завершенні своєї роботи функція fseek () повертає нуль, а в разі помилки - ненульове значення.

У наступній програмі показано, як використовується fseek (). Тут в певному файлі відшукує деякий байт, а потім відображає його. У командному рядку потрібно вказати ім'я файлу, а потім потрібний байт, тобто відстань в байтах від початку файлу.

# include <stdio.h> # include <stdlib.h> int main (int argc, char * argv []) {  FILE * fp;

  if (argc! = 3) {     printf ("Синтаксис: SEEK <ім'я файлу> <байт> \ n");     exit (1);   }

  if ((fp = fopen (argv [1], "rb "))== NULL) {     printf ("Помилка при відкритті файлу. \ n");     exit (1);   }

  if (fseek (fp, atol (argv [2]), SEEK_SET)) {     printf ("Seek error. \ n");     exit (1);   }

  printf ("У% ld-м байті міститься% c. \ n", atol (argv [2]), getc (fp));   fclose (fp);

  return 0; }

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

fseek (fp, 9 * sizeof (struct addr), SEEK_SET);

Поточне значення індексу поточної позиції у файлі можна визначити за допомогою функції ftell (). Ось її прототип:

long int ftell (FILE * pf);

Функція повертає поточне значення покажчика поточної позиції у файлі, пов'язаному з покажчиком файлу pf. При невдалому результаті вона повертає -1. Зазвичай прямий доступ може знадобитися лише для двійкових файлів. Причина тут проста - тому що в текстових файлах можуть виконуватися перетворення символів, то може і не бути прямого відповідності між тим, що знаходиться у файлі і тим байтом, до якого потрібен доступ. Єдиний випадок, коли треба використовувати fseek() для текстового файлу - це доступ до тієї позиції, яка була вже знайдена за допомогою ftell(); такий доступ виконується за допомогою макросу SEEK_SET, використо­вуваного в якості початку відліку.

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