Jinsi ya kuandika faili ya ingizo kwa s. Kufungua faili

Lebo: Faili za maandishi, fopen, fclose, feof, setbuf, setvbuf, fflush, fgetc, fprintf, fscanf, fgets, mtiririko ulioakibishwa, mtiririko usio na buffer.

Fanya kazi na faili za maandishi

Kufanya kazi na faili ya maandishi ni sawa na kufanya kazi na kiweko: kwa kutumia vitendaji vya kuingiza vilivyoumbizwa tunahifadhi data kwenye faili, kwa kutumia vitendaji vya kutoa vilivyoumbizwa tunasoma data kutoka kwa faili. Kuna nuances nyingi ambazo tutaangalia baadaye. Shughuli kuu zinazohitajika kufanywa ni

  • 1. Fungua faili ili iweze kupatikana. Ipasavyo, unaweza kuifungua kwa kusoma, kuandika, kusoma na kuandika, kuandika tena au kuandika hadi mwisho wa faili, nk. Unapofungua faili, kundi la makosa linaweza pia kutokea - faili inaweza kuwa haipo, inaweza kuwa aina ya faili isiyo sahihi, huenda usiwe na ruhusa ya kufanya kazi na faili, nk. Yote hii lazima izingatiwe.
  • 2. Kufanya kazi moja kwa moja na faili - kuandika na kusoma. Hapa tunahitaji pia kukumbuka kuwa hatufanyi kazi na kumbukumbu ya ufikiaji bila mpangilio, lakini kwa mkondo uliohifadhiwa, ambao unaongeza maelezo yake mwenyewe.
  • 3. Funga faili. Kwa kuwa faili ni rasilimali ya nje ya programu, ikiwa haijafungwa, itaendelea kunyongwa kwenye kumbukumbu, ikiwezekana hata baada ya programu kufungwa (kwa mfano, haitawezekana kufuta faili wazi au kufanya mabadiliko; na kadhalika.). Kwa kuongeza, wakati mwingine ni muhimu si kufunga, lakini "kufungua upya" faili ili, kwa mfano, kubadilisha hali ya kufikia.

Kwa kuongeza, kuna idadi ya kazi wakati hatuhitaji kufikia yaliyomo ya faili: kubadilisha jina, kusonga, kunakili, nk. Kwa bahati mbaya, kiwango cha C hakina maelezo ya utendakazi kwa mahitaji haya. Kwa kweli, zinapatikana kwa kila utekelezaji wa mkusanyaji. Kusoma yaliyomo kwenye saraka (folda, saraka) pia ni kupata faili, kwa sababu folda yenyewe ni faili iliyo na metainformation.

Wakati mwingine ni muhimu kufanya shughuli za msaidizi: hoja kwenye eneo linalohitajika kwenye faili, kumbuka nafasi ya sasa, kuamua urefu wa faili, nk.

Ili kufanya kazi na faili, unahitaji kipengee cha FILE. Kipengee hiki huhifadhi kitambulisho cha mtiririko wa faili na maelezo yanayohitajika ili kuidhibiti, ikijumuisha kielekezi kwa bafa yake, kiashirio cha nafasi ya faili na viashirio vya hali.

Kitu cha FILE yenyewe ni muundo, lakini sehemu zake hazipaswi kufikiwa. Programu inayobebeka lazima ichukue faili kama kitu dhahania kinachoruhusu ufikiaji wa mtiririko wa faili.

Uundaji na ugawaji wa kumbukumbu kwa kitu cha aina FILE unafanywa kwa kutumia fopen au tmpfile kazi (kuna wengine, lakini tutazingatia haya tu).

Kazi ya fopen inafungua faili. Inapokea hoja mbili - kamba yenye anwani ya faili na kamba yenye hali ya kufikia faili. Jina la faili linaweza kuwa kamili au la jamaa. fopen inarudisha kielekezi kwa kitu cha FILE ambacho kinaweza kutumika kupata faili zaidi.

FILE* fopen(const char* jina la faili, const char* mode);

Kwa mfano, hebu tufungue faili na kuandika Hello World ndani yake

#pamoja na #pamoja na #pamoja na void main() ( //Kwa kutumia utofauti wa faili tutafikia faili FILE *faili; //Fungua faili ya maandishi yenye ruhusa ya kuandika faili = fopen("C:/c/test.txt", "w+t") ; //Andika kwa faili fprintf(faili, "Hujambo, Ulimwengu!"); //Funga faili fclose(faili); getch();)

Kazi ya fopen yenyewe hutenga kumbukumbu kwa kitu; kusafisha hufanywa na kazi ya fclose. Inahitajika kufunga faili, haitajifunga yenyewe.

Chaguo la kukokotoa la fopen linaweza kufungua faili katika hali ya maandishi au ya binary. Chaguo msingi ni maandishi. Njia ya ufikiaji inaweza kuwa kama ifuatavyo

Chaguzi za ufikiaji wa faili.
Aina Maelezo
r Kusoma. Faili lazima iwepo.
w Andika faili mpya. Ikiwa faili iliyo na jina sawa tayari ipo, yaliyomo yake yatapotea.
a Andika hadi mwisho wa faili. Uendeshaji wa nafasi (fseek, fsetpos, frewind) hupuuzwa. Faili imeundwa ikiwa haikuwepo.
r+ Kusoma na kusasisha. Unaweza kusoma na kuandika. Faili lazima iwepo.
w+ Kurekodi na kusasisha. Faili mpya imeundwa. Ikiwa faili iliyo na jina sawa tayari ipo, yaliyomo yake yatapotea. Mnaweza kuandika na kusoma.
a+ Maliza chapisho na usasishe. Shughuli za uwekaji nafasi ni za kusoma tu na kupuuzwa kwa maandishi. Ikiwa faili haikuwepo, mpya itaundwa.

Ikiwa ni muhimu kufungua faili katika hali ya binary, basi barua b inaongezwa hadi mwisho wa mstari, kwa mfano "rb", "wb", "ab", au, kwa hali ya mchanganyiko, "ab +", " wb+”, “ab+”. Badala ya b, unaweza kuongeza barua t, kisha faili itafungua katika hali ya maandishi. Inategemea utekelezaji. Katika kiwango kipya cha C (2011), herufi x inamaanisha kuwa fopen inapaswa kushindwa ikiwa faili tayari ipo. Wacha tuongeze programu yetu ya zamani: fungua tena faili na uzingatie kile tulichoandika hapo.

#pamoja na #pamoja na #pamoja na void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); fprintf(faili, "Hujambo, Ulimwengu!"); fclose(faili); faili = fopen("C:/c/test.txt", "r"); fgets(bafa, 127, faili); printf("%s", bafa); fclose(faili); getch(); )

Badala ya kazi ya fgets, unaweza kutumia fscanf, lakini unahitaji kukumbuka kuwa inaweza tu kusoma mstari hadi nafasi ya kwanza.
fscanf(faili, "%127s", buffer);

Pia, badala ya kufungua na kufunga faili, unaweza kutumia kazi ya freopen, ambayo "hufungua tena" faili na haki mpya za kufikia.

#pamoja na #pamoja na #pamoja na void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); fprintf(faili, "Hujambo, Ulimwengu!"); freopen("C:/ c/test.txt", "r", faili); fgets(bafa, 127, faili); printf("%s", bafa); fclose(faili); getch(); )

Vipengele vya kukokotoa fprintf na fscanf hutofautiana na printf na scanf kwa kuwa tu huchukua kama hoja yao ya kwanza kielekezi kwa FILE ambacho watatoa au kutoka kwao watasoma data. Inastahili kuongeza mara moja kwamba kazi za printf na scanf zinaweza kubadilishwa kwa urahisi na kazi za fprintf na fscanf. Katika Mfumo wa Uendeshaji (tunazingatia mifumo ya uendeshaji ya kawaida na ya kutosha) kuna mitiririko mitatu ya kawaida: mkondo wa pato wa kawaida stdout, mkondo wa kawaida wa pembejeo stdin na mkondo wa matokeo wa makosa ya kawaida stderr. Zinafunguliwa kiotomatiki programu inapozinduliwa na inahusishwa na koni. Mfano

#pamoja na #pamoja na #pamoja na void main() ( int a, b; fprintf(stdout, "Ingiza nambari mbili\n"); fscanf(stdin, "%d", &a); fscanf(stdin, "%d", &b); ikiwa (b == 0) ( fprintf(stderr, "Error: divide by sifuri"); ) vinginevyo ( fprintf(stdout, "%.3f", (float) a / (float) b); ) getch(); )

Hitilafu katika kufungua faili

Ikiwa simu ya chaguo la kukokotoa itashindwa, itarudi NULL. Makosa wakati wa kufanya kazi na faili hufanyika mara nyingi, kwa hivyo kila wakati tunapofungua faili, tunahitaji kuangalia matokeo ya kazi.

#pamoja na #pamoja na #pamoja na #fafanua ERROR_OPEN_FILE -3 batili kuu() ( FILE *faili; char bafa; faili = fopen("C:/c/test.txt", "w"); ikiwa (faili == NULL) ( printf("Hitilafu ya kufungua faili"); getch(); toka(ERROR_OPEN_FILE); ) fprintf(faili, "Hujambo, Ulimwengu!"); freopen("C:/c/test.txt", "r", faili); ikiwa (faili = = NULL) ( printf("Hitilafu ya kufungua faili"); getch(); toka(ERROR_OPEN_FILE); ) fgets(bafa, 127, faili); printf("%s", bafa); fclose(faili); getch() ;)

Tatizo linatokea wakati faili kadhaa zinafunguliwa mara moja: ikiwa mmoja wao hawezi kufunguliwa, basi wengine lazima pia kufungwa

FILE *inputFile, *outputFile; isiyotiwa saini m, n; haijatiwa saini i, j; inputFile = fopen(INPUT_FILE, READ_ONLY); ikiwa (inputFile == NULL) ( printf("Hitilafu ya kufungua faili %s", INPUT_FILE); getch(); toka(3); ) outputFile = fopen(OUTPUT_FILE, WRITE_ONLY); ikiwa (outputFile == NULL) ( printf("Hitilafu ya kufungua faili %s", OUTPUT_FILE); getch(); ikiwa (inputFile != NULL) ( fclose(inputFile); ) toka(4); ) ...

Katika hali rahisi, unaweza kuchukua hatua moja kwa moja, kama ilivyo kwenye kipande cha msimbo uliopita. Katika hali ngumu zaidi, njia hutumiwa kuchukua nafasi ya RAII kutoka C ++: vifuniko, au vipengele vya mkusanyaji (kusafisha katika GCC), nk.

Kuhifadhi Data

Kama ilivyoelezwa hapo awali, tunapotoa data, huwekwa kwanza kwenye bafa. Bafa imefutwa

  • 1) Ikiwa imejaa
  • 2) Ikiwa mkondo umefungwa
  • 3) Ikiwa tunaonyesha wazi kwamba ni muhimu kufuta bafa (kuna vighairi hapa pia :)).
  • 4) Pia imefutwa ikiwa programu imekamilika kwa mafanikio. Wakati huo huo, faili zote zimefungwa. Katika kesi ya hitilafu ya wakati wa kukimbia, hii inaweza kutokea.

Unaweza kulazimisha upakuaji wa bafa kwa kupiga kitendakazi cha fflush(File *). Hebu tuangalie mifano miwili - pamoja na bila kusafisha.

#pamoja na #pamoja na #pamoja na batili kuu() ( FILE *faili; char c; faili = fopen("C:/c/test.txt", "w"); fanya ( c = getch(); fprintf(faili, "%c", c ); fprintf(stdout, "%c", c); //fflush(file); ) while(c != "q"); fclose(file); getch(); )

Ondoa maoni kwa simu isiyofaa. Wakati wa kukimbia, fungua faili ya maandishi na uangalie tabia.

Unaweza kukabidhi bafa ya faili mwenyewe kwa kuweka saizi yako mwenyewe. Hii inafanywa kwa kutumia kazi

Seti tupu (FILE * mkondo, char * bafa);

ambayo inachukua FILE iliyofunguliwa tayari na kielekezi kwa bafa mpya. Ukubwa wa bafa mpya lazima iwe si chini ya BUFSIZ (kwa mfano, kwenye kituo cha kazi cha BUFSIZ ni baiti 512). Ukipitisha NULL kama bafa, mtiririko unakuwa bila buffer. Unaweza pia kutumia kazi

Int setvbuf(FILE * mkondo, char * buffer, int mode, size_t size);

ambayo inakubali bafa ya saizi ya kiholela. Hali inaweza kuchukua maadili yafuatayo

  • _IFBF- buffering kamili. Data imeandikwa kwa faili wakati imejaa. Inaposomwa, bafa inachukuliwa kuwa kamili wakati operesheni ya kuingiza imeombwa na bafa haina kitu.
  • _IOLBF- bafa ya mstari. Data imeandikwa kwa faili wakati imejaa au wakati herufi mpya inapopatikana. Inaposomwa, bafa hujazwa kwa herufi mpya wakati operesheni ya kuingiza imeombwa na bafa haina kitu.
  • _IONBF- hakuna buffer. Katika kesi hii, ukubwa na vigezo vya buffer vinapuuzwa.
Ikiwa imefanikiwa, chaguo la kukokotoa linarudi 0.

Mfano: wacha tuweke bafa yetu na tuone jinsi usomaji kutoka kwa faili unafanywa. Hebu faili iwe fupi (kitu kama Hello, World!), na tunaisoma tabia kwa tabia

#pamoja na #pamoja na #pamoja na tupu kuu() ( FILE *ingizo = NULL; char c; char buffer = (0); ingizo = fopen("D:/c/text.txt", "rt"); setbuf(ingizo, bafa); wakati ( !feof(input)) ( c = fgetc(pembejeo); printf("%c\n", c); printf("%s\n", bafa); _getch(); ) fclose(input);)

Inaweza kuonekana kuwa data tayari iko kwenye bafa. Kusoma herufi kwa herufi hufanywa kutoka kwa bafa.

feof

Kazi int feof(FILE * mkondo); inarudi kweli ikiwa mwisho wa faili umefikiwa. Kazi ni rahisi kutumia wakati unahitaji kupitia faili nzima tangu mwanzo hadi mwisho. Acha kuwe na faili iliyo na maandishi maandishi text.txt. Tunasoma tabia ya faili kwa tabia na kuionyesha kwenye skrini.

#pamoja na #pamoja na #pamoja na utupu kuu() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); ikiwa (ingizo == NULL) ( printf("Hitilafu ya kufungua faili") ; _getch(); toka(0); ) huku (!feof(input)) ( c = fgetc(input); fprintf(stdout, "%c", c); ) fclose(input); _getch();)

Kila kitu kitakuwa sawa, lakini kazi ya feof haifanyi kazi kwa usahihi ... Hii ni kutokana na ukweli kwamba dhana ya "mwisho wa faili" haijafafanuliwa. Hitilafu ambayo mara nyingi hutokea wakati wa kutumia feof ni kwamba data ya mwisho iliyosomwa imechapishwa mara mbili. Hii ni kutokana na ukweli kwamba data imeandikwa kwa bafa ya pembejeo, usomaji wa mwisho hutokea na kosa na kazi inarudi thamani ya zamani iliyosomwa.

#pamoja na #pamoja na #pamoja na utupu kuu() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); ikiwa (ingizo == NULL) ( printf("Hitilafu ya kufungua faili") ; _getch(); toka(0); ) huku (!feof(input)) ( fscanf(input, "%c", &c); fprintf(stdout, "%c", c); ) fclose(input); _pata();)

Mfano huu utashindwa (uwezekano mkubwa) na uchapishe herufi ya mwisho ya faili mara mbili.

Suluhisho sio kutumia feof. Kwa mfano, hifadhi jumla ya idadi ya rekodi, au tumia ukweli kwamba vipengele vya fscanf n.k. kwa kawaida hurejesha idadi ya thamani zilizosomwa na kulinganishwa kwa usahihi.

#pamoja na #pamoja na #pamoja na utupu kuu() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); ikiwa (ingizo == NULL) ( printf("Hitilafu ya kufungua faili") ; _getch(); toka(0); ) huku (fscanf(input, "%c", &c) == 1) ( fprintf(stdout, "%c", c); ) fclose(input); _getch() ;)

Mifano

1. Faili moja ina nambari mbili - vipimo vya safu. Wacha tujaze faili ya pili na safu ya nambari za nasibu.

#pamoja na #pamoja na #pamoja na #pamoja na //Majina ya faili na ruhusa #fafanua INPUT_FILE "D:/c/input.txt" #fafanua OUTPUT_FILE "D:/c/output.txt" #fafanua READ_ONLY "r" #fafanua WRITE_ONLY "w" //Thamani ya juu zaidi ya mkusanyiko saizi #fafanua MAX_DIMENSION 100 //Hitilafu wakati wa kufungua faili #fafanua ERROR_OPEN_FILE -3 batili kuu() ( FILE *inputFile, *outputFile; unsigned m, n; unsigned i, j; inputFile = fopen(INPUT_FILE, READ_ONLY); inputFile == NULL) ( printf("Hitilafu ya kufungua faili %s", INPUT_FILE); getch(); toka(ERROR_OPEN_FILE); ) outputFile = fopen(OUTPUT_FILE, WRITE_ONLY); ikiwa (outputFile == NULL) ( printf("Kosa kufungua faili %s", OUTPUT_FILE); getch(); //Ikiwa faili inaweza kufunguliwa kwa kusomwa, basi lazima ifungwe ikiwa (inputFile != NULL) ( fclose(inputFile); ) exit(ERROR_OPEN_FILE); ) fscanf (inputFile, "%ud %ud", &m, &n); ikiwa (m > MAX_DIMENSION) ( m = MAX_DIMENSION; ) ikiwa (n > MAX_DIMENSION) ( n = MAX_DIMENSION; ) srand(time(NULL)); kwa (i = 0;i< n; i++) { for (j = 0; j < m; j++) { fprintf(outputFile, "%8d ", rand()); } fprintf(outputFile, "\n"); } //Закрываем файлы fclose(inputFile); fclose(outputFile); }

2. Mtumiaji anakili faili, na kwanza anachagua hali ya uendeshaji: faili inaweza kutolewa ama kwa console au kunakiliwa kwa faili mpya.

#pamoja na #pamoja na #pamoja na #fafanua ERROR_FILE_OPEN -3 batili kuu() ( FILE *origin = NULL; FILE *output = NULL; char filename; int mode; printf("Ingiza jina la faili: "); scanf("%1023s", jina la faili); origin = fopen (jina la faili, "r"); ikiwa (asili == NULL) ( printf("Hitilafu ya kufungua faili %s", jina la faili); getch(); toka(ERROR_FILE_OPEN); ) printf("ingiza modi: "); scanf( "%d", &mode); ikiwa (modi == 1) ( printf("Ingiza jina la faili: "); scanf("%1023s", jina la faili); pato = fopen(jina la faili, "w"); ikiwa (pato = = NULL) ( printf("Hitilafu ya kufungua faili %s", jina la faili); getch(); fclose(origin); toka(ERROR_FILE_OPEN); ) ) vinginevyo ( output = stdout; ) huku (!feof(origin)) ( fprintf (pato, "%c", fgetc(origin)); ) fclose(origin); fclose(output); getch();)

3. Mtumiaji huingiza data kutoka kwa console na imeandikwa kwa faili hadi ufunguo wa esc utakaposisitizwa. Angalia programu na uone. jinsi inavyofanya ikiwa unaingia backspace: ni nini pato kwa faili na ni nini pato kwa koni.

#pamoja na #pamoja na #pamoja na #fafanua ERROR_FILE_OPEN -3 batili kuu() ( FILE *output = NULL; char c; output = fopen("D:/c/test_output.txt", "w+t"); ikiwa (pato == NULL) ( printf ("Hitilafu ya kufungua faili"); _getch(); toka(ERROR_FILE_OPEN); ) kwa (;;) (c = _getch(); ikiwa (c == 27) ( break; ) fputc(c, pato); fputc( c, stdout); ) fclose(pato);)

4. Faili ina nambari kamili. Pata upeo wao. Wacha tuchukue fursa ya ukweli kwamba kazi ya fscanf inarudisha idadi ya vitu vilivyosomwa kwa usahihi na vinavyolingana. Nambari 1 inapaswa kurejeshwa kila wakati.

#pamoja na #pamoja na #pamoja na #fafanua ERROR_FILE_OPEN -3 batili kuu() ( FILE *input = NULL; int num, maxn, hasRead; input = fopen("D:/c/input.txt", "r"); ikiwa (ingizo == NULL) ( printf("Hitilafu ya kufungua faili"); _getch(); toka(ERROR_FILE_OPEN); ) maxn = INT_MIN; hasRead = 1; huku (imesoma == 1) ( hasRead = fscanf(input, "%d", &num); ikiwa (hasRead != 1) (endelea; ) ikiwa (num >

Suluhisho lingine ni kusoma nambari hadi tufikie mwisho wa faili.

#pamoja na #pamoja na #pamoja na #pamoja na #fafanua ERROR_FILE_OPEN -3 batili kuu() ( FILE *input = NULL; int num, maxn, hasRead; input = fopen("D:/c/input.txt", "r"); ikiwa (ingizo == NULL) ( printf("Hitilafu ya kufungua faili"); _getch(); toka(ERROR_FILE_OPEN); ) maxn = INT_MIN; huku (!feof(input)) ( fscanf(input, "%d", &num); ikiwa (num > maxn ) ( maxn = num; ) ) printf("max number = %d", maxn); fclose(input); _getch(); )

5. Faili ina maneno: neno la Kirusi, tabulation, neno la Kiingereza, katika safu kadhaa. Mtumiaji huingia neno la Kiingereza, ni muhimu kutoa moja ya Kirusi.

Faili ya tafsiri inaonekana kama hii

jua jua
kalamu ya penseli
penseli ya kalamu ya mpira
mlango wa mlango
dirisha la madirisha
mwenyekiti mwenyekiti
kiti cha mkono

na kuhifadhiwa katika usimbaji cp866 (OEM 866). Ni muhimu: jozi ya mwisho ya maneno pia inaisha na kulisha mstari.

Algorithm ni kama ifuatavyo: tunasoma mstari kutoka kwa faili, pata herufi ya kichupo kwenye mstari, badilisha herufi ya kichupo na sifuri, nakala ya neno la Kirusi kutoka kwa buffer, nakala ya neno la Kiingereza kutoka kwa buffer, angalia usawa.

#pamoja na #pamoja na #pamoja na #pamoja na #fafanua ERROR_FILE_OPEN -3 batili kuu() ( FILE *input = NULL; char buffer; char enWord; char ruWord; char usrWord; unsigned index; int length; int wasFound; input = fopen("D:/c/input.txt ", "r"); ikiwa (ingizo == NULL) ( printf("Hitilafu ya kufungua faili"); _getch(); toka(ERROR_FILE_OPEN); ) printf("ingiza neno: "); fgets(usrWord, 127, stdin ); ilipatikana = 0; wakati (!feof(pembejeo)) ( fgets(bafa, 511, ingizo); urefu = strlen(bafa); kwa (index = 0; index< length; index++) { if (buffer == "\t") { buffer = "\0"; break; } } strcpy(ruWord, buffer); strcpy(enWord, &buffer); if (!strcmp(enWord, usrWord)) { wasFound = 1; break; } } if (wasFound) { printf("%s", ruWord); } else { printf("Word not found"); } fclose(input); _getch(); }

6. Hesabu idadi ya mistari kwenye faili. Tutasoma herufi ya faili kwa herufi, tukihesabu idadi ya herufi "\n" hadi tutakapokutana na herufi ya EOF. EOF ni herufi maalum inayoonyesha kuwa ingizo limekamilika na hakuna data zaidi ya kusoma. Chaguo za kukokotoa hurejesha thamani hasi iwapo kutatokea hitilafu.
KUMBUKA: EOF ni ya aina int, kwa hivyo unahitaji kutumia int kusoma wahusika. Zaidi ya hayo, thamani ya EOF haijafafanuliwa na kiwango.

#fafanua _CRT_SALAMA_NO_ONYO #pamoja na #pamoja na #pamoja na int cntLines(const char *jina la faili) ( int lines = 0; int any; //yoyote ni ya aina int kwa sababu EOF ni ya aina int! FILE *f = fopen(jina la faili, "r"); ikiwa (f == NULL ) ( return -1; ) fanya ( any = fgetc(f); //printf("%c", any);//debug if (yoyote == "\n") ( lines++; ) ) wakati(yoyote ! = EOF); ​​fclose(f); mistari ya kurudisha; ) batili kuu() ( printf("%d\n", cntLines("C:/c/file.txt")); _getch(); )

Ru-Cyrl 18-mafunzo Sypachev S.S. 1989-04-14 [barua pepe imelindwa] Stepan Sypachev wanafunzi

Bado si wazi? - Andika maswali kwenye sanduku la barua

Hapo awali, wakati wa kuingiza na kutoa data, tulifanya kazi na mitiririko ya kawaida - kibodi na ufuatiliaji. Sasa hebu tuangalie jinsi lugha C inavyotumia kupokea data kutoka kwa faili na kuziandika hapo. Kabla ya kufanya shughuli hizi, lazima ufungue faili na uifikie.

Katika lugha ya programu ya C, kielekezi kwa faili ni cha aina ya FILE na tamko lake linaonekana kama hii:
FILE *myfile;

Kwa upande mwingine, fopen() chaguo la kukokotoa hufungua faili kwenye anwani iliyotajwa kama hoja yake ya kwanza katika hali ya kusoma ("r"), modi ya kuandika ("w"), au modi ya kuongeza ("a") na kurudisha pointer. kwake kwa programu. Kwa hivyo, mchakato wa kufungua faili na kuiunganisha kwenye programu inaonekana kama hii:
myfile = fopen("hello.txt", "r");

Wakati wa kusoma au kuandika data kwa faili, hupatikana kwa njia ya pointer ya faili (katika kesi hii, myfile).

Ikiwa kwa sababu moja au nyingine (hakuna faili kwenye anwani maalum, ufikiaji wake umekataliwa) kazi ya fopen () haiwezi kufungua faili, basi inarudi NULL. Katika programu halisi, karibu kila mara hushughulikia kosa la kufungua faili kwenye tawi la if, lakini tutaacha hili zaidi.

Tamko la chaguo la kukokotoa la fopen() lipo katika faili ya kichwa cha stdio.h, kwa hivyo ni lazima ijumuishwe. Pia katika stdio.h aina ya muundo FILE imetangazwa.

Baada ya kufanya kazi na faili kukamilika, ni desturi ya kuifunga ili kufungua buffer kutoka kwa data na kwa sababu nyingine. Hii ni muhimu hasa ikiwa programu inaendelea kufanya kazi baada ya kufanya kazi na faili. Kuvunja uunganisho kati ya faili ya nje na pointer kutoka kwa programu inafanywa kwa kutumia fclose() kazi. Pointer kwa faili hupitishwa kwake kama parameta:
fclose(myfile);

Zaidi ya faili moja inaweza kufunguliwa katika programu. Katika kesi hii, kila faili lazima ihusishwe na pointer yake ya faili. Hata hivyo, ikiwa programu inafanya kazi kwanza na faili moja na kisha kuifunga, basi pointer inaweza kutumika kufungua faili ya pili.

Kusoma na kuandika kwa faili ya maandishi

fscanf()

fscanf() chaguo za kukokotoa ni sawa kimaana na kitendakazi cha scanf(), lakini tofauti na hicho, hutoa ingizo lililoumbizwa kutoka kwa faili badala ya ingizo la kawaida. Kazi ya fscanf() inachukua vigezo: pointer ya faili, kamba ya fomati, anwani za maeneo ya kumbukumbu ya kuandika data:
fscanf(myfile, "%s%d", str, &a);

Hurejesha nambari ya data iliyosomwa kwa ufanisi au EOF. Nafasi na herufi mpya huhesabiwa kama vikomo vya data.

Wacha tuseme tunayo faili iliyo na maelezo yafuatayo ya vitu:

Tufaha 10 23.4 ndizi 5 25.0 mkate 1 10.3

#pamoja na kuu () ( FILE * faili; struct food ( char name[ 20 ] ; unsigned qty; float price; ) ; struct food shop[ 10 ] ; char i= 0 ; file = fopen ( "fscanf.txt" , "r" ) ; wakati (fscanf (faili, "%s%u%f" , duka[ i].name , & (duka[ i].qty ) , & (duka[ i].price ) ) != EOF) ( printf ("%s %u %.2f \n", duka[ i].jina, duka[ i].qty, duka[ i].bei); i++; ))

Katika kesi hii, muundo na safu ya miundo hutangazwa. Kila mstari kutoka kwa faili unafanana na kipengele kimoja cha safu; kipengele cha safu ni muundo ulio na kamba na sehemu mbili za nambari. Kitanzi kinasoma safu mlalo moja kwa kila marudio. Wakati mwisho wa faili unakabiliwa, fscanf() inarudisha EOF na kitanzi kinaisha.

fgets()

Kitendakazi cha fgets() ni sawa na gets() kitendakazi na hufanya uingizaji wa mstari kwa mstari kutoka kwa faili. Simu moja kwa fgets() itasoma mstari mmoja. Katika kesi hii, huwezi kusoma mstari mzima, lakini sehemu yake tu tangu mwanzo. fgets() vigezo vinaonekana kama hii:
fgets (safu_ya_wahusika, nambari_ya_wahusika_kusomwa, kielekezi_kwa_faili)

Kwa mfano:
fgets(str, 50, myfile)

Simu hii ya chaguo la kukokotoa itasoma kutoka kwa faili inayohusishwa na kielekezi cha myfile mstari mmoja kamili wa maandishi ikiwa urefu wake ni chini ya vibambo 50, ikijumuisha herufi "\n", ambayo fomula ya kukokotoa pia itahifadhi katika safu. Kipengele cha mwisho (cha 50) cha safu ya safu kitakuwa herufi "\0" iliyoongezwa na fgets() . Ikiwa kamba ni ndefu, chaguo la kukokotoa litasoma herufi 49 na kuandika "\0" mwishoni. Katika kesi hii, "\n" haitakuwa kwenye mstari wa kusoma.

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

Katika mpango huu, tofauti na uliopita, data inasomwa mstari kwa mstari kwenye safu ya safu. Wakati mstari unaofuata unasomwa, uliopita unapotea. Kazi ya fgets() inarudisha NULL ikiwa haiwezi kusoma mstari unaofuata.

getc() au fgetc()

Getc() au fgetc() kazi (zote mbili zinafanya kazi) hukuruhusu kupata herufi moja inayofuata kutoka kwa faili.

wakati ((arr[ i] = fgetc (faili) ) != EOF) ( ikiwa (arr[ i] == " \n") (arr[i] = " \0 " ; printf("%s \n", sivyo); i = 0; ) mwingine i++; ) arr[i] = " \0 " ; printf("%s \n", sivyo);

Nambari ya mfano inaonyesha data kutoka kwa faili kwenye skrini.

Kuandika kwa faili ya maandishi

Kama vile ingizo, pato kwa faili linaweza kuwa tofauti.

  • Toleo lililoumbizwa. Kazi fprintf (faili_index, format_string, vigezo) .
  • Pato la baada kwa mstari. Kazi fputs(kamba, file_pointer) .
  • Pato la herufi kwa herufi. Kazi fputc() au putc(ishara, file_pointer) .

Ifuatayo ni mifano ya msimbo inayotumia mbinu tatu za kutoa data kwa faili.

Sehemu za uandishi za muundo mmoja kwa kila mstari wa faili:

file = fopen ("fprintf.txt" , "w" ) ; wakati (scanf ("%s%u%f" , shop[ i].name , & (shop[ i].qty ) , & (duka[ i].price ) ) != EOF) ( fprintf (faili, " %s %u %.2f \n", duka[ i].jina, duka[ i].qty, duka[ i].bei); i++; )

Pato la mstari kwa mstari kwa faili (fputs(), tofauti na puts() yenyewe, haiweki "\n" mwishoni mwa mstari):

while (anapata (arr) != NULL) ( fputs (arr, file); fputs (" \n", faili); )

Mfano wa matokeo ya herufi kwa herufi:

wakati ((i = getchar () ) != EOF) putc (i, faili);

Kusoma kutoka na kuandika kwa faili ya binary

Unaweza kufanya kazi na faili sio kama mlolongo wa wahusika, lakini kama mlolongo wa ka. Kimsingi, haiwezekani kufanya kazi na faili zisizo za maandishi kwa njia nyingine yoyote. Walakini, unaweza kusoma na kuandika kwa faili za maandishi kwa njia hii. Faida ya njia hii ya kupata faili ni kasi ya kusoma-kuandika: kizuizi kikubwa cha habari kinaweza kusoma / kuandikwa kwa ufikiaji mmoja.

Wakati wa kufungua faili kwa ufikiaji wa binary, parameta ya pili ya fopen() ni kamba "rb" au "wb".

Mada ya kufanya kazi na faili za binary ni ngumu sana na inahitaji somo tofauti ili kuisoma. Hapa tu sifa za kazi za kusoma na kuandika kwa faili, ambayo inachukuliwa kama mkondo wa kawaida, itazingatiwa.

Kazi za fread() na fwrite() huchukua kama vigezo:

  1. anwani ya eneo la kumbukumbu ambapo data imeandikwa au kusomwa kutoka,
  2. saizi ya aina yoyote,
  3. kiasi cha data iliyosomwa ya saizi maalum,
  4. faharisi ya faili.

Vitendaji hivi hurejesha idadi ya data iliyosomwa au kuandikwa kwa mafanikio. Wale. unaweza "kuagiza" usomaji wa vipengele 50 vya data, lakini upokea 10 tu. Hakutakuwa na kosa.

Mfano wa kutumia fread() na fwrite() kazi:

#pamoja na #pamoja na kuu () ( FILE * file; char shelf1[ 50 ], shelf2[ 100 ] ; int n, m; file = fopen ("shelf1.txt" , "rb" ) ; n= fread (rafu1, sizeof (char ) , 50 , faili); fclose (faili) ; file = fopen ("shelf2.txt" , "rb" ) ; m= fread (rafu2, sizeof (char ) , 50 , faili) ; fclose (faili) ; shelf1[ n] = " \0 " ; rafu2[m] = " \n"; rafu2[ m+ 1 ] = " \0 " ; file = fopen ("shop.txt" , "wb" ) ; fwrite (strcat (rafu2, rafu1) , sizeof (char ) , n+ m, faili); fclose (faili); )

Hapa jaribio linafanywa kusoma herufi 50 kutoka kwa faili ya kwanza. n huhifadhi idadi ya herufi zilizosomwa. Thamani ya n inaweza kuwa 50 au chini. Data imewekwa kwa safu. Kitu kimoja kinatokea na faili ya pili. Ifuatayo, mstari wa kwanza umeongezwa kwa pili, na data inatupwa kwenye faili ya tatu.

Kutatua tatizo

  1. Andika programu inayouliza mtumiaji jina (anwani) ya faili ya maandishi, kisha uifungue na uhesabu idadi ya wahusika na mistari ndani yake.
  2. Andika programu ambayo huandika kwa data ya faili iliyopokelewa kutoka kwa faili nyingine na kurekebishwa kwa njia fulani kabla ya kuandika. Kila safu ya data iliyopatikana kutoka kwa faili lazima ilingane na muundo.

- kulinganisha kutambua usawa au usawa.

Madhumuni ya vitendo ya kuhesabu ni kufafanua seti ya viunga vya ishara tofauti vya aina kamili.

Mfano wa kutumia anuwai zilizoorodheshwa:

mo=1, tu, sisi, th, fr, sa, su ) siku;

huweka(“ Ingiza siku ya juma (kutoka 1 hadi 7) : ”); scanf(“%d”, &t_day);

siku = siku; start = mo;

mwisho = w_day -t_day;

printf(“\n Jumatatu ni siku %d ya wiki, \ sasa ni siku %d. \n\

Hadi mwisho wa wiki siku %d (siku). ”, anza, t_day, mwisho);

Matokeo ya programu: Ingiza siku ya juma (kutoka 1 hadi 7): 2

Jumatatu ni siku ya 1 ya juma, sasa ni siku ya 2. Kuna siku 5 (siku) hadi mwisho wa juma.

18. Faili katika lugha C

Faili ni seti ya data iliyo kwenye vyombo vya habari vya nje na inachukuliwa kuwa moja wakati wa usindikaji. Faili zina data iliyokusudiwa kuhifadhi kwa muda mrefu.

Kuna aina mbili za faili: maandishi na binary. Faili za maandishi ni mlolongo wa herufi za ASCII na zinaweza kutazamwa na kuhaririwa kwa kutumia kihariri chochote cha maandishi.

Faili za binary (binary) ni mlolongo wa data, muundo ambao umedhamiriwa na programu.

Lugha ya C ina seti kubwa ya vitendakazi vya kufanya kazi na faili, ambazo nyingi zinapatikana katika maktaba ya stdio.h na io.h.

18.1. Kufungua faili

Kila faili imepewa jina la ndani la mantiki, ambalo hutumiwa baadaye wakati wa kuipata. Jina la kimantiki (kitambulisho cha faili) ni

pointer kwa faili, i.e. kwa eneo la kumbukumbu ambalo lina habari zote muhimu kuhusu faili. Umbizo la tamko la pointer ya faili ni kama ifuatavyo:

FILE * pointer kwa faili;

FILE - kitambulisho cha aina ya muundo kilichoelezewa kwenye maktaba ya kawaida

stdio.h na iliyo na habari ifuatayo:

aina ya muundo (

- idadi ya baiti ambazo hazijasomwa zilizobaki kwenye bafa;

saizi ya kawaida ya buffer ni ka 512; mara tu kiwango=0,

block inayofuata ya data inasomwa kwenye buffer kutoka kwa faili;

- bendera ya hali ya faili - soma, andika, ongeza;

- maelezo ya faili, i.e. nambari inayofafanua hapana-

kushikilia char bila saini;

- tabia isiyoambukizwa, i.e. ungetc-tabia;

- saizi ya bafa ya kati ya ndani;

bafa ya char isiyotiwa saini;

- thamani ya kielekezi cha ufikiaji ndani ya bafa, i.e.

hubainisha mwanzo wa bafa, mwanzo wa mstari, au thamani ya sasa

Thamani ya pointer ndani ya bafa kulingana na modi

ma buffering;

char *curp isiyotiwa saini;

- thamani ya sasa ya pointer kwa ufikiaji ndani ya

fera, i.e. inabainisha nafasi ya sasa katika bafa ya kubadilishana

endelea na programu;

istemp isiyo na saini;

- bendera ya faili ya muda;

- bendera wakati wa kufanya kazi na faili;

) FILE;

Kabla ya kuanza kufanya kazi na faili, i.e. Ili kuweza kusoma au kuandika habari kwa faili, lazima ifunguliwe kwa ufikiaji. Kwa lengo hili kazi ni kawaida kutumika

FILE* fopen(char* file_name, char* mode);

inachukua uwakilishi wa nje - jina la kimwili la faili kwenye kati (floppy disk, gari ngumu) na inafanana na jina la mantiki.

Jina la kimwili, i.e. jina la faili na njia yake imeainishwa na parameta ya kwanza

– mstari, kwa mfano, “a:Mas_dat.dat” – faili inayoitwa Mas_dat.dat iko kwenye floppy disk, “d:\\work\\Sved.txt” – faili inayoitwa Sved.txt iko kwenye diski ngumu. endesha kwenye saraka ya kazi.

Makini! Backslash (\), kama tabia maalum, imeandikwa mara mbili kwa mstari.

Baada ya kufunguliwa kwa mafanikio, kitendakazi cha fopen kinarudisha kielekezi kwenye faili (hapa kinajulikana kama kielekezi cha faili). Kwa hitilafu, NULL inarejeshwa. Hali hii kawaida hutokea wakati njia ya faili kufunguliwa imeelezwa vibaya. Kwa mfano, ikiwa katika darasa la maonyesho la chuo kikuu chetu unataja njia ambayo ni marufuku kwa kuandika (kawaida d:\work\ inaruhusiwa).

Kigezo cha pili ni mstari unaobainisha hali ya ufikiaji wa faili:

w - faili inafunguliwa kwa maandishi; ikiwa hakuna faili iliyo na jina lililopewa, itaundwa; ikiwa faili kama hiyo ipo, basi habari ya hapo awali inaharibiwa kabla ya kufunguliwa;

r - faili inafungua kwa kusoma tu; ikiwa hakuna faili kama hiyo, hitilafu hutokea;

a - faili inafunguliwa ili kuongeza habari mpya hadi mwisho;

r + - faili inafunguliwa kwa data ya uhariri - wote kuandika na kusoma habari inawezekana;

w+ - sawa na kwa r+;

a+ - sawa na kwa, kuandika tu kunaweza kufanywa popote kwenye faili; usomaji wa faili pia unapatikana;

t - faili inafungua katika hali ya maandishi; b - faili inafungua katika hali ya binary.

Hali ya maandishi hutofautiana na hali ya jozi kwa kuwa faili inapofunguliwa kama maandishi, jozi ya vibambo "mlisho wa mstari", "rejesho la gari" hubadilishwa na herufi moja: "milisho ya mstari" kwa utendaji wote wa kuandika data kwenye faili. , na kwa vitendaji vyote vya pato herufi "line feed" " sasa inabadilishwa na herufi mbili: "line feed", "carriage return".

Kwa chaguo-msingi, faili inafungua kwa hali ya maandishi. Mfano: FILE *f; - pointer kwa faili f imetangazwa;

f = fopen("d:\\work\\Dat_sp.cpp", "w"); - faili yenye jina la mantiki f, ambayo ina jina la kimwili Dat_sp.cpp, iko kwenye gari d, katika saraka ya kazi, inafunguliwa kwa kuandika; au kwa ufupi zaidi

FILE *f = fopen("d:\\work\\Dat_sp.cpp", "w");

18.2. Kufunga faili

Baada ya kufanya kazi na faili, ufikiaji wake lazima ufungwe. Hii inafanywa na kazi ya int fclose (kiashiria cha faili). Kwa mfano, kutoka kwa mfano uliopita, faili imefungwa kama hii: fclose (f);

Ili kufunga faili nyingi, kazi huletwa, iliyotangazwa kama ifuatavyo: batili fcloseall (batili);

Ikiwa unahitaji kubadilisha hali ya kufikia faili, lazima kwanza ufunge faili na kisha uifungue tena, lakini kwa haki tofauti za kufikia. Ili kufanya hivyo, tumia kazi ya kawaida:

FILE* fungua upya (char*file_name, char *mode, FILE *file_pointer);

Chaguo hili la kukokotoa hufunga kwanza faili iliyotangazwa file_pointer(kama fopen kazi inavyofanya), na kisha kufungua faili na jina la faili na ruhusa "mode".

Lugha ya C ina uwezo wa kufanya kazi na faili za muda ambazo zinahitajika tu wakati programu inaendesha. Katika kesi hii, kazi hutumiwa

FILE* tmpfile (batili);

ambayo huunda faili ya muda kwenye diski na haki za ufikiaji "w + b"; baada ya programu kukamilika au baada ya faili ya muda kufungwa, inafutwa kiatomati.

18.3. Andika - soma habari

Vitendo vyote vya kusoma na kuandika data kwenye faili vinaweza kugawanywa katika vikundi vitatu: shughuli za pembejeo za tabia-na-tabia; shughuli za mstari kwa mstari wa I/O; zuia shughuli za I/O.

Hebu tuangalie kazi kuu zinazotumiwa katika kila moja ya makundi haya matatu ya uendeshaji.

Mhusika-kwa-mhusika I/O

Katika vitendaji vya herufi kwa herufi za I/O, herufi moja inapokelewa kutoka kwa faili au herufi moja inatumwa kwa faili:

Safu ya I/O

Uhamisho wa vitendaji vya I/O kutoka kwa faili au kwenda

Zuia I/O

Zuia vitendaji vya I/O hufanya kazi kwenye vizuizi vyote

habari:

int fread (utupu*p, intsize,

- husoma n vizuizi vya ukubwa wa baiti kila moja kutoka kwa faili

int n, FILE *f)

la f kwa eneo la kumbukumbu na pointer p (inahitajika

int fwrite (utupu*p, intsize,

tenga kumbukumbu mapema ili kuzuia kusomwa);

- huandika n vitalu vya baiti za ukubwa kila moja kutoka kwa

int n, FILE *f)

eneo la kumbukumbu na pointer p hadi faili f.

I/O iliyoumbizwa inatolewa na vitendaji.

Kwa urahisi wa upatikanaji, habari katika vifaa vya kuhifadhi huhifadhiwa kwa namna ya faili.

Faili ni eneo lenye jina la kumbukumbu ya nje iliyotengwa kwa ajili ya kuhifadhi safu ya data. Data iliyo katika faili ni ya asili tofauti sana: mipango katika lugha ya algorithmic au mashine; data ya awali ya uendeshaji wa programu au matokeo ya utekelezaji wa programu; maandishi ya bure; picha za picha, nk.

Saraka (folda, saraka) - mkusanyiko unaoitwa wa ka kwenye njia ya uhifadhi iliyo na majina ya subdirectories na faili, zinazotumiwa katika mfumo wa faili ili kurahisisha shirika la faili.

Mfumo wa faili inayoitwa sehemu ya kazi ya mfumo wa uendeshaji ambayo hufanya shughuli kwenye faili. Mifano ya mifumo ya faili ni FAT (FAT - Jedwali la Ugawaji wa Faili), NTFS, UDF (hutumika kwenye CD).

Kuna matoleo matatu kuu ya FAT: FAT12, FAT16 na FAT32. Wanatofautiana katika kina kidogo cha rekodi katika muundo wa disk, i.e. idadi ya biti zilizotengwa kuhifadhi nambari ya nguzo. FAT12 hutumiwa hasa kwa diski za floppy (hadi 4 KB), FAT16 - kwa disks ndogo za uwezo, FAT32 - kwa anatoa za juu za FLASH (hadi 32 GB).

Wacha tuangalie muundo wa mfumo wa faili kwa kutumia FAT32 kama mfano.

muundo wa faili FAT32

Vifaa vya kumbukumbu ya nje katika mfumo wa FAT32 vina anwani ya kuzuia badala ya kushughulikia kwa kawaida. Taarifa imeandikwa kwa kifaa cha kumbukumbu ya nje katika vitalu au sekta.

Sekta ni sehemu ya chini kabisa inayoweza kushughulikiwa ya uhifadhi wa taarifa kwenye vifaa vya hifadhi ya nje. Kwa kawaida, ukubwa wa sekta ni fasta kwa 512 bytes. Ili kuongeza nafasi ya anwani ya vifaa vya kumbukumbu ya nje, sekta zinajumuishwa katika vikundi vinavyoitwa makundi.

Nguzo ni muungano wa sekta kadhaa, ambayo inaweza kuchukuliwa kama kitengo huru na mali fulani. Mali kuu ya nguzo ni saizi yake, iliyopimwa kwa idadi ya sekta au idadi ya ka.

Mfumo wa faili wa FAT32 una muundo ufuatao.

Vikundi vinavyotumiwa kuandika faili vimehesabiwa kuanzia 2. Kama sheria, kikundi cha 2 kinatumiwa na saraka ya mizizi, na kuanzia kikundi Nambari 3 safu ya data huhifadhiwa. Sekta zinazotumiwa kuhifadhi habari juu ya saraka ya mizizi hazijaunganishwa.
Saizi ya chini ya faili inayohitajika kwenye diski inalingana na nguzo 1.

Sekta ya boot huanza na habari ifuatayo:

  • EB 58 90 - kuruka bila masharti na saini;
  • 4D 53 44 4F 53 35 2E 30 MSDOS5.0;
  • 00 02 - idadi ya ka katika sekta (kawaida 512);
  • 1 byte - idadi ya sekta katika nguzo;
  • 2 byte - idadi ya sekta za hifadhi.

Kwa kuongeza, sekta ya boot ina taarifa muhimu zifuatazo:

  • 0x10 (1 byte) - idadi ya meza za FAT (kawaida 2);
  • 0x20 (4 byte) - idadi ya sekta kwenye diski;
  • 0x2С (4 byte) - nambari ya nguzo ya saraka ya mizizi;
  • 0x47 (bytes 11) - lebo ya kiasi;
  • 0x1FE (2 byte) - saini ya sekta ya boot (55 AA).

Sekta ya habari ya mfumo wa faili ina:

  • 0x00 (4 byte) - saini (52 52 61 41);
  • 0x1E4 (4 byte) - saini (72 72 41 61);
  • 0x1E8 (4 byte) - idadi ya makundi ya bure, -1 ikiwa haijulikani;
  • 0x1EC (4 byte) - idadi ya nguzo ya mwisho iliyorekodiwa;
  • 0x1FE (2 byte) - saini (55 AA).

Jedwali la FAT lina habari kuhusu hali ya kila nguzo kwenye diski. Biti 2 za chini za duka la meza la FAT F8 FF FF 0F FF FF FF FF (ambayo inalingana na hali ya makundi 0 na 1, ambayo haipo kimwili). Ifuatayo, hali ya kila nguzo ina nambari ya nguzo ambayo faili ya sasa inaendelea au habari ifuatayo:

  • 00 00 00 00 - nguzo ni bure;
  • FF FF FF 0F - mwisho wa faili ya sasa.
  • 8 byte - jina la faili;
  • 3 byte - ugani wa faili;

Saraka ya mizizi ina seti ya rekodi za habari 32-bit kuhusu kila faili, iliyo na habari ifuatayo:

Wakati wa kufanya kazi na majina ya faili ndefu (ikiwa ni pamoja na majina ya Kirusi), jina la faili limewekwa kwa kutumia mfumo wa encoding UTF-16. Katika kesi hii, byte 2 zimetengwa kwa kusimba kila herufi. Katika kesi hii, jina la faili limeandikwa katika muundo ufuatao:

  • 1 mlolongo baiti;
  • Biti 10 zina herufi 5 za chini za jina la faili;
  • 1 byte sifa;
  • 1 byte imehifadhiwa;
  • 1 byte - hundi ya jina la DOS;
  • Biti 12 zina herufi 3 za chini za jina la faili;
  • 2 byte - idadi ya nguzo ya kwanza;
  • herufi zilizobaki za jina refu.

Kufanya kazi na faili katika lugha ya C

Kwa mtayarishaji programu, faili iliyofunguliwa inawakilishwa kama mlolongo wa data inayosomwa au kuandikwa. Wakati faili inafunguliwa, inahusishwa na I/O mkondo. Taarifa ya pato imeandikwa kwa mkondo, taarifa ya pembejeo inasomwa kutoka kwa mkondo.

Mtiririko unapofunguliwa kwa I/O, unahusishwa na muundo wa kawaida wa FILE, ambao umefafanuliwa katika stdio.h. Muundo wa FILE una habari muhimu kuhusu faili.

Kufungua faili hufanywa kwa kutumia fopen() kazi, ambayo inarudisha pointer kwenye muundo wa FILE ambao unaweza kutumika kwa shughuli zinazofuata kwenye faili.

FILE *fopen(jina, aina);


jina - jina la faili ya kufungua (pamoja na njia),
type ni kielekezi kwa safu ya wahusika ambayo inafafanua jinsi faili inavyopatikana:
  • "r" - fungua faili kwa kusoma (faili lazima iwepo);
  • "w" - fungua faili tupu kwa kuandika; ikiwa faili iko, yaliyomo yake yanapotea;
  • "a" - fungua faili kwa kuandika hadi mwisho (kwa kuongezea); faili imeundwa ikiwa haipo;
  • "r +" - fungua faili kwa kusoma na kuandika (faili lazima iwepo);
  • "w+" - fungua faili tupu kwa kusoma na kuandika; ikiwa faili iko, yaliyomo yake yanapotea;
  • "a+" - fungua faili kwa kusoma na kuongezea; ikiwa faili haipo, basi imeundwa.

Thamani ya kurudi ni kiashirio kwa mkondo wazi. Ikiwa hitilafu itapatikana, NULL itarejeshwa.

Fclose() chaguo za kukokotoa hufunga mtiririko au mitiririko inayohusishwa na faili zilizofunguliwa kwa kutumia fopen() chaguo la kukokotoa. Mtiririko utakaofungwa unaamuliwa na hoja ya fclose() chaguo la kukokotoa.

Thamani ya kurejesha: thamani 0 ikiwa mtiririko ulifungwa kwa mafanikio; EOF mara kwa mara ikiwa hitilafu ilitokea.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#pamoja na
int kuu() (
FILE *fp;
char name = "my.txt" ;
ikiwa ((fp = fopen(jina, "r")) == NULL )
{
printf( "Imeshindwa kufungua faili");
getchar();
kurudi 0;
}
// alifanikiwa kufungua faili
... // vitendo vinavyohitajika kwenye data
fclose (fp);
getchar();
kurudi 0;
}

Kusoma herufi kutoka kwa faili:

char fgetc(mkondo);


Hoja ya kukokotoa ni kielekezi kwa mtiririko wa aina FILE. Chaguo la kukokotoa linarudisha msimbo wa herufi iliyosomwa. Ikiwa mwisho wa faili umefikiwa au hitilafu hutokea, EOF ya mara kwa mara inarudi.

Kuandika ishara kwa faili:

fputc(char, mkondo);

Hoja za chaguo za kukokotoa ni herufi na kielekezi kwa mtiririko wa aina FILE. Chaguo la kukokotoa linarudisha msimbo wa herufi iliyosomwa.

Vipengele vya fscanf() na fprintf() vinafanana na vitendaji vya scanf() na printf(), lakini hufanya kazi na faili za data, na kuwa na kielekezi cha faili kama hoja yao ya kwanza.

fscanf(mkondo, "InputFormat", hoja);

Utaratibu wa I/O uliotengenezwa na , hauambatani na mtindo unaokubalika kwa ujumla wa upangaji unaolenga kitu leo, kwa kuongezea, hutumia sana utendakazi wa vielelezo ambao unachukuliwa kuwa si salama katika mazingira ya kisasa ya utekelezaji wa nambari salama. Njia mbadala wakati wa kutengeneza programu-tumizi ni utaratibu wa madarasa ya kawaida ya I/O yanayotolewa na kiwango cha lugha cha C++.

Kufungua faili

Madarasa yanayotumika sana ni ifstream kwa kusoma, ofstream kwa maandishi, na fstream kwa kurekebisha faili.

Madarasa yote ya I/O yaliyounganishwa yanatokana kwa njia isiyo ya moja kwa moja kutoka kwa ios ya kawaida, na kurithi kikamilifu utendakazi wake. Kwa hivyo, hali ya kufungua faili imeainishwa na mshiriki wa data wa aina ya uandikishaji ya open_mode, ambayo inafafanuliwa kama ifuatavyo:

Enum open_mode ( programu, binary, ndani, nje, trunc, alikula );

Chini ni thamani zinazowezekana za bendera na madhumuni yao.

Kwa mfano, ili kufungua faili inayoitwa test.txt ili kusoma data katika mfumo wa jozi, ungeandika:

ifstream faili; file.open("test.txt", ios::in | ios::binary);

Kiendeshaji cha mantiki AU (|) hukuruhusu kuunda modi na mchanganyiko wowote wa bendera. Kwa hivyo, ili wakati wa kufungua faili kwa kuingia, usiandike kwa bahati mbaya faili iliyopo na jina moja, lazima utumie fomu ifuatayo:

faili ya mkondo; file.open("test.txt", ios::out | ios::app);

Inachukuliwa kuwa faili ya kichwa inayolingana imejumuishwa katika mradi:

#pamoja na

Kuangalia ikiwa faili ilifunguliwa kwa mafanikio, unaweza kutumia ujenzi

Ikiwa (!faili) (//Kushughulikia kosa la kufungua faili)

Waendeshaji wa kuingizwa na uchimbaji

Imebatilishwa katika madarasa ya kushughulikia faili mwendeshaji wa ujumuishaji (<<) записывает данные в файловый поток. Как только вы открыли файл для записи, можно записывать в него текстовую строку целиком:

Faili<< "Это строка текста";

Unaweza pia kuandika kamba ya maandishi katika sehemu:

Faili<< "Это " << "строка " << "текста";

Taarifa ya endl inamaliza pembejeo ya mstari na kurudi kwa gari:

Faili<< "Это строка текста" << endl;

Kutumia opereta ni pamoja na, ni rahisi kuandika maadili ya anuwai au vitu vya safu kwa faili:

faili ya mkondo ("Temp.txt"); char buff = "Safu ya maandishi ina vigezo"; int vx = 100; kuelea pi = 3.14159; faili<< buff << endl << vx << endl << pi << endl;

Kama matokeo ya kutekeleza msimbo, mistari mitatu ya faili ya maandishi ya Temp.txt huundwa:

Safu ya maandishi ina vigeu 100 3.14159

Kumbuka kuwa nambari zimeandikwa kwa faili kama mifuatano ya maandishi badala ya maadili ya binary.

Opereta wa kurejesha(>>) hutoa athari kinyume. Inaweza kuonekana kuwa ili kutoa herufi kutoka kwa faili ya Temp.txt iliyoandikwa mapema, ungeandika msimbo kama ifuatayo:

Ifstream faili("Temp.txt"); char buff; int vx; kuelea pi; faili >> buff >> vx >> pi;

Walakini, mwendeshaji wa uchimbaji atasimama kwenye kikomo cha kwanza ambacho hukutana nacho (nafasi, kichupo, au laini mpya). Kwa hivyo, wakati wa kuchanganua sentensi "Safu ya maandishi ina vigeu," neno "Nakala" pekee ndilo litakaloandikwa kwa safu ya buff, nafasi hupuuzwa, na neno "safu" litakuwa thamani ya tofauti nzima ya vx, na msimbo. utekelezaji "utaenda mrama" kwa ukiukaji usioepukika wa muundo wa data. Ifuatayo, tunapojadili darasa la ifstream, tutaonyesha jinsi ya kupanga vizuri usomaji wa faili kutoka kwa mfano uliopita.

ifstream darasa: kusoma faili

Kama jina linavyopendekeza, darasa la ifstream limeundwa kuingiza utiririshaji wa faili. Mbinu kuu za darasa zimeorodheshwa hapa chini. Nyingi zao hurithiwa kutoka kwa darasa la istream na zimejaa kupita kiasi ili kupanua utendakazi wa mzazi. Kwa mfano, kazi ya kupata, kulingana na parameter ya simu, haiwezi kusoma tu tabia moja, lakini pia block ya wahusika.

Sasa ni wazi jinsi mfano uliopita unahitaji kurekebishwa ili kutumia opereta wa uchimbaji wa data kutoa matokeo yanayotarajiwa:

Ifstream faili("Temp.txt"); char buff; int vx; kuelea pi; file.getline(buff, sizeof(buff)); faili >> vx >> pi:

Njia ya kupata laini itasoma safu ya kwanza ya faili hadi mwisho, na mendeshaji >> atatoa maadili kwa anuwai.

Mfano ufuatao unaonyesha kuongeza data kwenye faili ya maandishi na kisha kusoma faili nzima. Kitanzi cha wakati(1) kinatumika badala ya while(!file2.eof()) kwa sababu zilizojadiliwa katika .

#pamoja na #pamoja na kutumia nafasi ya majina std; int main() ( ofstream file; file.open("test.txt",ios::out|ios::app); ikiwa (!faili) ( cout<< "File error - can"t open to write data!"; cin.sync(); cin.get(); return 1; } for (int i=0; i<10; i++) file << i << endl; file.close(); ifstream file2; file2.open("test.txt", ios::in); if (!file2) { cout << "File error - can"t open to read data!"; cin.sync(); cin.get(); return 2; } int a,k=0; while (1) { file2 >> a; ikiwa (file2.eof()) itavunjika; koti<< a << " "; k++; } cout << endl << "K=" << k << endl; file2.close(); cin.sync(); cin.get(); return 0; }

Mfano ufuatao unaonyesha kitanzi kinachosoma mistari kutoka kwenye faili ya test.txt na kuzionyesha kwenye kiweko.

#pamoja na #pamoja na kutumia nafasi ya majina std; int main() ( ifstream faili; // tengeneza faili ya kitu cha kutiririsha.open("test.txt"); // fungua faili ili isomwe ikiwa (!faili) itarudisha 1;// rudisha kwenye ufunguzi wa makosa char str; // bafa ya laini tuli // Soma na uonyeshe mistari katika kitanzi hadi eof wakati (!file.getline(str, sizeof(str))).eof()) cout<< str << endl; // вывод прочитанной строки на экран cin.sync(); cin.get(); return 0; }

Nambari hii chini ya Windows OS pia inategemea uwepo wa herufi mpya kwenye safu ya mwisho ya faili; itakuwa ya kuaminika zaidi kufanya hivi:

Wakati (1) (ikiwa (file.eof()) inavunjika; file.getline(str, sizeof(str)); cout<< str << endl; }

Simu za wazi kwa njia zilizo wazi na za karibu hazihitajiki. Kwa kweli, kumwita mjenzi kwa hoja hukuruhusu kufungua faili mara moja, wakati wa kuunda kitu cha faili kilichowekwa nyuzi:

Ifstream faili("test.txt");

Badala ya njia ya karibu, unaweza kutumia operator wa kufuta, ambayo itaita moja kwa moja uharibifu wa kitu cha faili na kufunga faili. Nambari ya kitanzi wakati inahakikisha ukaguzi sahihi wa mwisho wa faili.

ofstream class: kuandika faili

Darasa la ofstream limeundwa kutoa data kutoka kwa mtiririko wa faili. Ifuatayo inaorodhesha njia kuu za darasa hili.

Opereta ya ujumuishaji iliyoelezewa hapo awali ni rahisi kwa kupanga maandishi kwa faili ya maandishi:

faili ya mkondo ("temp.txt"); ikiwa (!faili) itarudi; kwa (int i=1; i<=3; i++) file << "Строка " << i << endl; file.close();

Faili za binary

Kimsingi, data ya binary inachukuliwa kama data ya maandishi. Tofauti ni kwamba ikiwa data ya binary imeandikwa katika muundo maalum wa mantiki, basi lazima isomwe kutoka kwa faili hadi kutofautiana kwa aina sawa ya muundo.

Kigezo cha kwanza cha njia za kuandika na kusoma (anwani ya kizuizi cha kuandika / kusoma) lazima iwe ya aina ya pointer char * , kwa hiyo ni muhimu kufanya uongofu wa wazi wa aina ya anwani ya muundo wa * batili. Kigezo cha pili kinabainisha kuwa vizuizi vya binary vya faili vina ukubwa wa kawaida wa baiti bila kujali urefu halisi wa rekodi. Programu ifuatayo inatoa mfano wa kuunda na kuonyesha data katika daftari rahisi. Maingizo ya faili basi yanasomwa kwa mpangilio na kuonyeshwa kwenye koni.

#pamoja na #pamoja na #pamoja na kutumia nafasi ya majina std; muundo Vidokezo ( // muundo wa data ya daftari char Jina; // jina kamili char Simu; // simu int Umri; // umri); int main() ( setlocale(LC_ALL, "Russian"); Notes Note1= ("The Terrible Ioann Vasilyevich", "haijasakinishwa", 60 ); Notes Note2= ("Godunov Boris Fedorovich", "095-111-2233" , 30 ); Notes Note3= ( "Romanov Petr Mikhailovich ", "812-333-2211 ", 20 ); ofstream ofile("Notebook.dat", ios::binary); ofile.write((char*)&Note1, sizeof (Vidokezo)); // block ya 1 ofile.andika((char*)&Note2, sizeof(Notes)); // 2nd block ofile.andika((char*)&Note3, sizeof(Vidokezo)); // block ya 3 ofile.close(); // funga faili iliyorekodiwa ifstream ifile("Notebook.dat", ios::binary); Notes Note; // muundo tofauti char str;// bafa ya kamba tuli // Soma na uonyeshe mistari katika a kitanzi hadi eof wakati (!ifile.read((char*)&Note, sizeof(Notes)).eof()) ( sprintf(str, "%s\tPhone: %s\tAge: %d" , Note.Name, Kumbuka.Simu, Kumbuka.Umri); cout<< str << endl; } ifile.close(); // закрыть прочитанный файл cin.sync(); cin.get(); return 0; }

Kama matokeo ya kutekeleza nambari hii, faili ya binary Notebook.dat huundwa kutoka kwa vizuizi vitatu vya baiti 80 kila moja (ikizingatiwa kuwa herufi ni baiti moja). Kwa kawaida, unaweza kutumia njia nyingine za kuunganisha na kufanya shughuli zozote kwenye nyanja za muundo maalum wa data.

fstream class: ufikiaji wa faili bila mpangilio

Wacha tuchukue kuwa tunayo maingizo 100 kwenye daftari yetu, na tunataka kuhesabu ya 50. Bila shaka, unaweza kuandaa kitanzi na kusoma rekodi zote kutoka kwa kwanza hadi kwa kupewa. Ni wazi suluhisho linalolengwa zaidi ni kuweka pointer ya nafasi ya faili moja kwa moja hadi 50 na usome kutoka kwayo:

Ifstream ifile("Notebook.dat", ios::binary); int pos = 49 * sizeof(Vidokezo); ifile.seekg(pos); // tafuta ingizo la Vidokezo vya 50; // Vidokezo - muundo wa "rekodi" ulioelezwa hapo juu ifile.read((char*)&Note, sizeof(Vidokezo));

Shughuli hizo za utafutaji zinafaa ikiwa faili ina rekodi za ukubwa unaojulikana na wa mara kwa mara. Ili kuchukua nafasi ya yaliyomo kwenye rekodi ya kiholela, unahitaji kufungua mtiririko wa matokeo katika hali ya urekebishaji:

Ofstream ofile ("Notebook.dat", ios::binary | ios::ate); int pos = 49 * sizeof(Vidokezo); ofile seekp(pos); // tafuta maelezo ya 50 Notes Note50 = ("Yeltsin Boris Nikolaevich", "095-222-3322", 64); ofile.write((char*)&Note, sizeof(Vidokezo)); // mbadala

Ikiwa hutabainisha bendera ya ios::ate (au ios::app), basi unapofungua faili ya binary ya Notebook.dat, maudhui yake ya awali yatafutwa!

Hatimaye, inawezekana kufungua faili wakati huo huo kwa kusoma / kuandika, kwa kutumia mbinu zilizorithiwa na darasa la utiririshaji wa fstream kutoka kwa watangulizi wake. Kwa kuwa darasa la fstream linatokana na istream na ostream (wazazi wa ifstream na ofstream mtawalia), mbinu zote zilizotajwa hapo awali zinapatikana kwenye programu.

Mfano ufuatao unaonyesha mpangilio upya wa maingizo ya kwanza na ya tatu katika faili ya Notebook.dat.

#pamoja na #pamoja na #pamoja na kutumia nafasi ya majina std; struct Notes (Char Jina; char Simu; int Age; ); int main() ( setlocale(LC_ALL, "Russian"); Notes Note1, Note3; // Fungua faili kwa kusoma/kuandika kwa wakati mmoja fstream file("Notebook.dat", ios::binary | ios::in | ios: : out); file.seekg(2 * sizeof(Vidokezo)); // pata na usome Note3 file.soma((char*)&Note3, sizeof(Notes)); file.seekg(0); // pata na usome Note1 file.read((char*)&Note1, sizeof(Vidokezo)); file.seekg(0); // Note1<== Note3 file.write((char*)&Note3, sizeof(Notes)); file.seekg(2 * sizeof(Notes)); // Note3 <== Note1 file.write((char*)&Note1, sizeof(Notes)); char str; // Считывать и отображать записи в цикле, пока не eof file.seekg(0); // вернуться к началу файла while (!file.read((char*)&Note1, sizeof(Notes)).eof()) { sprintf(str, "%s\tТел: %s\tВозраст: %d", Note1.Name, Note1.Phone, Note1.Age); cout << str << endl; } file.close(); cin.sync(); cin.get(); return 0; }

Katika kijenzi cha kitu cha faili, lazima ubainishe bendera za ios::in na ios::nje, kuruhusu shughuli za kusoma na kuandika kwa wakati mmoja. Kama matokeo ya kutekeleza msimbo huu, maingizo ya kwanza na ya tatu katika faili ya binary ya Notebook.dat yatabadilishwa.

Kuna mifano ya ziada juu ya mada.