Kako postaviti pametne telefone i računala. Informativni portal
  • Dom
  • Željezo
  • Programiranje rada s tekstualnim datotekama. Rad s tekstualnim datotekama

Programiranje rada s tekstualnim datotekama. Rad s tekstualnim datotekama

Za programera otvorena datoteka predstavljen kao niz podataka koji se čitaju ili pišu. Kada se datoteka otvori, ona je povezana s I/O protok . Izlazne informacije se zapisuju u stream, ulazne informacije se čitaju iz toka.

Kada se tok otvori za I/O, on je povezan sa standardnom strukturom tipa FILE, koja je definirana u stdio.h. Struktura FILE sadrži potrebne informacije o datoteci.

Otvaranje datoteke vrši se pomoću funkcije fopen() koja vraća pokazivač na strukturu tipa FILE, koja se može koristiti za naknadne operacije s datotekom.

DATOTEKA *fopen(naziv, vrsta);

naziv je naziv datoteke koja se otvara (uključujući putanju),
type - pokazivač na niz znakova koji definiraju kako se pristupa datoteci:

· "r" - otvorite datoteku za čitanje (datoteka mora postojati);

"w" - otvoren prazna datoteka za snimanje; ako datoteka postoji, njen sadržaj se gubi;

· "a" - otvorena datoteka za pisanje do kraja (za dodavanje); datoteka se kreira ako ne postoji;

· "r+" - otvorite datoteku za čitanje i pisanje (datoteka mora postojati);

· "w+" - otvori praznu datoteku za čitanje i pisanje; ako datoteka postoji, njen sadržaj se gubi;

· "a+" - otvorite datoteku za čitanje i dodavanje, ako datoteka ne postoji, kreira se.

Povratna vrijednost je pokazivač na otvoreni tok. Ako se pronađe greška, vraća se NULL.

Funkcija fclose() zatvara tok ili streamove povezane s datotekama otvorenim pomoću fopen(). Tok koji treba zatvoriti određen je argumentom funkcije fclose().

Povratna vrijednost: vrijednost 0 ako je stream uspješno zatvoren; EOF konstanta ako je došlo do greške.

#uključiti
int main()

char name="my.txt";

if(fp = fopen(ime, "r")!=NULL)

// je li bilo moguće otvoriti datoteku?
... // potrebne radnje na podacima

else printf("Ne mogu otvoriti datoteku");

Čitanje znaka iz datoteke:

char fgetc(stream);

Argument funkcije je pokazivač na tok tipa FILE. Funkcija vraća kod pročitanog znaka. Ako se dostigne kraj datoteke ili dođe do greške, vraća se EOF konstanta.
Upisivanje znaka u datoteku:

fputc(znak, tok);

Argumenti funkcije su znak i pokazivač na tok tipa FILE. Funkcija vraća kod pročitanog znaka.

Funkcije fscanf() i fprintf() su slične scanf funkcije() i printf(), ali rade na datotekama s podacima i imaju pokazivač datoteke kao prvi argument.

fscanf(stream, "Format unosa", argumenti);
fprintf(stream, "Izlazni format", argumenti);

Funkcije fgets() i fputs() služe za niz I/O, analogne su funkcijama gets() i puts() za rad s datotekama.

fgets(pokazivač na niz, broj znakova, tok);

Znakovi se čitaju iz toka dok se znak ne pročita nova linija"\n", koji je uključen u niz, ili dok kraj toka ne bude EOF ili je pročitan maksimalni broj znakova. Rezultat se stavlja u string pokazivač i završava null znakom "\0". Funkcija vraća adresu niza.

fputs (pokazivač na niz, tok);

Kopira niz u stream s trenutne pozicije. Završni nulti znak se ne kopira.
Primjer Unesite broj i spremite ga u datoteku s1.txt. Pročitajte broj iz datoteke s1.txt, povećajte ga za 3 i spremite u datoteku s2.txt.

Funkcija fopen() otvara stream za upotrebu, povezuje datoteku s danim streamom, a zatim vraća pokazivač FILE na dati konac. Najčešće se datoteka vidi kao disk datoteka. Funkcija fopen() ima sljedeći prototip:

FILE *fopen(const char *naziv datoteke, const char *način);

Gdje način pokazuje na niz koji sadrži željeni način otvaranja datoteke. Važeće vrijednosti za način rada u Borland C++ prikazane su u tablici. naziv datoteke mora biti niz znakova koji predstavlja valjani naziv datoteke operacijski sustav, i može sadržavati put.

Funkcija fopen() vraća pokazivač bazni tip DATOTEKA. Ovaj pokazivač identificira datoteku i koristi ga većina funkcija. sustav datoteka. Nikada ga ne biste trebali mijenjati sami. Funkcija vraća null pokazivač ako se datoteka ne može otvoriti.

Kao što tablica pokazuje, datoteka se može otvoriti u tekstualnom ili binarnom načinu. U tekstualnom načinu, kada tipkate, redoslijed vraćanja i povlačenja reda preveden je u znak novog retka. U izlazu je točno suprotno: znak novog retka se prevodi u povratni redak i prijelaz retka. V binarne datoteke nema takvog prijevoda. Kada ni t ni b nisu navedeni u argumentu načina, tekstualni/binarni status datoteke određen je vrijednošću globalne varijable _fmode definirane u Borland C++. Prema zadanim postavkama, fmode je postavljen na O_TEXT, odnosno postavljen je tekstualni način. Postavljanje _fmode na O_BINARY otvorit će datoteke u binarnom načinu. (Ove makronaredbe definirane su u fcntl.h.) Naravno, korištenje eksplicitnog t ili b eliminira učinke varijable _fmode. Osim toga, _fmode je specifičan samo za Borland proizvode. Nije definiran u ANSI C I/O sustavu.

Ako trebate otvoriti datoteku pod nazivom test za pisanje, tada biste trebali napisati:

Fp = fopen("test", "w") ;

Gdje je fp varijabla tipa FILE *. Međutim, obično ćete vidjeti sljedeće:

If((fp = fopen("test", "w"))==NULL) (
puts("Ne mogu otvoriti datoteku.");
izlaz (1);
}

Ova metoda omogućuje vam otkrivanje pogrešaka prilikom otvaranja datoteke, na primjer, prisutnost zaštite od pisanja ili nedostatak slobodan prostor na disku.

Ako se fopen() koristi za otvaranje datoteke za pisanje, tada bilo koja već postojeća datoteka s dato ime bit će obrisan. Ako datoteka s navedenim imenom ne postoji, bit će stvorena.

Ako trebate dodati informacije na kraj datoteke, trebali biste koristiti način (dodavanje). Ako datoteka ne postoji, bit će kreirana.

Otvaranje datoteke za čitanje zahtijeva prisutnost datoteke. Ako datoteka ne postoji, bit će vraćena pogreška. Ako je datoteka otvorena za operaciju čitanja/pisanja, onda se ne briše ako postoji, a ako datoteka ne postoji, onda se kreira.

Stol: Valjane vrijednosti načina rada

Značenje

Otvara datoteku za čitanje. (Otvara se kao tekstualna datoteka prema zadanim postavkama.)

Stvara datoteku za pisanje. (Otvara se kao tekstualna datoteka prema zadanim postavkama.)

Dodaje se datoteci. (Otvara se kao tekstualna datoteka prema zadanim postavkama.)

Otvara binarnu datoteku za čitanje.

Otvara binarnu datoteku za pisanje.

Dodaje se binarnoj datoteci.

Otvara datoteku za čitanje/pisanje. (Otvara se kao tekstualna datoteka prema zadanim postavkama.)

Stvara datoteku za čitanje/pisanje. (Otvara se kao tekstualna datoteka prema zadanim postavkama.)

Prilaže ili stvara datoteku za čitanje/pisanje. (Otvara se kao tekstualna datoteka prema zadanim postavkama.)

Otvara binarnu datoteku za čitanje/pisanje.

Stvara binarnu datoteku za čitanje/pisanje.

Prilaže ili stvara binarnu datoteku za čitanje/pisanje.

Stvara tekstualnu datoteku za pisanje.

Dodaje se tekstualnoj datoteci.

Otvara tekstualnu datoteku za čitanje.

Stvara tekstualnu datoteku za čitanje/pisanje.

Otvara ili stvara tekstualnu datoteku za čitanje/pisanje.

Rad s tekstualnim datotekama u C++.

Postoje dvije glavne vrste datoteka: tekstualne i binarne. Datoteke omogućuju korisniku čitanje velikih količina podataka izravno s diska bez da ih upisuje s tipkovnice.

    Tekst nazivaju se datoteke koje se sastoje od bilo kojeg karaktera. Organizirani su u retke, od kojih svaki završava znakom za kraj reda. Kraj same datoteke označen je simbolom "kraj datoteke". Prilikom pisanja informacija u tekstualnu datoteku, koja se može vidjeti pomoću bilo kojeg uređivača teksta, svi podaci se pretvaraju u vrstu znakova i pohranjuju u obliku znakova.

    V binarni U datotekama se informacije čitaju i zapisuju u obliku blokova određene veličine, u koje se mogu pohraniti podaci bilo koje vrste i strukture.

Za rad s datotekama, posebnim vrste podataka, nazvao potoci. Teći ifstream koristi se za rad s datotekama u načinu čitanja, i izvan struje u načinu snimanja. Stream se koristi za rad s datotekama u načinu pisanja i čitanja. fstream.

U C++ programima, pri radu s tekstualnim datotekama, potrebno je uključiti iostream i fstream knjižnice.

Da bi Zapiši podatke u tekstualnu datoteku, morate:

    opisati varijablu tipa toka.

    izlazne informacije u datoteku.

    svakako zatvorite datoteku.

Za čitanja podatke iz tekstualne datoteke, morate:

    opisati varijablu tipa ifstream.

    otvorite datoteku pomoću funkcije otvaranja.

    zatvorite datoteku.

Snimanje informacije u tekstualnu datoteku

    Kao što je ranije spomenuto, kako bi počeli raditi s tekstualnu datoteku, potrebno je opisati varijabla tipa izvan struje. Na primjer, ovako:

    Stvorit će se varijabla F za upisivanje informacija u datoteku.

    Sljedeći korak je otvaranje datoteke za pisanje. V opći slučaj Operator otvaranja streama izgledat će ovako:

F. open("datoteka", način rada);

Ovdje je F varijabla deklarirana kao offstream,

datoteka- puno ime datoteku na disku

mode - način rada s otvorenom datotekom.

Imajte na umu da prilikom navođenja punog naziva datoteke morate staviti dvostruku kosu crtu. Na primjer, puni naziv datoteke noobs.txt koja se nalazi u mapi igre na disku D: morat će biti napisan ovako:

D:\\game\\noobs.txt.

Datoteka se može otvoriti na jedan od sljedećih načina:

ios::in - otvori datoteku u načinu čitanja podataka, ovaj način je zadani način za ifstream streamove;

ios::out - otvori datoteku u načinu pisanja podataka (u ovom slučaju, informacije o postojećoj datoteci su uništene), ovaj način je zadani način za streamove;

ios::app - otvorite datoteku u načinu upisivanja podataka do kraja datoteke;

ios::ate - premjestiti na kraj već otvorene datoteke;

ios::trunc - obrišite datoteku, isto se događa u ios::out modu;

ios::nocreate - ne otvaraj datoteku ako ne postoji;

ios::noreplace - Ne otvaraj postojeću datoteku.

Parametar načina može biti odsutan, u tom slučaju se datoteka otvara u zadanom načinu za ovaj stream.

Nakon uspješnog otvaranja datoteke (u bilo kojem načinu), F varijabla će pohraniti true, u suprotnom false. Time će se provjeriti ispravnost operacije otvaranja datoteke.

Možete otvoriti datoteku (uzmimo D:\\game\\noobs.txt kao primjer) u načinu pisanja koristeći jedan od sljedećih metoda:

// prvi put

izvan struje F;

F.open("D:\\game\\noobs.txt", ios::out);

//drugi način, ios::out način je zadani način rada

// za tećiizvan struje

izvan struje F;

// treći način kombinira opis varijable i vrstu toka

//i otvorite datoteku u jednoj izjavi

ofstream F("D:\\game\\noobs.txt", ios::out);

Nakon otvaranja datoteke u načinu pisanja, kreirat će se prazna datoteka u koju se mogu upisivati ​​informacije.

Ako želite otvoriti postojeću datoteku u načinu prije pisanja, upotrijebite ios::app kao način rada.

Nakon otvaranja datoteke u načinu pisanja, u nju možete pisati na isti način kao na ekranu, samo umjesto standardnog izlaznog uređajacoutmorate navesti naziv otvorene datoteke.

Na primjer, za pisanje varijable a u tok F, izlazni izraz bi bio:

Za sekvencijalni ispis varijabli b, c, d u tok G, izlazni izraz postaje:

G<

Stream se zatvara pomoću operatora:

PRIMJER:

Napravite tekstualnu datoteku D:\\game\\noobs.txt i u nju upišite n realnih brojeva.

#include "stdafx.h"

#uključiti

#uključiti

#uključiti

korištenje imenskog prostora std;

int main()

setlocale(LC_ALL, "RUS");

int i, n;

dvostruko a;

//opisuje tok za pisanje podataka u datoteku

izvan struje f;

//otvori datoteku u načinu pisanja,

//načinios:: vaninstaliran prema zadanim postavkama

f.open("D:\\game\\noobs.txt", ios::out);

//unesite broj realnih brojeva

cout<<" n="; cin>> n;

//petlja za unos realnih brojeva

//i zapisivanje u datoteku

za (i=0; i

cout<<"a=";

//unos broja

cin>>a;

f<

//zatvaranje streama

f.close();

sustav("pauza");

vrati 0;

_______________________________________________________________

Za čitanje informacija iz tekstualne datoteke potrebno je deklarirati varijablu tipa ifstream. Nakon toga morate otvoriti datoteku za čitanje pomoću operatora otvorena. Ako se varijabla zove F, tada će prve dvije izjave biti sljedeće:

F.open("D:\\game\\noobs.txt", ios::in);

Nakon otvaranja datoteke u načinu čitanja, možete čitati informacije iz nje na isti način kao i s tipkovnice, samo umjestocinnavedite naziv toka iz kojeg će se podaci čitati.

Na primjer, za čitanje iz toka F u varijablu a, ulazni izraz bi izgledao ovako:

Dva broja u uređivaču teksta smatraju se odvojenima ako između njih postoji barem jedan od znakova: razmak, tabulator, znak na kraju retka. Dobro je ako programer unaprijed zna koliko i koje vrijednosti treba pohraniti u tekstualnu datoteku. Međutim, često je vrsta vrijednosti pohranjenih u datoteci jednostavno poznata, a njihov broj može varirati. Da biste riješili ovaj problem, morate čitati vrijednosti iz datoteke jednu po jednu, a prije svakog čitanja provjeriti je li dosegnut kraj datoteke. Za to postoji funkcija F. eof().

Ovdje je F naziv toka, funkcija vraća booleovu vrijednost: true ili false, ovisno o tome je li dosegnut kraj datoteke. Stoga se petlja za čitanje sadržaja cijele datoteke može napisati ovako:

//organizirati za čitanje vrijednosti iz datoteke, izvršenje

//petlja će se prekinuti kada dođemo do kraja datoteke,

//u ovom slučaju F.eof() će vratiti true

dok (!F.eof())

PRIMJER:

Realni brojevi su pohranjeni u tekstualnoj datoteci D:\\game\\noobs.txt, prikažite ih na ekranu i izračunajte njihov broj.

#include "stdafx.h"

#uključiti

#uključiti

#uključiti

#uključiti

korištenje imenskog prostora std;

int main()

setlocale(LC_ALL, "RUS");

intn=0;

plutati a;

fstream F;

//otvori datoteku u načinu čitanja

F.open("D:\\game\\noobs.txt");

//ako je datoteka ispravno otvorena, onda

//petlja za čitanje vrijednosti iz datoteke; izvođenje petlje će biti prekinuto,

// kada dođemo do kraja datoteke, u tom slučaju F.eof() će vratiti true.

dok (!F.eof())

//čitanje sljedeće vrijednosti iz toka F u varijablu a

F>>a;

//iznesite vrijednost varijable a na ekran

cout<

//povećavamo broj pročitanih brojeva

//zatvaranje streama

f.close();

//unos broja pročitanih brojeva na ekranu

cout<<"n="<

//ako je datoteka neispravno otvorena, onda izlaz

//poruke o nepostojanju takve datoteke

inače cout<<" Файл не существует"<

sustav("pauza");

vrati 0;

C++. Obrada binarnih datoteka

Prilikom pisanja informacija u binarnu datoteku, znakovi i brojevi se zapisuju kao niz bajtova.

Da bi Zapiši podatke u binarnu datoteku, potrebno je:

    deklarirajte varijablu datoteke tipa FAIL * koristeći izraz FILE *filename;. Ovdje naziv datoteke je naziv varijable gdje će se pohraniti pokazivač na datoteku.

    zapišite informacije u datoteku pomoću funkcije fwrite

Da bi razmišljati z podataka iz binarne datoteke, morate:

    opišite varijablu tipa FILE *

    otvorite datoteku s funkcijom fopen

    zatvorite datoteku s funkcijom fclose

Osnovne funkcije potrebne za rad s binarnim datotekama.

Za otkrića datoteka, namijenjena je funkcija fopen.

FILE *fopen(const *naziv datoteke, const char *način)

Ovdje filename je niz koji pohranjuje puni naziv datoteke koja se otvara, mode je niz koji definira način rada s datotekom; moguće su sljedeće vrijednosti:

"rb" - otvoriti binarnu datoteku u načinu čitanja;

"wb" - kreirajte binarnu datoteku za pisanje; ako postoji, njezin se sadržaj briše;

"ab" - stvoriti ili otvoriti binarnu datoteku za dodavanje na kraj datoteke;

"rb+" - otvori postojeću binarnu datoteku u načinu čitanja i pisanja;

"wb+" - otvori binarnu datoteku u načinu čitanja i pisanja, postojeća datoteka se briše;

"ab+" - Otvara se ili kreira binarna datoteka kako bi se ispravile postojeće informacije i dodale nove informacije na kraj datoteke.

Funkcija vraća NULL vrijednost u varijablu datoteke f ako datoteka nije uspješno otvorena. Nakon otvaranja datoteke, dostupan je njezin 0-ti bajt, pokazivač datoteke je 0, čija se vrijednost pomiče za pročitani (upisani) broj bajtova dok se čita ili upisuje. Trenutna vrijednost pokazivača datoteke je broj bajta iz kojeg će se dogoditi operacija čitanja ili pisanja.

Za zatvaranje datoteke, namijenjena je funkcija fclose

int fclose(FILE *naziv datoteke);

Vraća 0 ako je datoteka uspješno zatvorena, NULL u suprotnom.

Funkcija uklanjanja je za uklanjanje datoteke.

int remove(const char *naziv datoteke);

Ova funkcija uklanja datoteku pod nazivom filenema s diska. Datoteka koju treba izbrisati mora biti zatvorena. Funkcija vraća vrijednost različitu od nule ako se datoteka ne može izbrisati.

Za preimenovanje datoteke, funkcija preimenovanja je namijenjena:

int rename(const char *oldfilename, const char *newfilename);

Prvi parametar je stari naziv datoteke, drugi je novi. Vraća 0 nakon uspješnog završetka programa.

Čitanje iz binarne datoteke vrši se pomoću funkcije fread:

fread(void *ptr, veličina, n, FILE *naziv datoteke);

Funkcija fread čita n elemenata veličine veličine iz naziva datoteke u ptr polje. Funkcija vraća broj pročitanih elemenata. Nakon čitanja iz datoteke, njen pokazivač se pomiče za n*veličine bajtova.

Snimanje u binarnu datoteku vrši se pomoću funkcije fwrite:

fwrite(const void *ptr, veličina, n, FILE *naziv datoteke);

Funkcija fwrite zapisuje n elemenata veličine u naziv datoteke iz ptr polja. Funkcija vraća broj napisanih elemenata. Nakon što se informacija upiše u datoteku, pokazivač se pomiče za n*veličine bajtova.

Za kontrola kraja datoteke postoji feof funkcija:

int feof(FILE *naziv datoteke);

Vraća vrijednost različitu od nule ako se dostigne kraj datoteke.

PRIMJER:

Napravite binarnu datoteku D:\\game\\noobs.dat i u nju upišite cijeli broj n i n realnih brojeva.

#include "stdafx.h"

#uključiti

korištenje imenskog prostora std;

int main()

setlocale(LC_ALL, "RUS");

int n, i;

dvostruko a;

// kreirati binarnu datoteku u načinu pisanja

f=fopen("D:\\game\\noobs.dat", "wb");

// ulazni brojeviman

cout<<"n="; cin>>n;

fwrite(&n, sizeof(int), 1, f);

//petlja za unos n realnih brojeva

za (i=0; i

//unesite sljedeći realni broj

cout<<"a=";

cin>>a;

//upisivanje realnog broja u binarnu datoteku

fwrite(&a, sizeof(double), 1, f);

// Zatvoriti datoteka

fclose(f);

sustav("pauza");

vrati 0;

PRIMJER:

Prikaži sadržaj binarne datoteke D:\\game\\noobs.dat stvorene u prethodnom zadatku

#include "stdafx.h"

#uključiti

korištenje imenskog prostora std;

int main()

setlocale(LC_ALL, "RUS");

int n, i;

dvostruko *a;

DATOTEKA *f; //opisati varijablu datoteke

//otvaranje postojeće binarne datoteke u načinu čitanja

//čitaj jedan cijeli broj iz datoteke u varijablu n

//izlaz n na ekran

cout<<"n="<

//dodijeliti memoriju za niz od n brojeva

a=novi dupli[n];

//čitanje n realnih brojeva iz datoteke u niz a

//izlaz niza na ekran

za (i=0; i

cout<

cout<

// Zatvoriti datoteka

fclose(f);

sustav("pauza");

vrati 0;

Binarni- sekvencijalna struktura podataka, nakon otvaranja datoteke, dostupan je prvi bajt pohranjen u njoj. Možete uzastopno pisati ili čitati podatke iz datoteke. Pretpostavimo da trebate izbrojati petnaesti broj, a zatim prvi. Uz serijski pristup, to se može učiniti na sljedeći način:

int n, i;

dvostruko a;

DATOTEKA *f;

f=fopen("D:\\game\\noobs.dat", "rb");

za (i=0; i<15; i++)

fclose(f);

f=fopen("D:\\game\\noobs.dat", "rb");

fread(&a, sizeof(double), 1, f);

fclose(f);

Kao što vidite, čitanje brojeva iz datoteke, a zatim ponovno otvaranje datoteke nije najprikladniji način. Mnogo je prikladnije koristiti funkciju fseek za pomicanje pokazivača datoteke na zadani bajt.

int fseek(FILE *naziv datoteke, dugi int pomak, int porijeklo);

Funkcija postavlja pokazivač na trenutni položaj datoteke F u skladu s vrijednošću ishodišta i pomaka. Parametar pomaka jednak je broju bajtova za koji će se pokazivač datoteke pomaknuti u odnosu na ishodište navedeno parametrom ishodišta. Vrijednost parametra ishodišta mora biti jedna od sljedećih vrijednosti za pomak, definiranih u zaglavlju stdio.h:

SEEK_SET - od početka datoteke;

SEEK_CUR - sa trenutne pozicije;

SEEK_END - s kraja datoteke.

Funkcija vraća nulu ako je operacija uspješna, različitu od nule ako pomak ne uspije.

Funkcija fseek zapravo implementira izravan pristup bilo kojoj vrijednosti u datoteci. Trebate samo znati mjesto (broj bajta) vrijednosti u datoteci. Razmotrite korištenje izravnog pristupa u binarnim datotekama na primjeru rješavanja sljedećeg problema.

PRIMJER

U binarnoj datoteci D:\\game\\noobs.dat stvorenoj ranije, zamijenite najveći i najmanji od stvarnih brojeva.

Algoritam za rješavanje problema sastoji se od sljedećih koraka:

    čitanje realnih vrijednosti iz datoteke u niz a.

    pretražite u nizu a maksimalne (max) i minimalne (min) vrijednosti i njihove brojeve (imax, imin).

    pomicanje pokazivača datoteke na maksimalnu vrijednost i pisanje min.

    pomicanje pokazivača datoteke na minimalnu vrijednost i pisanje max.

U nastavku se nalazi tekst programa za rješavanje problema s komentarima.

#include "stdafx.h"

#uključiti

korištenje imenskog prostora std;

int main()

setlocale(LC_ALL, "RUS");

int n, i, imax, imin;

dvostruko *a, max, min;

DATOTEKA *f;

//otvori datoteku u načinu čitanja/pisanja

f=fopen("D:\\game\\noobs.dat", "rb+");

//čitanje iz datoteke u varijablu n broj

//stvarni brojevi u datoteci

fread(&n, sizeof(int), 1, f);

cout<<"n="<

// dodijeliti memoriju za pohranjivanje realnih brojeva,

//koji će biti pohranjen u nizu a

a=novi dupli[n];

//čitanje iz datoteke u niz i realne brojeve

fread(a, sizeof(double), n, f);

//tražimo maksimalne i minimalne elemente

//u nizu a i njihovim indeksima

za (imax=imin=0, max=min=a, i=1; i

ako (a[i]>max)

max=a[i];

ako (a[i]

min=a[i];

// krećući se pokazivač Do maksimum element

fseek(f, sizeof(int)+imax*sizeof(double), SEEK_SET);

//snimanje min umjesto maksimalnog elementa datoteke

fwrite(&min, sizeof(dvostruko), 1, f);

// krećući se pokazivač Do minimum element

fseek(f, sizeof(int)+imin*sizeof(double), SEEK_SET);

//zabilježite maksimum umjesto minimalnog elementa datoteke

fwrite(&max, sizeof(double), 1, f);

//zatvaranje datoteke

fclose(f);

// slobodna memorija

izbrisati[ ]a;

sustav("pauza");

Radi lakšeg rukovanja, informacije u uređajima za pohranu pohranjuju se u obliku datoteka.

Datoteka je imenovano područje vanjske memorije dodijeljeno za pohranjivanje niza podataka. Podaci sadržani u datotekama su najrazličitije prirode: programi na algoritamskom ili strojnom jeziku; početni podaci za rad programa ili rezultati izvođenja programa; proizvoljni tekstovi; grafike itd.

Direktorij (mapa, imenik) - imenovana zbirka bajtova na mediju za pohranu koji sadrži nazive poddirektorija i datoteka, koji se koriste u datotečnom sustavu za pojednostavljenje organizacije datoteka.

sustav datoteka je funkcionalni dio operacijskog sustava koji pruža operacije nad datotekama. Primjeri datotečnih sustava su FAT (FAT - File Allocation Table, file allocation table), NTFS, UDF (koristi se na CD-ovima).

Postoje tri glavne verzije FAT-a: FAT12, FAT16 i FAT32. Razlikuju se po bitnosti zapisa u strukturi diska, t.j. broj bitova dodijeljenih za pohranjivanje broja klastera. FAT12 se uglavnom koristi za diskete (do 4 KB), FAT16 za male diskove, FAT32 za FLASH pogone velikog kapaciteta (do 32 GB).

Razmotrimo strukturu datotečnog sustava koristeći FAT32 kao primjer.

FAT32 struktura datoteke

Vanjski memorijski uređaji u sustavu FAT32 nisu bajt, već blok adresiranje. Informacije se zapisuju na vanjski memorijski uređaj u blokovima ili sektorima.

Sektor - minimalna adresabilna jedinica za pohranu informacija na vanjskim uređajima za pohranu. Tipično, veličina sektora je fiksna na 512 bajtova. Kako bi se povećao adresni prostor vanjskih memorijskih uređaja, sektori se kombiniraju u grupe koje se nazivaju klasteri.

Klaster je asocijacija više sektora, koji se mogu smatrati samostalnom cjelinom s određenim svojstvima. Glavno svojstvo klastera je njegova veličina, mjerena brojem sektora ili brojem bajtova.

FAT32 datotečni sustav ima sljedeću strukturu.

Klasteri koji se koriste za pisanje datoteka numerirani su počevši od 2. U pravilu, klaster #2 koristi korijenski direktorij, a počevši od klastera #3, pohranjuje se niz podataka. Sektori koji se koriste za pohranu informacija iznad korijenskog direktorija nisu grupirani.
Minimalna veličina datoteke na disku je 1 klaster.

Sektor za pokretanje počinje sa sljedećim informacijama:

  • EB 58 90 - bezuvjetna grana i potpis;
  • 4D 53 44 4F 53 35 2E 30 MSDOS5.0;
  • 00 02 - broj bajtova u sektoru (obično 512);
  • 1 bajt - broj sektora u klasteru;
  • 2 bajta - broj rezervnih sektora.

Osim toga, sektor za pokretanje sadrži sljedeće važne informacije:

  • 0x10 (1 bajt) – broj FAT tablica (obično 2);
  • 0x20 (4 bajta) - broj sektora na disku;
  • 0x2C (4 bajta) – broj klastera korijenskog imenika;
  • 0x47 (11 bajtova) – oznaka volumena;
  • 0x1FE (2 bajta) - Potpis sektora za pokretanje (55 AA).

Informacijski sektor datotečnog sustava sadrži:

  • 0x00 (4 bajta) – potpis (52 52 61 41);
  • 0x1E4 (4 bajta) – potpis (72 72 41 61 );
  • 0x1E8 (4 bajta) – broj slobodnih klastera, -1 ako nije poznato;
  • 0x1EC (4 bajta) – broj posljednjeg snimljenog klastera;
  • 0x1FE (2 bajta) - potpis (55 AA).

FAT tablica sadrži informacije o stanju svakog klastera na disku. Donja 2 bajta FAT tablice pohranjuju F8 FF FF 0F FF FF FF FF (što odgovara stanju klastera 0 i 1, fizički odsutan). Nadalje, stanje svakog klastera sadrži broj klastera u kojem se nastavlja trenutna datoteka ili sljedeće informacije:

  • 00 00 00 00 – klaster je slobodan;
  • FF FF FF 0F je kraj trenutne datoteke.
  • 8 bajtova - naziv datoteke;
  • 3 bajta - ekstenzija datoteke;

Korijenski direktorij sadrži skup 32-bitnih zapisa podataka za svaku datoteku koji sadrži sljedeće informacije:

Kada radite s dugim nazivima datoteka (uključujući ruske nazive), naziv datoteke je kodiran u UTF-16 sustavu kodiranja. U ovom slučaju, 2 bajta se dodjeljuju za kodiranje svakog znaka. U ovom slučaju, naziv datoteke je napisan u obliku sljedeće strukture:

  • sekvenca od 1 bajta;
  • 10 bajtova sadrži donjih 5 znakova naziva datoteke;
  • 1 bajtni atribut;
  • 1 bajt rezerviran;
  • 1 bajt - kontrolni zbroj DOS imena;
  • 12 bajtova sadrži donja 3 znaka naziva datoteke;
  • 2 bajta – broj prvog klastera;
  • preostali znakovi dugog imena.

Rad s datotekama u C

Programeru je otvorena datoteka predstavljena kao niz podataka koji se čitaju ili pišu. Kada se datoteka otvori, ona je povezana s I/O protok. Izlazne informacije se zapisuju u stream, ulazne informacije se čitaju iz toka.

Kada se tok otvori za I/O, on je povezan sa standardnom strukturom tipa FILE, koja je definirana u stdio.h. Struktura FILE sadrži potrebne informacije o datoteci.

Otvaranje datoteke vrši se pomoću funkcije fopen() koja vraća pokazivač na strukturu tipa FILE, koja se može koristiti za naknadne operacije na datoteci.

DATOTEKA *fopen(naziv, vrsta);


naziv je naziv datoteke koja se otvara (uključujući putanju),
type je pokazivač na niz znakova koji definiraju kako se pristupa datoteci:
  • "r" - otvorena datoteka za čitanje (datoteka mora postojati);
  • "w" - otvori praznu datoteku za pisanje; ako datoteka postoji, njen sadržaj se gubi;
  • "a" - otvorena datoteka za pisanje do kraja (za dodavanje); datoteka se kreira ako ne postoji;
  • "r+" - otvorena datoteka za čitanje i pisanje (datoteka mora postojati);
  • "w+" - otvori praznu datoteku za čitanje i pisanje; ako datoteka postoji, njen sadržaj se gubi;
  • "a+" - otvorite datoteku za čitanje i dodavanje, ako datoteka ne postoji, kreira se.

Povratna vrijednost je pokazivač na otvoreni tok. Ako se pronađe greška, vraća se NULL.

Funkcija fclose() zatvara tok ili streamove povezane s datotekama otvorenim pomoću fopen(). Tok koji treba zatvoriti određen je argumentom funkcije fclose().

Povratna vrijednost: vrijednost 0 ako je stream uspješno zatvoren; EOF konstanta ako je došlo do greške.

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

#uključiti
int main() (
DATOTEKA *fp;
char name = "my.txt" ;
ako ((fp = fopen(ime, "r" )) == NULL )
{
printf( "Ne mogu otvoriti datoteku");
getchar();
vrati 0;
}
// otvaranje datoteke uspjelo
... // potrebne radnje nad podacima
fclose(fp);
getchar();
vrati 0;
}

Čitanje znaka iz datoteke:

char fgetc(stream);


Argument funkcije je pokazivač na tok tipa FILE. Funkcija vraća kod pročitanog znaka. Ako se dostigne kraj datoteke ili dođe do greške, vraća se EOF konstanta.

Upisivanje znaka u datoteku:

fputc(znak, tok);

Argumenti funkcije su znak i pokazivač na tok tipa FILE . Funkcija vraća kod pročitanog znaka.

Funkcije fscanf() i fprintf() slične su funkcijama scanf() i printf(), ali rade na podatkovnim datotekama i imaju pokazivač datoteke kao prvi argument.

fscanf(stream, "InputFormat" , args);

I/O mehanizam koji je razvio , ne odgovara općeprihvaćenom stilu objektno orijentiranog programiranja danas, osim toga, aktivno koristi operacije pokazivača, koje se smatraju potencijalno nesigurnima u modernim okruženjima sigurnog izvršavanja koda. Alternativa za razvoj aplikacija je standardni mehanizam I/O klase koji osigurava standard jezika C++.

Otvaranje datoteka

Najčešće korištene klase su ifstream za čitanje, ofstream za pisanje i fstream za modificiranje datoteka.

Sve I/O klase s navojem neizravno su izvedene iz zajedničkog pretka ios-a, u potpunosti nasljeđujući njegovu funkcionalnost. Na primjer, nabrojani član podataka open_mode specificira način otvaranja datoteke, koji je definiran na sljedeći način:

Enum open_mode ( app, binary, in, out, trunc, ate );

Ispod su moguće vrijednosti zastava i njihova namjena.

Na primjer, da biste otvorili datoteku pod nazivom test.txt za čitanje binarnih podataka, napisali biste:

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

Logički OR operator (|) omogućuje vam da sastavite način s bilo kojom kombinacijom zastavica. Kako prilikom otvaranja datoteke pisanjem ne biste slučajno prebrisali postojeću datoteku s istim imenom, morate koristiti sljedeći obrazac:

offstream datoteka; file.open("test.txt", ios::out | ios::app);

Pretpostavlja se da je odgovarajuća datoteka zaglavlja povezana s projektom:

#uključiti

Da biste provjerili je li datoteka uspješno otvorena, možete koristiti konstrukciju

If (!file) ( // Rukovanje pogreškom otvaranja datoteke)

Operatori uključivanja i ekstrakcije

Poništeno u klasama rukovanja datotekama uključiti operatora (<<) записывает данные в файловый поток. Как только вы открыли файл для записи, можно записывать в него текстовую строку целиком:

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

Također možete napisati tekstualni niz u dijelovima:

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

Naredba endl završava unos retka s povratkom nositelja:

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

Koristeći operator uključivanja, lako je zapisati vrijednosti varijabli ili elemenata niza u datoteku:

Datoteka izvan streama ("Temp.txt"); char buff = "Tekstualni niz sadrži varijable"; int vx = 100; plovak pi = 3,14159; datoteka<< buff << endl << vx << endl << pi << endl;

Kao rezultat izvršenja koda, generiraju se tri retka tekstualne datoteke Temp.txt:

Tekstualni niz sadrži varijable 100 3.14159

Imajte na umu da se numeričke vrijednosti zapisuju u datoteku kao tekstualni nizovi, a ne binarne vrijednosti.

operator ekstrakcije(>>) čini suprotno. Čini se da da biste izdvojili znakove iz datoteke Temp.txt koja je ranije napisana, trebate napisati sljedeći kod:

ifstream datoteka("Temp.txt"); char buff; intvx; floatpi; datoteka >> buff >> vx >> pi;

Međutim, operator ekstrakcije će se zaustaviti na prvom graničniku (razmak, tabulator ili novi redak) na koji naiđe. Dakle, prilikom raščlanjivanja rečenice "Text array contains varijable", samo će riječ "Text" biti upisana u buff array, razmak se zanemaruje, a riječ "array" će postati vrijednost cjelobrojne varijable vx i koda izvršenje će se "pokvariti" s neizbježnim kršenjem strukture podataka. Zatim, kada raspravljamo o klasi ifstream, pokazat ćemo kako pravilno organizirati čitanje datoteke iz prethodnog primjera.

ifstream klasa: čitanje datoteka

Kao što naziv implicira, klasa ifstream dizajnirana je za unos toka datoteke. Glavne metode klase navedene su u nastavku. Većina ih je naslijeđena iz klase istream i preopterećena roditeljskom funkcionalnošću. Na primjer, funkcija get, ovisno o parametru poziva, može čitati ne samo jedan znak, već i blok znakova.

Sada je jasno kako trebate modificirati prethodni primjer tako da korištenje operatora ekstrakcije podataka daje očekivani rezultat:

ifstream datoteka("Temp.txt"); char buff; intvx; floatpi; file.getline(buff, sizeof(buff)); datoteka >> vx >> pi:

Metoda getline pročitat će prvi redak datoteke do kraja, a operator >> će dodijeliti vrijednosti varijablama.

Sljedeći primjer prikazuje dodavanje podataka u tekstualnu datoteku, a zatim čitanje cijele datoteke. Petlja while (1) koristi se umjesto while(!file2.eof()) iz razloga o kojima se raspravlja u .

#uključiti #uključiti korištenje imenskog prostora std; int main() ( datoteka izvan streama; file.open("test.txt",ios::out|ios::app); if (!file) (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; if (file2.eof()) break; cout<< a << " "; k++; } cout << endl << "K=" << k << endl; file2.close(); cin.sync(); cin.get(); return 0; }

Sljedeći primjer ponavlja čitanje redaka iz datoteke test.txt i njihovo prikazivanje na konzoli.

#uključiti #uključiti korištenje imenskog prostora std; int main() ( ifstream datoteka; // kreiraj datoteku objekta stream file.open("test.txt"); // otvori datoteku za čitanje if (!file) return 1; // povratak na pogrešku otvaranja char str; / / statički međuspremnik reda // Čitanje i prikaz redaka u petlji do eof dok (!file.getline(str, sizeof(str)).eof()) cout<< str << endl; // вывод прочитанной строки на экран cin.sync(); cin.get(); return 0; }

Ovaj kod pod Windows OS-om također ovisi o prisutnosti znaka novog retka u zadnjem retku datoteke, bilo bi pouzdanije učiniti ovo:

Dok (1) ( if (file.eof()) break; file.getline(str, sizeof(str)); cout<< str << endl; }

Eksplicitni pozivi metodama otvaranja i zatvaranja nisu obavezni. Doista, pozivanje konstruktora s argumentom omogućuje vam da odmah otvorite datoteku, u trenutku kada se kreira objekt toka datoteke:

ifstream datoteka("test.txt");

Umjesto metode close, možete koristiti operator delete, koji će automatski pozvati destruktor objekta datoteke i zatvoriti datoteku. Kod petlje while osigurava ispravnu provjeru kraja datoteke.

ofstream klasa: pisanje datoteka

Klasa ofstream dizajnirana je za izlaz podataka iz toka datoteka. Glavne metode ove klase navedene su u nastavku.

Ranije opisani operator uključivanja prikladan je za organiziranje pisanja u tekstualnu datoteku:

Datoteka izvan streama("temp.txt"); if (!file) return; za (int i=1; i<=3; i++) file << "Строка " << i << endl; file.close();

Binarne datoteke

U principu, binarni podaci se poslužuju kao tekstualni podaci. Razlika je u tome što ako su binarni podaci zapisani u određenoj logičkoj strukturi, onda se moraju pročitati iz datoteke u varijablu istog tipa strukture.

Prvi parametar metoda pisanja i čitanja (adresa bloka za pisanje/čitanje) mora biti tipa pokazivača znakova char * , pa je potrebno eksplicitno pretvoriti tip adrese void * strukture. Drugi parametar određuje da binarni blokovi datoteke imaju konstantnu veličinu bajta bez obzira na stvarnu duljinu zapisa. Sljedeći dodatak daje primjer kako stvoriti i prikazati podatke u jednostavnoj bilježnici. Zapisi datoteke se zatim uzastopno čitaju i prikazuju na konzoli.

#uključiti #uključiti #uključiti korištenje imenskog prostora std; struct Bilješke ( // struktura podataka bilježnice char Ime; // puno ime char Telefon; // telefon int Dob; // starost); int main() ( setlocale(LC_ALL, "ruski"); Bilješke Note1= ("Grozny Ioann Vasilievich", "nije instalirano", 60); Bilješke Note2= ("Godunov Boris Fedorovich", "095-111-2233 ", 30 ); Bilješke Note3= ("Romanov Petr Mihajlovič", "812-333-2211", 20); ofstream ofile("Notebook.dat", ios::binary); ofile.write((char*)&Note1, sizeof (Napomene)); // 1. blok ofile.write((char*)&Note2, sizeof(Notes)); // 2. blok ofile.write((char*)&Note3, sizeof(Notes)); / / 3. blok ofile .close(); // zatvori napisanu datoteku ifstream ifile("Notebook.dat", ios::binary); Bilješke Napomena; // strukturirana varijabla char str; // statički string buffer // Čitanje i prikaz redaka u petlji do eof while (!ifile.read((char*)&Note, sizeof(Notes)).eof()) ( sprintf(str, "%s\tBody: %s\tAge: %d" , Note.Name, Note .Telefon, Napomena. Dob); cout<< str << endl; } ifile.close(); // закрыть прочитанный файл cin.sync(); cin.get(); return 0; }

Kao rezultat izvršavanja ovog koda, binarna datoteka Notebook.dat formira se iz tri bloka od 80 bajtova svaki (pod pretpostavkom da su znakovi jednobajtni). Naravno, možete koristiti druge metode strujanja i izvesti bilo koju operaciju na poljima određene strukture podataka.

fstream klasa: slučajni pristup datoteci

Pretpostavimo da je u našoj bilježnici skupljeno 100 unosa, a mi želimo izbrojati 50. Naravno, možete organizirati petlju i pročitati sve zapise od prvog do zadanog. Očito je ciljanije rješenje postaviti pokazivač pozicije pos datoteke izravno na unos 50 i pročitati ga:

ifstream ifile("Bilježnica.dat", ios::binary); int pos = 49 * sizeof(Napomene); ako traži (pos); // traži 50. unos Bilješke Napomena; //Napomene - gore opisana struktura "zapisa" ifile.read((char*)&Note, sizeof(Notes));

Takve operacije pretraživanja učinkovite su ako se datoteka sastoji od zapisa poznate i konstantne veličine. Da biste zamijenili sadržaj proizvoljnog unosa, morate otvoriti izlazni tok u modificiranom načinu:

Ofstream ofile("Bilježnica.dat", ios::binary | ios::ate); int pos = 49 * sizeof(Napomene); ofile seekp(pos); // traži 50. bilješku Bilješke Note50 = ("Jeljcin Boris Nikolajevič", "095-222-3322", 64); ofile.write((char*)&Note, sizeof(Notes)); // zamjena

Ako ne navedete oznaku ios::ate (ili ios::app), onda kada otvorite binarnu datoteku Notebook.dat, njezin će se prethodni sadržaj izbrisati!

Konačno, moguće je istovremeno otvoriti datoteku za čitanje/pisanje, korištenjem metoda koje je klasa streaminga fstream naslijedila od svojih prethodnika. Budući da je klasa fstream izvedena iz istreama i ostreama (roditelji ifstreama odnosno ofstreama), sve prethodno spomenute metode postaju dostupne aplikaciji.

Sljedeći primjer zamjenjuje prvi i treći unos u datoteci Notebook.dat.

#uključiti #uključiti #uključiti korištenje imenskog prostora std; struct Bilješke ( char Ime; char Telefon; int Dob; ); int main() ( setlocale(LC_ALL, "Ruski"); Bilješke Note1, Note3; // Otvorite datoteku za istovremeno čitanje/pisanje fstream file("Notebook.dat", ios::binary | ios::in | ios:: out); file.seekg(2 * sizeof(Notes)); // pronaći i pročitati Note3 file.read((char*)&Note3, sizeof(Notes)); file.seekg(0); // pronaći i pročitati Note1 file.read((char*)&Note1, sizeof(Notes)); file.seekg(0); // Napomena1<== 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; }

Oznake ios::in i ios::out moraju biti specificirane u konstruktoru objekta datoteke kako bi se omogućile istodobne operacije čitanja i pisanja. Kao rezultat izvršavanja ovog koda, prvi i treći zapis binarne datoteke Notebook.dat bit će zamijenjeni.

Postoje dodatni primjeri na temu.

Vrhunski povezani članci