Риклад зґ списком роззсилки

™об показати, Як можна легко записувати великґ об'№ми даних, користуючись функцґЯми fread () ґ fwrite (), ми розглЯнемо програму роботи зґ списком розсилки. Џрограма зможе зберґгати адреси у файлґ. Ђдреси будуть зберґгатисЯ в масивґ структур наступного типу:

struct addr {

char name [30];

char street [40];

char city [20];

char state [3];

unsigned long int zip;

} Addr_list [MAX];

‡наченнЯ MAX визнача№ максимальну кґлькґсть адрес, що може бути у списку.

Џри виконаннґ програми поле name кожно» структури ґнґцґалґзу№тьсЯ порожнґм вказґвником (NULL). “ програмґ вґльною вважа№тьсЯ та структура, поле name Яко» мґстить рЯдок нульово» довжини, тобто ґм'Я адресата ЯвлЯ№ собою порожнґм рЯдком.

„алґ наведенґ функцґ» save () ґ load (), Якґ використовуютьсЯ вґдповґдно длЯ збереженнЯ ґ завантаженнЯ бази даних (списку розсилки). ‡вернґть увагу, наскґльки коротко вдалосЯ закодувати кожну з функцґй, а адже цЯ стислґсть досЯгнута завдЯки потужностґ fread () ґ fwrite ()! § ше звернґть увагу на те, Як цґ функцґ» перевґрЯють значеннЯ, що повертаютьсЯ функцґЯми fread () ґ fwrite (), щоб виЯвити таким чином можливґ помилки.

/* ‡береженнЯ списку. */

void save (void) {

FILE *fp;

register int i;

if ((fp = fopen ("maillist", "wb")) == NULL) {

printf ("Џомилка при вiдкриттi файлу. \n");

return;

}

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

if (*addr_list[i].name)

if (fwrite (&addr_list[i], sizeof (struct addr), 1, fp) != 1)

printf ("Џомилка при записi файлу. \n");

fclose (fp);

}

/* ‡авантажити файл. */

void load (void) {

FILE *fp;

register int i;

if ((fp = fopen ("maillist", "rb")) == NULL) {

printf ("Џомилка при вiдкриттi файлу. \ n");

return;

}

init_list ();

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

if (fread (&addr_list[i], sizeof (struct addr), 1, fp) != 1) {

if (feof (fp)) break;

printf ("Џомилка при читаннi файлу. \n");

}

fclose (fp);

}

Ћбидвґ функцґ», save () ґ load (), пґдтверджують (або не пґдтверджують) успґшнґсть виконаннЯ функцґЯми fread () ґ fwrite () операцґй з файлом, перевґрЯючи значеннЯ, що повертаютьсЯ функцґЯми fread () ґ fwrite (). Љрґм того, функцґЯ load () Явно перевґрЯ№, чи не досЯгнуто кґнець файлу. ђобить вона це за допомогою виклику функцґ» feof (). –е доводитьсЯ робити тому, що fread () ґ в разґ помилки, ґ при досЯгненнґ кґнцЯ файлу поверта№ одне ґ те ж значеннЯ.

„алґ показана всЯ програма, що оброблЯ№ списки розсилки. є» можна використовувати Як Ядро длЯ подальших розширень, в не», наприклад, можна додати засоби пошуку адрес.

/* Џроста програма обробки списку розсилки,

в Якґй використову№тьсЯ масив структур. */

# include <windows.h>

# include <locale.h>

# include <stdio.h>

# include <stdlib.h>

# define MAX 100

 

struct addr {

char name [30];

char street [40];

char city [20];

char state [20];

unsigned long int zip;

} addr_list [MAX];

void init_list (), enter ();

void delete1 (), list ();

void load (), save ();

int menu_select (), find_free ();

 

int main() {

setlocale(LC_CTYPE, "Russian");

char choice;

init_list (); /* ґнґцґалґзацґЯ масиву структур */

for (; ;) {

choice = menu_select ();

switch (choice)

{

case 1: enter (); break;

case 2: delete1 (); break;

case 3: list (); break;

case 4: save (); break;

case 5: load (); break;

case 6: exit (0);

}

}

system ("pause");

return 0;

}

 

/* §нґцґалґзацґЯ списку. */

void init_list () {

register int t;

for (t = 0; t <MAX; ++t) addr_list [t].name[0] = '\0';

}

/* ЋтриманнЯ значеннЯ, вибраного в меню. */

int menu_select () {

char s [80];

int c;

printf ("1. ‚вести iм'Я \n");

printf ("2. ‚идалити iм'Я \n");

printf ("3. ‚ивести список \n");

printf ("4. ‡берегти файл \n");

printf ("5. ‡авантажити файл \n");

printf ("6. ‚ихiд \n");

do {

printf ("\n ‚ведiть номер потрiбного пункту: ");

gets (s);

c = atoi (s);

} while (c <0 || c> 6);

return c;

}

/* „одаваннЯ адреси в список. */

void enter () {

int slot;

char s [80];

slot = find_free ();

if (slot == -1) {

printf ("\n ‘писок заповнений");

return;

}

printf ("‚ведiть iм'Я: ");

gets (addr_list [slot].name);

printf ("‚ведiть вулицю: ");

gets (addr_list [slot].street);

printf ("‚ведiть мiсто: ");

gets (addr_list [slot].city);

printf ("‚ведiть Ћбласть: ");

gets (addr_list [slot].state);

printf ("‚ведiть поштовий iндекс: ");

gets (s);

addr_list [slot].zip = strtoul (s, '\0', 10);

}

/* Џошук вґльно» структури. */

int find_free () {

register int t;

for (t = 0; addr_list[t].name [0] && t <MAX; ++t);

if (t == MAX) return -1; /* вґльних структур нема№ */

return t;

}

/* ‚идаленнЯ адреси. */

void delete1 () {

register int slot;

char s [80];

printf ("‚ведiть Ь запису: ");

gets (s);

slot = atoi (s);

if (slot >= 0 && slot <MAX)

addr_list [slot].name [0] = '\0';

}

/* ‚ивґд списку на екран. */

void list () {

register int t;

for (t = 0; t <MAX; ++t) {

if (addr_list[t].name [0])

{

printf ("%s \n", addr_list[t].name);

printf ("%s \n", addr_list[t].street);

printf ("%s \n", addr_list[t].city);

printf ("%s \n", addr_list[t].state);

printf ("%lu \n \n", addr_list[t].zip);

}

}

printf ("\n \n");

}

/* ‡береженнЯ списку. */

void save () {

FILE *fp;

register int i;

if ((fp = fopen ("maillist", "wb")) == NULL) {

printf ("Џомилка при вiдкриттi файлу. \n");

return;

}

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

if (*addr_list[i].name)

if (fwrite (&addr_list[i], sizeof (struct addr), 1, fp) != 1)

printf ("Џомилка при записi файлу. \n");

fclose (fp);

}

/* ‡авантажити файл. */

void load () {

FILE *fp;

register int i;

if ((fp = fopen ("maillist", "rb")) == NULL) {

printf ("Џомилка при вiдкриттi файлу. \ n");

return;

}

init_list ();

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

if (fread (&addr_list[i], sizeof (struct addr), 1, fp) != 1) {

if (feof (fp)) break;

printf ("Џомилка при читаннi файлу. \n");

}

fclose (fp);

}

 

”ункциЯ fseek()

”ормат функцґ»:

fseek(fp, n, m);

–Я функцґЯ встановлю№ вказґвник у файлґ fp в позицґю, що вґдсто»ть на n байт вґд поточно», а напрЯмок перемґщеннЯ (вперед або назад) визнача№тьсЯ параметром m, Який може бути заданий одним з трьох значень: 0, 1, 2 або однґ№ю з трьох символьних констант, визначених у файлґ stdio.h:

- SEEK_SET = 0 С до початку файлу;

- SEEK_CUR = 1 С вказґвник на поточну позицґю у файлґ;

- SEEK_END = 2 С до кґнцЯ файлу.

”ункцґЯ fseek () використову№тьсЯ длЯ введеннЯ/виведеннЯ потоком. „лЯ роботи не з потоковими даними слґд використовувати функцґю lseek (). ЏґслЯ функцґ» fseek () можна виконувати операцґ» оновленнЯ у файлах, вґдкритих длЯ поновленнЯ. Џри вдалому завершеннґ роботи fseek () поверта№ нуль, в ґншому випадку функцґЯ поверта№ код помилки. ’одґ глобальна змґнна errno прийма№ одне з наступних значень:

- EBADF - невґрний вказґвник файлу;

- EINVAL - невґрний аргумент функцґ»;

- ESPIPE - пошук на пристро» заборонений.

Џри прЯмому доступґ можна виконувати операцґ» веденнЯ/виведеннЯ, використовуючи систему введеннЯ/виведеннЯ мови ‘ ґ функцґю fseek (), Яка встановлю№ вказґвник поточно» позицґ» у файлґ. Ћсь прототип цґ№» функцґ»:

int fseek (FILE <вказґвник файлу>, long int <кґлькґсть_байт>, <початок_вґдлґку>);

кґлькґсть_байт - кґлькґсть байтґв, рахуючи вґд початок_вґдлґку, воно визнача№ нове значеннЯ вказґвника поточно» позицґ», а початок вґдлґку - це один з наступних макросґв:

Џочаток вґдлґку - Њакрос

Џочаток файлу - SEEK_SET

Џоточна позицґЯ - SEEK_CUR

Љґнець файлу - SEEK_END

’ому, щоб отримати у файлґ доступ на вґдстанґ кґлькґсть_байт байтґв вґд початку файлу, початок_вґдлґку повинен дорґвнювати SEEK_SET. ™об при доступґ вґдстань вґдраховуваласЯ вґд поточно» позицґ», використовуйте макрос SEEK_CUR, а щоб при доступґ вґдстань вґдраховуваласЯ вґд кґнцЯ файлу, потрґбно вказувати макрос SEEK_END. Џри успґшному завершеннґ сво№» роботи функцґЯ fseek () поверта№ нуль, а в разґ помилки - ненульове значеннЯ.

“ наступнґй програмґ показано, Як використову№тьсЯ fseek (). „ана програма в певному файлґ вґдшуку№ деЯкий байт, а потґм вґдобража№ його. “ командному рЯдку потрґбно вказати ґм'Я файлу, а потґм потрґбний байт, тобто його вґдстань в байтах вґд початку файлу.

# include <stdlib.h>

# include <stdio.h>

# include <windows.h>

# include <locale.h>

 

int main () {

setlocale(LC_CTYPE, "Russian");

FILE * fp;

char ch;

if ((fp = fopen ("testr", "r")) == NULL) {

printf ("Џомилка при вiдкриттi файлу. \ n");

system ("pause");

exit (1);

}

fseek (fp, 6, SEEK_SET);

ch=fgetc (fp);

printf ("“ 6-му байтi мiститьсЯ ");

putchar (ch);

printf ("\n");

fclose (fp);

system ("pause");

return 0;

}

”ункцґю fseek () можна використовувати длЯ доступу всерединґ багатьох значень одного типу, просто множачи розмґр даних на номер елемента, Який вам потрґбен. Ќаприклад, припустимо, № список розсилки, Який склада№тьсЯ з структур типу addr (визначених ранґше). ™об отримати доступ до десЯто» адреси у файлґ, в Якому зберґгаютьсЯ адреси, використовуйте наступний оператор:

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

Џоточне значеннЯ вказґвника поточно» позицґ» у файлґ можна визначити за допомогою функцґ» ftell (). Ћсь »» прототип:

long int ftell (FILE <вказґвником файлу>);

”ункцґЯ поверта№ поточне значеннЯ вказґвника поточно» позицґ» у файлґ, пов'Язаному з вказґвником файлу вф. Џри невдалому результатґ вона поверта№ -1.

‡азвичай прЯмий доступ може знадобитисЯ лише длЯ двґйкових файлґв. Џричина тут проста - тому що в текстових файлах можуть виконуватисЯ перетвореннЯ символґв, то може ґ не бути прЯмо» вґдповґдностґ мґж тим, що знаходитьсЯ в файлґ ґ тим байтом, до Якого потрґбен доступ. ёдиний випадок, коли треба використовувати fseek () длЯ текстового файлу - це доступ до тґ№» позицґ», Яка була вже знайдена за допомогою ftell (); такий доступ викону№тьсЯ за допомогою макросу SEEK_SET, використовуваного в Якостґ початку вґдлґку.

„обре пам'Ятайте наступне: навґть Якщо в файлґ знаходитьсЯ один тґльки текст, все одно цей файл при необхґдностґ можна вґдкрити ґ в двґйковому режимґ. ЌґЯкґ обмеженнЯ, пов'Язанґ з тим, що файли мґстЯть текст, до операцґй прЯмого доступу не вґдносЯтьсЯ. –ґ обмеженнЯ стосуютьсЯ лише до файлґв, вґдкритих в текстовому режимґ.

”ункциЯ ftell()

”ормат функцґ»:

long int i = ftell(fp);

Џоверта№ поточне значеннЯ вказґвника файлу fp (тобто номер поточно» позицґ») у виглЯдґ значеннЯ типу long int. ‚ґдлґк йде в байтах вґд початку файлу.

Џовернене значеннЯ може бути використане потґм у функцґ» fseek ().

џкщо виЯвленґ помилки, то функцґЯ поверта№ значеннЯ -1L ґ привласню№ глобальнґй змґннґй errno додатне значеннЯ.

# include <stdlib.h>

# include <stdio.h>

# include <windows.h>

# include <locale.h>

# include <string.h>

 

int main() {

setlocale(LC_CTYPE, "Russian");

char str [80];

int i=0;

long int l;

FILE *fp;

if ((fp = fopen ("test", "r")) == NULL) {

printf ("Џомилка при вiдкриттi файлу. \n");

system ("pause");

exit(1);

}

while (! feof (fp)) {

l = ftell(fp);

printf ("Ќомер поточно» позицi» %d перед зчитуваннЯм ", l);

fgets (str, 79, fp);

printf (str);

}

l = ftell(fp);

printf ("\n Ќомер поточно» позицi» %d пiслЯ зчитуваннЯ ", l);

printf ("\n");

fclose (fp);

system ("pause");

return 0;

}

”ункциЯ fscanf()

”ормат функцґ»:

fscanf(fp, Control, arg1, arg2, ... , argn);

”ункцґЯ чита№ данґ з файлу з вказґвником fp, перетворю№ »х за форматами, записаними у керуючому рЯдку Control, ґ вґдформатованґ данґ запису№ в аргументи arg1, ... , аrgn. „окладнґ вґдомостґ про роботу цґ№» функцґ» можна отримати, ознайомившись з роботою функцґ» scanf () (функцґю scanf ()).

”ункциЯ fprintf()

”ормат функцґ»:

fprinf(fp, Control, arg1, arg2, ... , argn);

‚иводить данґ в файл з вказґвником fp, перетворю№ аргументи arg1, ... , аrgn до форматґв, Якґ записанґ в керуючому рЯдку Control, ґ вґдформатованґ данґ запису№ в файл. „окладнґ вґдомостґ про роботу цґ№» функцґ» можна отримати, ознайомившись з роботою функцґ» printf ().

Љрґм основних функцґй введеннЯ/виведеннЯ, про Якґ йшла мова, в системґ введеннЯ/виведеннЯ мови ‘ також № функцґ» fprintf () ґ fscanf (). –ґ двґ функцґ», за винЯтком того, що призначенґ длЯ роботи з файлами, ведуть себе точно так само, Як ґ printf () та scanf (). Џрототипи функцґй fprintf () ґ fscanf () наступнґ:

int fprintf (FILE * вф, const char * керуючий_рЯдок, ...);

int fscanf (FILE * вф, const char * керуючий_рЯдок, ...);

де вф - вказґвник файлу, що поверта№тьсЯ в результатґ виклику fopen (). Ћперацґ» введеннЯ/виведеннЯ функцґ» fprintf () ґ fscanf () виконують з тим файлом, на Який вказу№ вф.

‚ Якостґ прикладу пропону№тьсЯ розглЯнути наступну програму, Яка чита№ з клавґатури рЯдок ґ цґле значеннЯ, а потґм запису№ »х у файл на диску; ґм'Я цього файлу Р test1. ЏґслЯ цього програма чита№ цей файл ґ виводить ґнформацґю на екран. ЏґслЯ запуску програми перевґрте, Яким вийде файл test1. џк ви ґ побачите, в ньому буде цґлком легкий длЯ читаннЯ текст.

/* Џриклад використаннЯ fscanf () ґ fprintf () */

# include <stdlib.h>

# include <stdio.h>

# include <windows.h>

# include <locale.h>

 

int main () {

setlocale(LC_CTYPE, "Russian");

FILE *fp;

char s [80];

int t;

if ((fp = fopen ("test1", "w")) == NULL) {

printf ("Џомилка при вiдкриттi файлу. \ n");

system ("pause");

exit (1);

}

printf ("‚ведiть рЯдок i число: ");

fscanf (stdin, "%s %d", s, &t); /* читати з клавґатури */

fprintf (fp, "%s %d", s, t); /* писати в файл */

fclose (fp);

if ((fp = fopen ("test1", "r")) == NULL) {

printf ("Џомилка при вiдкриттi файлу. \n");

system ("pause");

exit (1);

}

printf("\n");

fscanf (fp, "%s %d", s, &t); /* читаннЯ з файлу */

fprintf (stdout, "%s %d", s, t); /* виведеннЯ на екран */

printf("\n");

fclose (fp);

system ("pause");

return 0;

}

Њаленьке попередженнЯ. •оча читати рґзносортнґ данґ з файлґв на дисках ґ писати »х у файли, розташованґ також на дисках, часто легше всього саме за допомогою функцґй fprintf () ґ fscanf (), але це не завжди найефективнґший спосґб виконаннЯ операцґй читаннЯ ґ запису. ’ак Як данґ в форматґ ASCII записуютьсЯ так, Як вони повиннґ з'ЯвитисЯ на екранґ (а не в двґйковому виглЯдґ), то кожен виклик цих функцґй пов'Язаний з певними накладними витратами. ’ому, Якщо треба пґклуватисЯ про розмґр файлу або швидкостґ, то, швидше за все, доведетьсЯ використовувати fread () ґ fwrite ().

”ункциЯ rewind()

”ормат функцґ»:

rewind(<вказґвник_на_файл>);

‚становлю№ вказґвник поточно» позицґ» у файлґ на початок файлу. ‚иклик функцґ» rewind (<вказґвник_на_файл>) вґдповґда№ виклику функцґ» fseek (<вказґвник_на_файл>, 0L, SEEK_SET) за винЯтком того, що rewind () скида№ ґндикатор кґнцЯ файлу ґ ґндикатори помилок, а fseek () скида№ тґльки ґндикатор кґнцЯ файлу. ЏґслЯ функцґ» rewind () можна виконувати операцґ» оновленнЯ длЯ файлґв, вґдкритих длЯ поновленнЯ. ”ункцґЯ не поверта№ нґЯкого значеннЯ.

™об познайомитисЯ з rewind (), змґнимо програму, розглЯнуту ранґше, таким чином, щоб вона вґдображала вмґст файлу вґдразу пґслЯ його створеннЯ. ™об виконати вґдображеннЯ, програма пґслЯ завершеннЯ введеннЯ "перемоту№" файл, а потґм чита№ його з самого початку. ‡вернґть увагу, що зараз файл необхґдно вґдкрити в режимґ читаннЯ/запису, використовуючи Як аргумент режим, що зада№ рЯдок "w+".

 

# include <stdlib.h>

# include <stdio.h>

# include <windows.h>

# include <locale.h>

# include <string.h>

 

int main() {

setlocale(LC_CTYPE, "Russian");

char str [80];

FILE *fp;

if ((fp = fopen ("TEST", "w+")) == NULL) {

printf ("Џомилка при вiдкриттi файлу. \ n");

system ("pause");

exit(1);

}

do {

printf ("‚ведiть рЯдок (порожнiй рЯдок - длЯ виходу): \n");

gets (str);

strcat (str, "\n"); // додаваннЯ роздґльника рЯдкґв

fputs (str, fp);

} while (strcmp("\n", str)); // strcmp() - порґвнЯннЯ рЯдкґв

/* ’епер викону№тьсЯ читаннЯ ґ вґдображеннЯ файлу */

rewind (fp); /* встановити вказґвник поточно» позицґ» на початок файлу. */

while (! feof (fp)) {

fgets (str, 79, fp);

printf (str);

}

fclose (fp);

system ("pause");

return 0;

}

 

”ункциЯ remove()

”ормат функцґ»:

int remove (< ґм'Я_файлу>);

”ункцґЯ видалЯ№ файл з ґм'Ям FILENameString. Џеред видаленнЯм файл повинен бути закритий. ђЯдок FILENameString повинен мґстити повний шлЯх до файлу. Џри нормальному завершеннґ завданнЯ функцґЯ поверта№ нуль, а в разґ помилки Р 1 (ненульове значеннЯ). Џри цьому глобальна змґнна errno прийма№ наступнґ значеннЯ:

- EACCES - заборонено видалЯти;

- ENOENT - нема№ такого файлу або директорґ».

Ќаступна програма вилуча№ файл. Ћднак спочатку вона да№ можливґсть передумати. “тилґта, подґбна цґй, може стати в нагодґ комп'ютерним користувачам-новачкам.

/* Џодвґйна перевґрка перед вилученнЯм. */

# include <stdlib.h>

# include <stdio.h>

# include <windows.h>

# include <locale.h>

# include <ctype.h>

 

int main() {

setlocale(LC_CTYPE, "Russian");

char str [80];

char filename[20]={"test"};

printf ("‚илучити файл test? (y/n):");

gets (str);

if (toupper (*str) == 'y')

remove (filename);

if (remove (filename)) {

printf ("Ќе можна вилучити файл. \n");

system ("pause");

exit (1);

}

system ("pause");

return 0;

}

 

”ункциЯ FILElength()

”ормат функции:

long FILElength(fp);

”ункцґЯ поверта№ довжину файлу з вказґвником fp в байтах. „лЯ роботи функцґ» потрґбно пґдключити файл io.h. “ випадку помилки функцґЯ поверта№ - 1, та глобальна змґнна errno набува№ значеннЯ EBADF - невґрний вказґвник файлу.

”ункциЯ ferror()

”ормат функцґ»:

ferror(fp);

”ункцґЯ ferror() визнача№, чи вґдбуласЯ помилка пґд час виконаннЯ операцґ» з файлом. Џрототип цґ№» функцґ» наступний:

int ferror(FILE < вказґвник_файлу >);

”ункцґЯ поверта№ значеннЯ true (ґстина), Якщо при останнґй операцґ» з файлом сталасЯ помилка, в ґншому ж випадку вона поверта№ false (неправда). ’ак Як при будь-Якґй операцґ» з файлом встановлю№тьсЯ своЯ умова помилки, то пґслЯ кожно» тако» операцґ» слґд одразу викликати ferror (), а ґнакше данґ про помилцґ можуть бути втраченґ.

“ наступнґй програмґ показано застосуваннЯ ferror (). Џрограма видалЯ№ табулЯцґ» з файлу, замґнюючи »х пробґлами. ђозмґр табулЯцґ» визнача№тьсЯ макросом TAB_SIZE. ‡вернґть увагу, що ferror () виклика№тьсЯ пґслЯ кожно» операцґ» з файлом.

/* Џрограма замґню№ в текстовому файлґ символи табулЯцґ» пробґлами ґ вґдслґдкову№ помилки. */

# include <stdlib.h>

# include <stdio.h>

# include <windows.h>

# include <locale.h>

# define IN 0

# define OUT 1

void err (int e);

 

int main() {

setlocale(LC_CTYPE, "Russian");

FILE *in, *out;

int i;

char ch;

if ((in = fopen ("testr", "rb")) == NULL) {

printf ("Ќе можна вiдкрити файл testr. \n");

system ("pause");

exit(1);

}

if ((out = fopen ("testw", "wb")) == NULL) {

printf ("Ќе можна вiдкрити файл testw. \n");

system ("pause");

exit(1);

}

do {

ch = fgetc (in);

if (ferror (in)) err (IN);

/* џкщо знайдена табулЯцґЯ, виводитьсЯ пробґл */

if (ch == '\t')

{

putc (' ', out);

if (ferror (out)) err (OUT);

}

else

{

putc (ch, out);

if (ferror (out)) err (OUT);

}

} while (!feof (in));

fclose (in);

fclose (out);

system ("pause");

return 0;

}

 

void err (int e) {

if (e == IN) printf ("Џомилка при введеннi. \n");

if (e == OUT) printf ("Џомилка при виведеннi. \n");

system ("pause");

exit (1);

}

 

”ункциЯ freopen()

”ормат функцґ»:

FILE *freopen(const char *FILEname, const char *mode, FILE *stream);

”ункцґЯ пґдставлЯ№ файл, заданий в першому параметрґ, замґсть уже вґдкритого потоку. ‚она закрива№ потґк незалежно вґд того, чи вґдкритий вґн. –Я функцґЯ корисна длЯ замґни файлу, пов'Язаного зґ стандартними пристроЯми введеннЯ/виведеннЯ stdin, stdout або stderr. ‘пособи вґдкриттЯ файлу аналогґчнґ функцґ» fopen (). Џри успґшному завершеннґ функцґЯ поверта№ вказґвник типу FILE (Як ґ функцґЯ fopen ()), при неуспґшному - NULL.

Џриклад перенаправленнЯ потоку за допомогою функцґ» freopen () наведено в лґстингу 1.

Истинг 1

/* ЏеренаправленнЯ стандартного виводу у файл */

if (freopen ("OUTPUT.FIL", "w", stdout) == NULL)

fprintf (stderr, "error redirecting stdout \n");

/* –ей висновок пґде вже в файл */

printf ("This will go into a FILE.");

/* ‡акриттЯ стандартного потоку */

fclose (stdout);

”ункциЯ ferror()

”ормат функцґ»:

ferror(FILE *fp);

”ункцґЯ вида№ ненульове значеннЯ, Якщо операцґЯ з файловим потоком завершу№тьсЯ з помилкою (наприклад, виника№ помилка читаннЯ файлу). „лЯ обробки помилок введеннЯ/виведеннЯ слґд записати цю функцґю перед блоком роботи з файлом у виглЯдґ:

if (ferror(fp)) { команди обробки помилок введеннЯ/виведеннЯ }

џк тґльки вґдбудетьсЯ помилка, викона№тьсЯ цЯ функцґЯ, ґ почнуть працювати команди обробки помилок.

”ункциЯ exit()

”ормат функцґ»:

exit(int status);

–Я функцґЯ використову№тьсЯ длЯ термґнового завершеннЯ роботи програми при обробцґ помилок вґдкриттЯ файлу, а також длЯ перериваннґ роботи програми з Якихось причин. Џеред завершеннЯм всґ файли закриваютьсЯ, залишки даних, що знаходЯтьсЯ в буферґ виведеннЯ, записуютьсЯ в пам'Ять ґ викликаютьсЯ функцґ» обробки помилок, попередньо заре№строванґ спецґальною функцґ№ю atexit (). –ґ функцґ» обробки помилок потрґбно написати самим ґ заре№струвати »х за допомогою виклику функцґ» atexit ().

„лЯ виклику функцґ» atexit () потрґбно пґдключити файл stdlib.h. Љожен виклик atexit () ре№стру№ нову функцґю exit (). Њожна заре№струвати до 32-х функцґй exit (). ‚они виконуватимутьсЯ за принципом роботи стеково» пам'Ятґ: "останнґй увґйшов - перший вийшов". ’обто останнЯ заре№стрована функцґЯ буде виконана першою. ЏоЯснимо сказане на прикладґ програми, наведено» в лґстингу 2.

Истинг 2

# include <stdio.h>

# include <stdlib.h>

/* –е перша функцґЯ exit () */

void exit_fn1 (void) {

printf ("Exit function # 1 called \ n");

}

/* –е друга функцґЯ exit () */

void exit_fn2 (void) {

printf ("Exit function # 2 called \ n");

}

/* ‚ основнґй програмґ вґдбува№тьсЯ ре№страцґЯ заданих ранґше функцґй exit (). ’ут же застосову№тьсЯ ґ сама функцґЯ exit (), Яка перед завершеннЯм роботи програми стане викликати цґ заре№строванґ ранґше функцґ» */

int main (void) {

/* ђе№страцґЯ першо» функцґ» */

atexit (exit_fn1);

/* ђе№страцґЯ друго» функцґ» */

atexit (exit_fn2);

/* Exit () спочатку викличе другу функцґю, тому що вона булла заре№стрована останньо», а потґм - першу функцґю. ЏґслЯ цього програма завершитьсЯ. */

exit (0);

return 0;

}

џке б числове значеннЯ ви не пґдставили замґсть аргументу функцґ», виклик заре№строваних функцґй exit () все одно вґдбудетьсЯ. џкщо ж не була заре№стрована жодна функцґЯ, то вґдбудетьсЯ завершеннЯ програми. ђе№страцґЯ функцґй exit () дґйсна тґльки в межах однґ№» програми.