Limbajul de programare C acceptă multe funcții standard de bibliotecă pentru introducerea și ieșirea fișierelor . Aceste funcții formează baza fișierului antet al bibliotecii standard C. <stdio.h>
Funcționalitatea I/O a limbajului C este implementată la un nivel scăzut conform standardelor actuale. Limbajul C rezumă toate operațiunile cu fișiere în operațiuni pe fluxuri de octeți , care pot fi fie „fluxuri de intrare”, fie „fluxuri de ieșire”. Spre deosebire de unele limbaje de programare timpurii, limbajul C nu acceptă direct accesul aleatoriu la fișierele de date; pentru a citi informațiile scrise în mijlocul fișierului, programatorul trebuie să creeze un flux care să se uite în mijlocul fișierului și apoi să citească secvențial octeți din flux.
Modelul I/O pentru fișiere de streaming a fost popularizat în mare parte de sistemul de operare Unix scris în C. O mare parte din funcționalitatea sistemelor de operare moderne a moștenit fluxuri de la Unix, iar multe limbi din familia de limbaje de programare C au moștenit interfața I/O fișier C cu diferențe minore (de exemplu, PHP ). Biblioteca standard C++ reflectă conceptul de streaming în sintaxa sa (vezi iostream ).
Fișierul este deschis utilizând funcția fopen, care returnează informații despre fluxul I/O atașat la fișierul specificat sau alt dispozitiv de pe care este citit (sau pe care este scris). La eșec, funcția returnează un pointer nul .
O freopenfuncție similară de bibliotecă C efectuează o operație similară după prima închidere a oricărui flux deschis asociat cu parametrii săi.
Sunt anuntati ca
FILE * fopen ( const char * cale , const char * mode ); FILE * freeopen ( const char * cale , const char * mode , FILE * fp );Funcția este în esență un „wrapper” pentru un apel de sistemfopen de nivel superior al sistemului de operare Unix . De asemenea, este un înveliș în jurul unui apel de sistem Unix , iar structura limbajului C în sine se referă adesea la descriptorul de fișier Unix corespunzător. Într -un mediu POSIX , o funcție poate fi utilizată pentru a inițializa o structură cu un descriptor de fișier. Cu toate acestea, descriptorii de fișiere ca un concept pur Unix nu sunt reprezentați în standardul limbajului C. open fclosecloseFILEfdopenFILE
Parametrul mode(modul) pentru fopenși freopentrebuie să fie un șir și să înceapă cu una dintre următoarele secvențe:
modul | Descriere | incepe cu.. | ||
---|---|---|---|---|
r | rb | se deschide spre lectură | start | |
w | wb | se deschide pentru scriere (creează un fișier dacă nu există). Șterge conținutul și suprascrie fișierul. | start | |
A | ab | se deschide pentru atașare (creează un fișier dacă nu există) | Sfârşit | |
r+ | rb+ | r+b | se deschide pentru citit și scris | start |
w+ | wb+ | w+b | se deschide pentru citit și scris. Șterge conținutul și suprascrie fișierul. | start |
a+ | ab+ | a+b | se deschide pentru citire și scriere (creează un fișier dacă nu există) | Sfârşit |
Valoarea „ b ” este rezervată pentru modul binar C. Standardul limbajului C definește două tipuri de fișiere - text și binare - deși sistemul de operare nu necesită să faceți distincția între ele (cu toate acestea, pentru unele compilatoare, cum ar fi LCC , specificând „b” atunci când lucrați cu un fișier binar este fundamental!). Un fișier text este un fișier care conține text împărțit în linii de un caracter de delimitare sau o secvență de sfârșit de linie (pe Unix , un singur avans de linie \n; pe Microsoft Windows , un avans de linie este urmat de un întoarcere de cărucior ) \r\n. Când se citesc octeți dintr-un fișier text, caracterele de sfârșit de linie sunt de obicei asociate (înlocuite) cu linii noi pentru a simplifica procesarea. Când scrieți un fișier text, un singur caracter de linie nouă este asociat (înlocuit) cu o secvență specifică OS de caractere de final de linie înainte de scriere. Un fișier binar este un fișier din care octeții sunt citiți și scoși într-o formă „brută” fără nicio legătură (înlocuire).
Când un fișier este deschis în modul de actualizare (' + ' ca al doilea sau al treilea caracter al argumentului de desemnare a modului), atât intrarea cât și ieșirea pot fi efectuate pe același fir. Cu toate acestea, o scriere nu poate urma o citire fără un apel intermediar fflushsau o funcție de poziție a fișierului ( fseek, fsetpossau rewind), iar o citire nu poate urma o scriere fără un apel intermediar la funcția de poziție a fișierului. [unu]
Modurile Scriere și Adăugare încearcă să creeze un fișier cu numele dat, dacă nu există deja un astfel de fișier. După cum sa menționat mai sus, dacă această operație eșuează, fopenreturnează NULL.
Funcția fcloseia un singur argument: un pointer către structura fluxului FILEpentru a se închide.
int fclose ( FIȘIER * fp );Funcția returnează zero la succes și EOF la eșec. Când programul se termină normal, funcția este apelată automat pentru fiecare fișier deschis.
Funcția fgetceste folosită pentru a citi un caracter din flux.
int fgetc ( FIȘIER * fp );Dacă are succes fgetc, returnează următorul octet sau caracter din flux (în funcție de faptul dacă fișierul este „binar” sau „text”, așa cum s-a discutat mai sus). Altfel fgetcrevine EOF. (Un anumit tip de eroare poate fi identificat printr-un apel ferrorsau feofcu un indicator de fișier.)
O macrocomandă getc standard este, de asemenea, definită în <stdio.h>, funcționând cu succes ca fgetc, cu excepția unui lucru: fiind o macrocomandă, își poate procesa argumentele de mai multe ori.
Funcția standard getchareste, de asemenea, definită în <stdio.h>, nu acceptă argumente și este echivalentă cu . getc(stdin)
„Capcană” EOFO greșeală comună este să utilizați sau fgetcsă atribuiți rezultatul unei variabile de tip înainte de a o compara cu . Următorul fragment de cod demonstrează această eroare, iar versiunea corectă este afișată lângă el: getcgetcharchar EOF
Eroare | Corect |
---|---|
char c ; în timp ce (( c = getchar ()) != EOF ) { putchar ( c ); } | int c ; în timp ce (( c = getchar ()) != EOF ) { putchar ( c ); } |
Luați în considerare un sistem în care un tip charcare are 8 biți (în special arhitectura x86 ) reprezintă 256 de valori distincte. getcharpoate returna oricare dintre cele 256 de caractere posibile și poate, de asemenea, să se întoarcă EOFpentru a indica sfârșitul fișierului, a cărui valoare nu se poate potrivi cu niciuna dintre valorile lui char.
Când rezultatul getchareste atribuit unei variabile de tip char, care poate reprezenta doar 256 de valori diferite, are loc o pierdere forțată de informații - atunci când 257 de valori sunt comprimate în 256 de „locuri” , are loc o coliziune . Valoarea EOFatunci când este convertită în chardevine imposibil de distins de oricare dintre celelalte 256 de caractere. Dacă acest caracter se găsește într-un fișier, codul de mai sus l-ar putea lua ca un sfârșit de fișier sau, mai rău, dacă tipul char este nesemnat, atunci având în vedere că EOF - este o valoare negativă, nu poate fi niciodată egal cu niciun . nesemnat char. exemplul de mai sus nu se va încheia la marcajul de sfârșit al fișierului, ci va rula pentru totdeauna, retipărind caracterul rezultat din conversia EOFîn char.
În sistemele în care intși charsunt de aceeași dimensiune[ ce? ] , chiar și versiunea „corectă” nu va funcționa corect din cauza asemănării EOFși a altui caracter. Modul corect de a gestiona această situație este de a verifica feofși ferrordupă ce getcharrevine EOF. Dacă feofdetectează că sfârșitul fișierului nu a fost încă atins, dar ferror„raportează” că nu există erori, atunci cel EOFreturnat getcharpoate fi considerat caracterul curent. Astfel de verificări suplimentare sunt rareori făcute, deoarece majoritatea programatorilor presupun că codul lor nu va rula niciodată pe astfel de charsisteme „mari”. O altă modalitate este să utilizați o verificare în timp de compilare care UINT_MAX > UCHAR_MAXva împiedica cel puțin compilarea pe astfel de sisteme.
Funcția fgetseste folosită pentru a citi un șir dintr-un flux. Citirea continuă până la sfârșitul liniei ( hex :0D0A, echivalent în liste cu \n ) sau până la atingerea lungimii liniei în care se citește. Să presupunem că avem some_file.txt fișier cu text
palindromuri Și în Yenisei - albastru. Și lama este mică. Și vulpea, este deștept - șobolanul i-a purtat brânză. (I. Babitsky) #include <stdio.h> #include <șir.h> int main ( int argc , char * argv []) /* argc stochează numărul de parametri, iar argv[] indică acești parametri. De exemplu, dacă rulăm executabilul „fgets_example param1 param2”, atunci argc va fi egal cu 3, iar argv[] = { "fgets_example" , "param1" , "param2" } */ { FIȘIER * fișier ; char * fname = "some_file.txt" ; char result_string [ 20 ]; //Șir de 20 de caractere fișier = fopen ( fname , "r" ); if ( fișier == NULL ) { printf ( "nu se poate deschide fișierul '%s'" , fname ); returnează 0 ; } int i = 0 ; char * real_tail ; while ( fgets ( șir_rezultat , dimensiunea ( șir_rezultat ), fișier )) { real_tail = "" ; printf ( "Șir %d:Lungimea șirului - %d:" , i ++ , strlen ( șir_rezultat )); if ( result_string [ strlen ( result_string ) -1 ] == '\n' ) // verifică dacă ultimul element din șir este caracterul final { real_tail = " \\ n" ; result_string [ strlen ( result_string ) -1 ] = '\0' ; }; // această parte a codului a fost adăugată doar pentru a afișa caracterul de sfârșit de linie în consolă fără o nouă linie printf ( " %s%s \n " , result_string , real_tail ); } fclose ( fișier ); returnează 0 ; }ca urmare a executiei vom obtine
Linia 0:Lungimea liniei - 11:palindromi\n Linia 1: Lungimea liniei - 19: Si in Yenisei - si Linia 2:Lungimea liniei - 6:neva.\n Linia 3: Lungimea liniei este de 17: Și lama este mică.\n Linia 4: Lungimea liniei - 19: O vulpe, este deștept Linia 5: Lungimea liniei - 19: - brânză de șobolan Linia 6: Lungimea liniei - 19: purtat. (I. Babitsky Linia 7: lungimea liniei - 2:th)Funcția strlen determină lungimea unui șir prin numărul de caractere până la „\0”, de exemplu:
printf ( "%d" , strlen ( "123 \0 123" )); //ieșiri 4În limbajul de programare C, funcțiile freadși fwrite, respectiv, implementează operațiuni de intrare și de ieșire a fișierelor . si declarat in . freadfwrite <stdio.h>
fwrite este definit ca
int fwrite ( const char * array , size_t size , size_t count , FILE * stream );Funcția fwritescrie un bloc de date în flux. Aceasta va scrie o serie de elemente arrayîn poziția curentă în flux. Se va scrie un sizeoctet pentru fiecare element. Indicatorul de poziție a fluxului se va schimba la numărul de octeți scrierea cu succes. Valoarea returnată va fi egală countcu dacă scrierea s-a finalizat cu succes. În cazul unei erori, valoarea returnată va fi mai mică decât count.
Următorul program deschide un exemplu de fișier .txt , îi scrie un șir de caractere și apoi îl închide.
#include <stdio.h> #include <șir.h> #include <stdlib.h> int main ( void ) { FIȘIER * fp ; size_t count ; char const * str = "bună ziua \n " ; fp = fopen ( "example.txt" , "wb" ); dacă ( fp == NULL ) { perror ( "eroare la deschiderea exemplului.txt" ); returnează EXIT_FAILURE ; } count = fwrite ( str , sizeof ( char ), strlen ( str ), fp ); printf ( "%lu octeți s-au scris. fclose(fp) %s. \n " , ( unsigned long ) count , fclose ( fp ) == 0 ? "succes" : "error" ); fclose ( fp ); returnează 0 ; }Funcția fputceste folosită pentru a scrie un caracter în flux.
int fputc ( int c , FIȘIER * fp );Opțiunea csilentioasă este convertită în unsigned charînainte de ieșire. Dacă are succes, fputcreturnează caracterul scris. Dacă o eroare, atunci fputcreturnează EOF.
O macrocomandă standard putceste, de asemenea, definită în <stdio.h>, funcționând în același mod în general fputc, cu excepția faptului că, ca macrocomandă, își poate procesa argumentele de mai multe ori.
Funcția standard putchar, definită și în <stdio.h>, ia doar primul argument și este echivalentă cu , unde este argumentul menționat. putc(c, stdout)c
Următorul program C deschide un fișier binar numit myfile , citește cinci octeți din acesta și apoi închide fișierul.
#include <stdio.h> #include <stdlib.h> int main ( void ) { charbuffer [ 5 ] = { 0 } ; /* inițializați cu zerouri */ int i , rc ; FILE * fp = fopen ( "fișierul meu" , "rb" ); dacă ( fp == NULL ) { perror ( "Eroare la deschiderea \" myfile \" " ); returnează EXIT_FAILURE ; } pentru ( i = 0 ; ( rc = getc ( fp )) != EOF && i < 5 ; buffer [ i ++ ] = rc ); fclose ( fp ); dacă ( i == 5 ) { puts ( "Octeți citiți..." ); printf ( " %x %x %x %x %x \n " , tampon [ 0 ], tampon [ 1 ], tampon [ 2 ], tampon [ 3 ], tampon [ 4 ]); } altfel fputs ( "Eroare la citirea fișierului. \n " , stderr ); returnează EXIT_SUCCESS ; }