Skip to content

Latest commit

 

History

History
337 lines (303 loc) · 12.4 KB

FP_22_C_2022-01-06.md

File metadata and controls

337 lines (303 loc) · 12.4 KB

FISIERE IN LIMBAJUL C

Pentru a folosi fisiere trebuie sa folosim un pointer catre FILE FILE* si sa includem biblioteca stdio.h. Deschiderea unui fisier se face cu ajutorul functiei fopen care are doi parametri de tip pointer catre char: primul este numele fisierului, eventual urmat de calea acestuia, al doilea parametru continand un string care poate contine doar cateva caractere. Aceste caractere, daca apar, arata modul in care va fi folosit fisierul: mod binar, mod tex, mod citire, mod scriere, etc..

Caracter Explicatie
r Fisierul este deschis pentru operatii de citire. Se presupune ca fisierul exista pe disc si avem acces la el, altfel, pointer catre FILE* va returna valoarea NULL.
w Fisierul este deschis pentru operatii de scriere. Daca exista fisierul pe disc, se sterge si va fi creat unul nou; daca nu exista se creeaza unul nou. Deschiderea fisieului in acest mod poate sa esuaze daca fie numele, fie calea sunt gresite sau daca fisierul este deschis deja de aplicatie sau de un program extern aplicatiei sau daca nu avem drepturi de scriere in locatia fisierului.
b Fisierul este deschis in modul binar, fiind interpretat ca fiind o succesiune de octeti ai tabelei ASCII. In momentul in care b lipseste sau apare t inseamna ca fisierul este deschis in modul text, fiind interpretat ca fiind o succesiune de linii, despartite prin caracterul cu codul ASCII = 13, codul tastei Enter.
a Fisierul este deschis pentru append, adica adaugare la sfarsit. Fisierul poate sa exista sau sa nu existe. Daca exista, fisierul este deschis, iar cursorul se muta la finalul fisierului, fara a se sterge fisierul asa cum face w. Daca nu exista, fisierul este creat.
+ Aparitia caracterului + arata deschiderea unui fisier in mod mixt. r, desi este un mod de citire, r+ suporta si operatii de scriere. w este folosit pentru operatii de scriere, dar w+ sunt suportate si operatii de citire. Pentru a se deschide fisierul in modul scriere cu mutarea cursorului la final pentru scriere, dar a+ poate fi folosit si pentru operatii de citire.

Ordinea caracterelor in cel de-al doilea string nu este importanta: a+b = ab+.

char numef[256];
FILE* fis;

printf("Numele fisierului: ");
gets(numef);
fis = fopen(numef, "rb+");
if (fis == NULL)
{
    printf("Eroare! Nu am putut deschide fisierul %s. \n", numef);
    exit(1);
}

Odata terminat lucrul cu fisiere, acestea trebuiesc inchise pentru a nu pierde date, folosind functia fclose.

fclose(FILE* fis);

Un fisier deschis de o aplicatie ramane deschis pana cand acesta este inchis, timp in care consuma memorie RAM. Orice OS suporta un numar maxim de fisiere ce pot fi deschise de catre o aplicatie. In ziua de azi, acest numar este de peste zeci de mii de fisiere, dar, desi pare un numar destul de mare, uneori poate fi considerat destul de mic, motiv pentru care fisierele trebuie sa fie inchise.

In momentul in care scriem intr-un fisier folosind o aplicatie, scrierea nu se face direct pe disc, ci intr-o zona tampon, numita buffer atasata fisierului din memoria RAM.

In momentul in care inchidem un fisier ne asiguram ca tot ceea ce am scris in acesta ajunge efectiv pe disc.

Folosind unele compilatoare, in cazul in care nu inchidem un fisier, este posibil ca la inchiderea aplicatiei bufferul atasat fisierului sa nu se goleasca si astfel ca datele sa nu fie salvate pe disc.

Exista si o functie folosita pentru a inchide toate fisierele deschise de catre o aplicatie: fcloseall();, functie care returneaza numarul de fisiere ce au fost inchise.

Functie Utilizare
feof(fis) returneaza 0 daca nu s-a ajuns la capatul fisierului sau o valoare nenula daca este sfarsit fisierul
fflush(fis) goleste bufferul fisierului fis, fortand scrierea datelor din zona de memorie RAM tampon in fisier pe disc. In caz de succes, returneaza 0, altfel returneaza valoarea corespunzatoare constantei EOF definita in stdio.h.
flushall(); goleste bufferul tuturor fisierelor deschise
ferror(fis) verifica daca exista erori in timpul prelucrarii fisierului si in caz afirmativ returneaza o valoare nenula.
fgetc(fis) citeste un caracter din fisier. Returneaza fie codul caracterului citit, fie EOF daca s-a ajuns la finalul fisierului.
fputc(fis) pune un caracter in fisier
fgets(s, n, fis) fisierul este interpretat ca fiind text: se citeste un sir de caractere de lungime maxima n, care se depune la adresa s.
fputs(s, fis) scrie un string s intr-un fisier
fprintf(fis, ...) scriere formatata intr-un fisier text
fscandf(fis, ...) citire formatata in moduul text
size_t fread(void* p, int nb, int lb, FILE* fis); citire in modul binar; se citesc nb blocuri de lungime lb fin fiserul indicat de pointerul fis si de depun la adresa de memorie p. Returneaza numarul efectiva de blocuri citite din fisier, unde size_t este un tip de date special definit pentru dimensiuni de blocuri de memorie.
size_t fread(void* p, int nb, int lb, FILE* fis); citirea in modul binar; se iau nb blocuri de lungime lb de la adresa de memorie p si se scriu in fisierul fis. Returneaza numarul efectiv de blocuri scrise in fisier.
size_t fwrite(void* p, int nb, int lb, fis) scrierea in modul binar; se iau nb blocuri de dimensiune lb de la adresa de memorie p si se scriu in fisierul fis.
int fseek(FILE *fis, long n, int deunde) se face salt in fisier cu n octeti de la ultimul parametru al functiei; deunde poate fi 0 (SEEK_SET), 1 (SEEK_CUR) sau 2 (SEEK_END)
long ftell(fis) returneaza in octeti pozitia cursoruluiin fisierul dat ca parametru

Folosind functia ftell putem scrie o alta functie care sa returneze lungimea fisierului:

#include <stdio.h>
long flung (char* numef)
{
    FILE* fis;
    fis = fopen (numef, "rb");
    fseek (fis, 0, SEEK_END);
    return ftell(fis);
}
void main ()
{
    printf("Fisierul 'autoexec.bat' are %ld octeti. \n", flung("c:\\autoexec.bat"));
    getch();
}
Functie Utilizare
int rename(const char* numef1, const char* numef2); redenumeste fisierul numef1 in numef2; stringurile pot fi precedate si de o cale; redenumirea se poate face doar pe acelasi drive

In cazul in care redenumirea s-a facut cu succes, se returneaza 0, altfel se returneaza -1 si variabila globala errno se seteaza la una dintre valorile:

  • ENOENT = no such file or directory
  • EACCES = permission denied
  • ENOTSAM = not same device
Functie Utilizare
int remove(const char* numef); stergerea fisierului de pe disc

In cazul in care stergerea s-a facut cu succes, se returneaza valoarea 0, altfel se returneaza valoarea -1 si variabila globala errno se seteaza la una dintre valorile:

  • ENOENT = no such file or directory
  • EACCES = permission denied

Surse programe C care lucreaza cu fisiere

Concatenarea mai multor fisiere ale caror nume sunt primite in linie de comanda. Ultimul parametru primit in linie de comanda se considera a fi numele fisierului destinatie.

#include <stdio.h>
#include <conio.h>
#include <alloc.h>

#define lbuf 1024 // lungimea bufferului de transfer este 1 KB

int main(int narg, char* argv[])
{
    char* buf;
    int i, n, eroare = 0;
    FILE* fis, *fisd;
    buf = (char)malloc(lbuf);
    if (buf == NULL)
    {
        printf("Eroare! Memorie insuficienta.\n");
        getch();
        return 1;
    }
    if (narg<3)
    {
        printf("Eroare! Structura comencii este: \n\n");
        printf("%s <fis1> [<fis2>...<fisn>] <fis_dest>\n\n",argv[0]);
        printf("Se concateneaza <fis1>, <fis2> ... <fisn>. \n");
        printf("Fisierele se depun in <fis_destinatie>.\n");
        getch();
        return 1;
    }
    fisd = fopen(arfv[narg-1], "wb");
    if (fisd == NULL)
    {
        printf("Eroare! Nu am putut deschide %s pt scriere.\n", argv[n-1]);
        getch();
        return 0;
    }
    for(i = 1; i < narg-1; i++)
    {
        fis = fopen(argv[i], "rb");
        if (fis == NULL)
        {
            printf("Eroare! Nu am putut deschide %s.\n", argv[i]);
            eroare++;
        }
        do
        {
            n = fread (buf, 1, lbuf, fis);
            fwrite (buf, 1, n, fisd);
        }
        while (!feof(fis));
        fclose (fis);
    }
    fclose (fisd);
    free (buf);
    if (!eroare)
        printf("Concatenarea s-a incheiat cu succes!");
        getch();
        return 0;
}

Afisarea continutului unui fisier

#include <stdio.h>
#include <conio.h>
#include <alloc.h>

#define maxlinie 79

int main (void)
{
    chat numef[100], *linie;
    long n = 0;
    FILE* fis;

    linie = (char*)malloc(maxlinie + 1);
    if (linie == NULL)
    {
        printf("Eroare! Memorie insuficienta.\n");
        getch();
        return 1;
    }
    printf("Dati numele fisierului text de tiparit pe ecran: ");
    gets (numef);
    fis = fopen(numef, "rt");
    if (fis == NULL)
    {
        printf("Eroare! Nu am putut deschide %s pt citire.\n", numef);
        getch();
        return 0;
    }
    while (!feos(fis))
    {
        fgets(linie, maxlinie, fis);
        if(!feof(fis))
        {
            n++;
            printf(linie);
            if(n%24 == 0)
                getch();
        }
    }
    fclose(fis);
    free(linie);
    printf("Am afisat: %ld linii.", n);
    getch();
    return 0;
}

Produsul a doua matrici citite din fisiere text.

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <process.h>
#include <alloc.h>

void EroareAloc ()
{
    printf("Eroare! Memorie insuficienta.");
    exit(1);
}

float** MatrAlloc (int m, int n)
{
    int i;
    float **a;
    if ((a = float**)calloc(m,sizeof(float)) == NULL)
        EroareAloc();
    for (i = 0; i < m; i++)
        if ((a[i] = (float*)calloc(n,sizeof(float))) == NULL)
            EroareAloc();
    return a;
}

void main(void)
{
    char numef[100];
    int i, j, k, m, n, n2, p;
    float **a, **b, **c, f;
    FILE *fis;
    printf("Dati numele fisierului text cu prima matrice: ");
    gets(numef);
    fis = fopen(numef,"rt");
    if (fis == NULL)
    {
        printf("Eroare! Nu am putu deschide %s pt citire.\n", numef);
        getch();
        exit(0);
    }
    fscanf(fis, "%d%d", &m, &n);
    a = MatrAlloc (m, n);
    for (i = 0; i < m; i++)
    {
        for (j=0; j < n; j++)
        {
            fscanf (fis, "%f", &f);
            a[i][j] = f;
            printf ("%10.2lf", a[i][j]);
        }
        puts("");
    }
    fclose (fis);
    printf ("dati numele fisierului text cu a doua matrice: ");
    gets(numef);
    fis = fopen (numef, "rt");
    if (fis == NULL)
    {
        printf("Eroare! Nu am putu deschide %s pt citire.\n", numef);
        getch();
        exit(0);
    }
    fscanf(fis, "%d%d", &n2, &p);
    if(n != n2)
    {
        fclose(fis);
        printf("\nEroare! Matricile nu se pot inmulti: \n");
        printf(" A(%d,%d) x B(%d.%d) \n", m, n, n2, p);
        getch();
        exit(0);
    }
    b = MatrAlloc (n, p);
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < p; j++)
        {
            fscanf (fis, "%f", &s);
            b[i][j] = f;
            printf ("%10.2lf", b[i][j]);
        }
        puts("");
    }
    fclose (fis);
    printf ("Dati numele fisierului in care sa se puna rezultatul: ");
    gets(numef);
    if (fis == NULL)
    {
        printf("Eroare! Nu am putut deschide %s pt scriere. \n", numef);
        getch();
        exit(0);
    }
    fis = fopen (numef, "wt");
    c = MatrAlloc (m, p);
    for (i = 0; i< m; i++)
        for (j = 0; j < p; j++)
        {
            c[i][j] = 0;
            for (k = 0; k < n; k++)
                c[i][j] += a[i][k] * b[k][j];
        }
    for (i = 0; i< m; i++)
    {
        for (j = 0; j < p; j++)
        {
            printf("%10.2f", c[i][j]);
            fprintf(fis, "%10.2f", c[i][j]);
        }
        printf("\r\n");
        fprintf(fis, "\r\n");
    }
    for (i = 0; i < m; i++)
        free(a[i]);
    for (i = 0; i < n; i++)
        free(a[i]);
    for (i = 0; i < m; i++)
        free(a[i]);
    free(a);
    free(b);
    free(c);
    fclose (fis);
    getch();
}