Функції верхнього рівня характеризуються буферизацією операцій зчитування та запису. Якщо проводиться операція запису у файл, то інформація з буферу записується у файл при заповненні буфера, закритті файла та за деяких інших умов. Інформація зчитується з буфера, до якого потрапляє нова порція інформації. Буферизація здійснюється автоматично. Вона дозволяє пришвидшити виконання програми за рахунок зменшення кількості звертань до зовнішніх пристроїв, що працюють відносно повільно. До функцій верхнього рівня належать:
a clearerr() – скидання прапорців помилок;
a fclose() – закриття потоку;
a fcloseall() – закриття всіх відкритих файлів;
a fdopen() – створення потоку для файла, відкритого раніше на нижньому рівні з використанням дескриптора;
a feof() – перевірка на кінець потоку;
a ferror() – перевірка прапорців помилок;
a flush() – скидання буфера потоку;
a fgetc() – читання символу з потоку;
a fileno() – отримання дескриптора файла, пов'язаного з потоком;
a fgetchar() – макрос читання зі stdin (аналог fgetc(stdin));
|
|
a fgets() – читання рядка з потоку;
a flushall() – скидання всіх буферів;
a fopen() – відкривання файла;
a fprintf() – форматоване виведення в потік;
a fputc() – запис символу в потік;
a fputchar() – макрос запису символу у stdout;
a fputs() – запис рядка в потік; символ нового рядка не дописується;
a fread() – неформатоване читання;
a freopen() – повторне відкривання в новому режимі;
a printf() – форматоване виведення у stdout;
a scanf() – форматоване введення зі stdin;
a fscanf() – форматоване читання з потоку;
a fseek() – позиціювання файлового покажчика;
a fwrite() – неформатований запис у потік;
a getc() – читає символ з потоку та переставляє файловий покажчик на наступну позицію;
a getchar() – макрос читання зі stdin (аналог getc(stdin));
a gets() – читання рядка зі stdin;
a getw() – читання слова з потоку (цілого типу int);
a putc() – макрос запису символу в потік;
a putchar() – макрос запису у stdout;
a puts() – записує рядок з нуль-символом у stdout і дописує символ нового рядка;
a putw() – запис слова в потік;
a rewind() – установлення файлового покажчика на початок файла;
a setbuf() – установлює буфер для відкритого потоку;
a setvbuf() – установлює буфер із низкою додаткових параметрів;
a sprintf() – форматоване виведення в рядок;
a sscanf() – форматоване введення з рядка;
a tempnam() – генерує ім'я тимчасового файла в каталозі;
a tmpfile() – створює тимчасовий файл;
a ungetc() – повертає символ у потік;
a vfprintf(), vsprintf(), vfscanf(), vscanf(), vsscanf() – аналоги відповідних описаних вище функцій, але приймають як параметри покажчик на список аргументів – адрес змінних, що виводяться чи яким присвоюються значення, що вводяться.
Розглянемо деякі функції.
Функція printf(control, arg1, arg2, ...) визначає формат і друкує свої аргументи в стандартне виведення під керуванням рядка control. Керуючий рядок містить два типи об'єктів: звичайні символи, що просто копіюються у вихідний потік, і специфікації перетворень, кожна з яких викликає перетворення та друк чергового аргументу printf.
|
|
Продемонструємо вплив задання різних специфікацій на друк "hello, world" (12 символів).
:%10s:: hello, world::%10-s:: hello, world::%20s:: hello, world::%-20s:: hello, world::%20.10s:: hello, world::%-20.10s:: hello, world::%.10s:: hello, world:Функція scanf використовується для введення даних та є аналогом printf. Функція scanf(control,arg1,arg2,...) читає символи зі стандартного введення, інтерпретує їх відповідно до формату, зазначеного в аргументі control, і розміщує результати в інші аргументи. Наприклад, звертання
int 1;
float x;
char name[50];
scanf("&d%f%s",&i,&x,name);
з рядком при введенні
E-1 alpha
приводить до присвоювання i значення 25, x – значення 5.432 і name – рядка "alpha", який закінчується символом '\0'. Ці три поля введення можна розділювати довільною кількістю пропусків, табуляцій і символів нових рядків. Виклик функції
int i;float x;char name[50];scanf("%2d %f%*d%2s",&i,&x,name);із введенням
56789 0123 45a72присвоїть i значення 56, x – 789.0, пропустить 0123 і помістить у name рядок "45". При наступному звертанні до будь-якої процедури введення розгляд почнеться з літери а. У наведених вище фрагментах програм name є покажчиком і, отже, перед ним не потрібно поміщати знак &.
Аргументи функції scanf мають бути покажчиками. Найрозповсюдженіша помилка полягає в написанні scanf("%d",n); замість scanf("%d",&n);
Функції sscanf і sprintf здійснюють аналогічні перетворення, але оперують із рядком, а не файлом:
sprintf(string,control,arg1,arg2,...)sscanf(string,control,arg1,arg2,...) Функція sprintf перетворює свої аргументи arg1, arg2 і т. д. відповідно до формату, зазначеного в control, але розміщує результати у string, а не в стандартне виведення. Звичайно, рядок string має бути достатньо великим, щоб вмістити результат. Наприклад, якщо name – символьний масив, а n – ціле, тоsprintf(name,"temp%d",n);
створює в name рядок вигляду tempnnn, де nnn – значення n.
Функція sscanf виконує зворотні перетворення – вона переглядає рядок string відповідно до формату в аргументі control і поміщає результуючі значення в аргументи arg1, arg2 і т. д. Ці аргументи мають бути покажчиками. У результаті виклику
sscanf(name,"temp%d",&n);змінна n одержує значення рядка цифр, що йдуть за темр у name.
Аналогічними є функції fprintf() та fscanf(), що працюють із файлами. Вони мають першим параметром змінні типу FILE*.
Функції getc(), getchar(), gets(), getw() зчитують відповідно символ, рядок, слово з потоку; putc(), putchar(), puts(), putw() – записують.
Перед використанням файла його необхідно відкрити за допомогою функції fopen зі стандартної бібліотеки. Функція fopen використовує зовнішнє ім'я файла, проводить деякі обслуговуючі дії й повертає внутрішнє ім'я, що має використовуватися при читанні з файла чи записах у нього. Це внутрішнє ім'я, що називається покажчикомфайла, фактично є покажчиком на структуру, що містить певну інформацію про файл (місце розміщення буфера, поточна позиція символу в буфері, спосіб використання файла, читання чи запис тощо). Користувач може й не знати всіх технічних деталей. Наприклад:
FILE *fopen(),*fp;
Тут fp є покажчиком на FILE, а fopen повертає покажчик на FILE. Зверніть увагу, що FILE є ім'ям типу (це реалізовано як typedef). Фактичне звертання до функції fopen у програмі має вигляд
fp=fopen(name,mode);
Першим аргументом функції fopen є ім'я файла, що задається у вигляді символьного рядка. Другий аргумент mode (режим) також є символьним рядком, що вказує, як файл буде використовуватися. Допустимими режимами є: читання ("r"), запис ("w") і дописування в кінець ("a"). Також можна використовувати "r+" – відкривання існуючого файла для читання та запису, "w+" – створення нового файла для запису й читання, "a+" – відкривання для дописування в кінець чи читання. Якщо файл існує, то він перезапишеться.
|
|
Якщо ви відкриєте для запису неіснуючий файл, то його буде створено (якщо це можливо). Відкривання існуючого файла для запису приводить до знищення його старого вмісту. Спроба читання неіснуючого файла є помилкою. Помилки можуть бути зумовлені й іншими причинами (напр., спробою читання з файла, якщо на це немає дозволу). За наявності помилки функція повертає нульове значення покажчика NULL (яке для зручності визначається у файлі stdio.h).
При роботі з уже відкритими файлами найпростішими є функції getc і putc. Функція getc повертає наступний символ з файла; їй потрібен покажчик файла, щоб знати, з якого файла читати. Таким чином, c=getc(fp) поміщає в "с" наступний символ з файла-потоку, зазначеного за допомогою fp, і EOF, якщо досягнуто кінець файла.
Функція putc putc(c,fp) поміщає символ "с" у файл fp і повертає "с". Подібно функціям getchar і putchar, getc і putc можуть бути макросами, а не функціями.
Функції getchar і putchar можуть бути визначені в терміналах getc, putc, stdin і stdout таким чином:
#define getchar()getc(stdin)
#define putchar(с)putc(c,stdout)
При роботі з файлами для форматного введення й виведення можна використовувати функції fscanf і fprintf. Вони ідентичні функціям scanf і printf, за винятком того, що першим аргументом є покажчик файла.
Розглянемо програму для конкатенації файлів. Схема, що тут використовується, зручна (аргументи в командному рядку обробляються послідовно). Якщо такі аргументи відсутні, то обробляється стандартне введення. Це дозволяє використовувати програму як самостійно, так і як частину більшої задачі.
#include <stdio.h> main(argc, argv) /*cat: concatenate files*/ int argc; char *argv[]; { FILE *fp,*fopen(); if(argc==1) /*no args;copy standard input*/ filecopy(stdin); else while(--argc>0) if((fp=fopen(*++argv,"r"))==NULL) { printf("cat:can't open %\n",*argv); break; } else { filecopy(fp); fclose(fp); } } filecopy(fp) /*copy file fp to standard output*/ FILE*fp; { int c; while((c=getc(fp))!=EOF) putc(c,stdout); }Функція fclose зворотна за дією стосовно fopen; вона розриває зв'язок між покажчиком файла й зовнішнім ім'ям, установлений функцією fopen, і вивільняє покажчик файла. Більшість операційних систем мають деякі обмеження на кількість одночасно відкритих файлів, якими може оперувати програма. Існує також інша причина для застосування функції fclose до вихідного файла – вона викликає звільнення буфера (за нормального завершення роботи програми функція fclose викликається автоматично для кожного відкритого файла).
|
|