<<Pagina Materiale

 
 
Fisiere 
Functii de I/E

O parte a puterii limbajului C consta in biblioteca de functii puse la dispozitia programatorului. Declaratiile diferitelor functii sunt grupate in fisiere antet (header).
Cateva din functiile si constantele cele mai des intilnite au fost deja utilizate in exemplele anterioare.

  • stdio.h - contine functii de introducere - extragere a datelor
  • Functiile utilizate pina in acest moment (de ex: getchar, printf, gets, etc.) opereaza cu fisierele standard de introducere si extragere: stdin(implicit tastatura) si stdout (implicit monitorul). Prin redirectare aceste fisiere standard se pot asocia cu alte fisiere.

    Exemplu:
                fisier_exe <fisier_1 >fisier_2

    In acest caz preluarea informatiilor se face din fisier_1, iar afisarea informatiilor de iesire se face in fisier_2.

    Urmatoarele functii opereaza cu fisiere specificate de utilizator:

      • pentru un caracter:
    • int getc(FILE *fis);- returneaza un caracter din fisierul precizat convertit la un intreg fara semn, iar la eroare returneaza EOF
    • int ungetc(int c, FILE *fis);- inapoiaza caracterul c in fisierul deschis  pentru citire
    • int putc(int c, FILE * fis); - trimite caracterul in fisierul deschis pentru scriere, la eroare returneaza EOF
      • pentru un sir de caractere:
    • char *fgets(char *s, int n, FILE *fis);- citeste maxim n-1 caractere sau pina la '\n' inclusiv, si le depune in s, adauga la sfirsit '\0' si returneaza adresa sirului. La eroare intoarce valoarea NULL
    • int fputs(const char *s, FILE *fis);   - scrie sirul in fisier, fara caracterul '\0'. La eroare intoarce EOF.

    •  
      • pentru scriere si citire cu format:
    • int fscanf (FILE *fis, const char *format [, adresa, ...]); - numarul de adrese trebuie sa corespunda cu numarul de specificatori de format. Formatul contine  - caractere spatii - se sare peste spatii pina la primul caracter nespatiu - caractere obisnuite - caractere ASCII, mai putin '%', se trece peste un caracter corespunzator in intrare
                          specificatorul de format: % [*] [width] type
                                * - se sare peste urmatoarea data
                                width - nr. de maxim de caractere ce se citesc
                                type  - tipul informatiei citite:
                                o - octal , u - fara semn, x,X - hexa
                                d - zecimal, l - long, f - float, lf - double,
                                e,E-  format stiintific, c - char, s - sir
    • int fprintf (FILE *fis, const char *format [, argum...]); - preia un sir de argumente si le aplica formatul corespunzator, dupa care le scrie in fisierul dat.   Formatul contine - caractere obisnuite, care apar la fel la iesire
                          specificatori de format (egal sau mai mic decit numarul de argumente): % [fanion] [width][.prec] type
                                fanion - alinierea la dreapta sau stinga, prezenta semnului, etc.
                                width  - numarul minim de caractere ce se afiseaza
                                prec   - precizia
  • conio.h - functii de intrare, iesire pentru consola
    • void window(int left, int top, int right, int bottom);- defineste o fereastra text precizata prin colturile stinga sus, dreapta jos
    • void clreol( void );- sterge intr-o fereastra text de la cursor pina la sfirsirul liniei
    • void clrscr( void );- sterge fereastra text activa si muta cursorul in pozitia 1,1
    • void gotoxy( int x, int y );- muta cursorul la coordonatele date
    • int  wherex( void );- returneaza coordonata curenta x
    • int  wherey( void );- returneaza coordonata curenta y
    • int  getch( void ); - citeste un caracter fara a-l afisa la consola
    • int  getche( void ); - citeste si afiseaza caracterul
    • int  kbhit( void ); - verifica daca a fost apasata o tasta
    • int  putch( int c );- pune un caracter in fereastra text curenta.
  • stdlib.h - contine tipuri, variabile si functii uzuale
    • #define max(a,b)    (((a) > (b)) ? (a) : (b))
    • #define min(a,b)    (((a) < (b)) ? (a) : (b))
      • pentru conversia unui sir:
    • double atof(const char *s); - returneaza valoarea reala obtinuta prin conversia  sirului, iar la eroare valoarea 0
    • int    atoi(const char *s); - converteste sirul la un intreg
    • long   atol(const char *s); - converteste sirul la un long
      • pentru terminarea programului:
    • void   exit(int status);  - termina programul si inchide toate fisierele. Parametrul status indica terminare normala (valoarea 0) sau anormala.
    • void   abort(void);- termina anormal programul
      • pentru alocare dinamica:
    • void  free(void *bloc);- elibereaza memorie alocata dinamic anterior
    • void *malloc(dim_t nr);- aloca nr locatii de memorie de cite sizeof(dim_t) octeti. La succes returneaza adresa de inceput a zonei alocate, la eroare returneaza NULL
      • cautare binara:
    • void * bsearch(const void *key, const void *base, size_t nelem, size_t width, int (*fcmp)(const void *, const void *));- returneaza adresa primei intrari din tablou care coincide cu parametrul cautat si zero daca acesta nu exista in tablou. ( key- adresa cheii cautate, base- inceputul tabloului, nelem- nr.elemente din tablou, width- dim. unui elem. de tablou, fcmp- functia de comparare definita de utilizator si care primeste doi parametrii )
      • sortare cu algorimul Quicksort:
      void  qsort(void *base, size_t nelem, size_t width, int (*fcmp)(const void *, const void *));- sorteaza tabloul dat
      Sus
    Lucrul cu fisiere

    Un fisier este o structura dinamica, situata in memoria secundara ( pe flopyy disk-uri sau harddisk-uri ); numarul de elemente ale unui fisier este variabil, chiar nul..

    Limbajul C permite operarea cu fisiere:

    • de tip text - un astfel de fisier contine o succesiune de linii, separate prin NL ('\n')
    • de tip binar - un astfel de fisier contine o succesiune de octeti, fara nici o structura.
    Prelucrarea unui fisier presupune asocierea acestuia cu un canal de I/E ( numit flux sau stream ). Exista doua canale predefinite, care se deschid automat la lansarea unui program:
    • stdin - fisier de intrare, text, este intrarea standard - tastatura
    • stdout - fisier de iesire, text, este iesirea standard - ecranul monitorului.
    Pentru a prelucra un fisier, trebuie parcurse urmatoarele etape:
    • se defineste o variabila de tipFILE *pentru accesarea fisierului; FILE * este un tip structura definit in stdio.h, care contine informatii referitoare la fisier si la tamponul de transfer de date intre memoria centrala si fisier ( adresa, lungimea tamponului, modul de utilizare a fisierului, indicator de sfarsit, de pozitie in fisier )
    • se deschide fisierul pentru un anumit mod de acces, folosind functia de biblioteca fopen, care realizeaza si asocierea intre variabila fisier si numele extern al fisierului
    • se prelucreaza fisierul in citire/scriere cu functiile specifice
    • se inchide fisierul folosind functia de biblioteca fclose.
    Mai jos se prezinta restul functiilor de prelucrare a fisierelor:
    • FILE *fopen(const char *nume_fis, const char *mod); - deschide fisierul cu numele dat pentru acces de tip mod. . Returneaza pointer la fisier sau NULL daca fisierul nu poate fi deschis; valoarea returnata este memorata in variabila fisier, care a fost declarata pentru accesarea lui.
            mod: "r" - readonly , este permisa doar citirea dintr-un fisier existent
                      "w" - write, creaza un nou fisier, sau daca exista deja, distruge vechiul continut
                      "a" - append, deschide pentru scriere un fisier existent ( scrierea se va face in continuarea informatiei deja existente in fisier, deci pointerul  de acces se plaseaza la sfirsitul fisierului )
                      "+" - permite scrierea si citirea - actualizare (ex: "r+", "w+", "a+"). O citire nu poate fi direct urmata de o scriere si reciproc. Intai trebuie repozitionat cursorul de acces printr-un apel la fseek.
                      "b" - specifica fisier de tip binar
                      "t" - specifica fisier de tip text (implicit), la care se face automat conversia CR-LF("\n\f") in sau din CR ('\n').
    • int fclose(FILE *fp);- inchide fisierul si elibereaza zona tampon; returneaza 0 la succes, EOF la eroare
    • int fseek(FILE *fp, long offset, int whence);- repozitioneaza pointerul asociat unui fisier . Offset - numarul de octeti intre pozitia data de whence si noua pozitie. Whence - are una din cele trei valori posibile:
                     SEEK_SET =  0 -  Cautarea se face de la inceputul fisierului
                     SEEK_CUR =  1 -  Cautare din pozitia curenta
                     SEEK_END =  2 -  Cautare de la sfirsitul fisierului
    • int feof(FILE *fis);- returneaza 0 daca nu s-a detectat sfarsit de fisier la ultima operatie de citire, respectiv o valoare nenula ( adevarata ) pentru sfarsit de fisier.
    Sus
    Argumentele liniei de comanda

    La lansarea in executie a unui fisier executabil, in linia de comanda, pe langa numele fisierului s epot specifica argumente, care se transmit ca parametrii functiei main. Antetul functiei main va fi atunci:

        int main( int argc, char ** argv )

    argc - reprezinta numarul de argumente
    argv -este un pointer la un tablou de siruri, reprezentand argumentele.

    Argumentele liniei de comanda vor fi sirurile:
        argv[0]  - numele fisierului executabil
        argv[1]
        ...
        argv[argc-1]

    Programul urmator tipareste argumentele liniei de comanda:
     

    // fisier listare.c
    #include<stdio.h>
    int main( int argc, char** argv){
      int i; 
      puts("Argumente:");
      for(i=0;i<argc;i++)
        puts(argv[i]);
      return 0;
    }

    O linie de comanda de forma:
      listare iata patru argumente

    va lansa in executie listare.exe, care va tipari pe ecran:
     listare.exe
     iata
     patru
     argumente:

    Sus
    Exemple

    1.Sa se scrie un program care copiaza continutul unui fisier in altul, numele sursei si destinatiei fiind transmise in linia de comanda.
     

    // fisier copiere.c
    # include <stdio.h>
    int main(int argc, char** argv){
      FILE *fisi, *fise; char c;
      if(!(fisi=fopen(argv[1],"r")||
         !(fise=fopen(argv[2],"w")){
            puts("Fisierele nu pot fi deschise");
            return 1;
      }  //eroare daca fisierele nu pot fi deschise
      while((c=fgetc(fisi))!=EOF) //copiere caracter cu caracter
        fputc(fise);
      fclose(fisi);
      fclose(fise);
      return 0;

    Lansarea in executie a programului se va face cu o linie de comanda de forma:
      copiere fisier_sursa.dat fisier_dest.dat

    Folosind redirectarea fisierelor standard, printr-o linie de comanda de forma:
        copiere1 <fisier_sursa.dat >fisier_dest.dat
    urmatorul program va avea acelasi rezultat:
     

    // fisier copiere1.c
    # include <stdio.h>
    void main(void){
      char c;
      while((c=getchar())!=EOF) //copiere caracter cu caracter
        putchar(c);
      return 0;

    2.Sa se scrie un program care executa in mod repetat urmatoarele operatii:

    • Preia informatiile (nume si nota) pentru o grupa de studenti. Citirea se face dintr-un fisier al carui nume se specifica de utilizator.
    • Verifica prezenta unui student in grupa
    • Listeaza grupa in ordine alfabetica si afiseaza media grupei.
    • Termina program.
    # include <stdio.h>
    # include <stdlib.h>
    # include <ctype.h>
    # include <string.h>
    # define MAX_S  30
    # define MAX_L  20

    char stud[MAX_S][MAX_L];
    FILE *fp=NULL;
    int nrstud;
    float medie;

    void citire(FILE *fp, char tab[][MAX_L]){
      float nota;
      int i;
      medie=0;
      i=0;
      while(!feof(fp)){
        fscanf(fp,"%s%f",tab[i++],&nota);
        medie+=nota;
      }
      nrstud=i-1;
      medie/=nrstud;
      qsort(tab,nrstud,MAX_L,strcmp);
    }

    int cauta(char *s, char tab[][MAX_L]){
      char *t;
      t=bsearch(s,tab,nrstud,MAX_L,strcmp);
      return (t-tab)/MAX_L;
    }

    void main(){
      char c,s[12];
      int i;
      while(1){
        printf("\nOptiunea:\nCitire, Prezenta_student, Listare, Iesire\n >");
        c=getchar();getchar();
        switch(toupper(c)){
          case 'C': printf("nume fisier:");gets(s);
                    if(fp!=NULL) fclose(fp);
                    if((fp=fopen(s,"r"))==NULL){
                         printf("fisierul %s nu exista\n",s);
                         break;
                    }
                    citire(fp,stud);
                    break;
          case 'P': printf("nume student:");gets(s);
                    if((i=cauta(s,stud))<0)
                         printf("nu exista studentul %s in grupa",s);
                    else
                         printf("studentul %s este al %d-lea din grupa",s,i+1);
                    break;
          case 'L': printf("Lista studenti:\n");
                    for(i=0;i<nrstud;i++)
                         printf("%d %s\n",i+1,stud[i]);
                    printf("\n\n media grupei = %4.2f\n\n",medie);
                    break;
          case 'I': printf("terminare program\n");
                    fclose(fp);exit(0);
        } /*switch*/
      } /*while*/
    }

    3.Intr-un fisier de tip text sunt pastrate valorile reale ale unei masuratori sub forma:
    nr_masuratori '\n' val1 '\n' val2 '\n' val3 ...
    Sa se scrie programul care afiseaza numarul de masuratori si valorile respective, dupa care adauga la fisier noi masuratori pina la introducerea valorii 0. Valorile citite se afiseaza in format stiintific.
     

    # include <math.h>
    # include <stdio.h>
    # include <stdlib.h>
    # define MAX  100

    FILE *fp;
    double masur[MAX],mas_noua;
    char nume_fis[12],s[20];
    int nr_mas;

    double convf(char *s){
      double val=0.0,putere;
      int i=0,semn;
      while(isspace(s[i]))
           i++;
      semn=(s[i]=='-')?-1:1;
      if(s[i]=='+'||s[i]=='-')
           i++;
      for(val=0.0;isdigit(s[i]);i++)
          val=10*val+s[i]-'0';
      if(s[i]=='.'){
           i++;
           for(putere=1.0;isdigit(s[i]);i++){
                val=10*val+s[i]-'0';
                putere*=10;
           }
           val/=putere;
      } /*sfirsit parte zecimala*/
      val*=semn;
      if(s[i]=='e' || s[i]=='E'){
         i++;
         semn=(s[i]=='-')?-1:1;
         if(s[i]=='+'||s[i]=='-')
                i++;
         for(putere=0.0;isdigit(s[i]);i++)
                putere=10*putere+s[i]-'0';
                val*=pow10(semn*putere);
      } /*sfirsit parte exponentiala*/
      return val;
    }

    void loadmat(FILE *fp,int *nrm,double *mas){
      int i=0;
      fscanf(fp,"%d",nrm);
      if (*nrm>MAX) *nrm=MAX;
      for(;i<*nrm;i++)
        fscanf(fp,"%lf",&mas[i]);
    }

    void afiseaza(double *mas,int nrm){
      int i;
      for(i=0;i<nrm;i++)
        printf("masuratoarea %d = %6.2e\n",i+1,mas[i]);
    }

    void main(){
      printf("nume fisier:");
      gets(nume_fis);
      if((fp=fopen(nume_fis,"r+"))==0){
         printf("nu exista fisierul\n");
         exit(1);
      }
      loadmat(fp,&nr_mas,masur);
      afiseaza(masur,nr_mas);
      fseek(fp,0L,SEEK_END);
      printf("\nmasuratoarea %d =",++nr_mas);
      while((mas_noua=convf(gets(s))) && nr_mas<MAX-1){
        printf("\nmasuratoarea %d =",++nr_mas);
        fprintf(fp,"%lf\n",mas_noua);
      }
      fseek(fp,0L,SEEK_SET);
      fprintf(fp,"%3d",--nr_mas);
      fclose(fp);
    }

    Sus
    Exercitii

    15.1.Intr-un fisier "cod.dat" este memorata o tabela de codificare, sub forma:
    car_de_codif ' ' car_codif '\n'
     Sa se preia un text din fisierul "dat1.dat", sa se codifice conform codului, iar textul obtinut sa se scrie in fisierul "dat2.txt".

    5.2.Sa se interclaseze continutul a doua fisiere intr-un al treilea fisier. Informatiile dintr-un fisier sunt:
    numarul_de_valori '\n' val1 '\n' val2 '\n'...
    Valorile intregi val1, val2, etc. sunt strict crescatoare. Valorile comune se trec o singura data in fisierul rezultant.

    5.3.Dintr-un fisier se citesc 15 caractere distincte, care codifica cifrele zecimale 0,1,2...9 si operatorii +,-,*,/ si =. Tot din fisier se citeste un sir
    de maxim 80 de caractere, terminat prin caracterul '='si care reprezinta o expresie aritmetica cu operanzi intregi fara semn.
    Se considera expresie corecta cea care satisface urmatoarele conditii:

    • contine numai caractere ale carei coduri au fost citite initial
    • nu contine doi operatori succesivi
    • nu contine impartiri la zero.
    Daca expresia este incorecta se afiseaza un mesaj de eroare corespunzator primei erori intilnite. Daca expresia este corecta se va evalua, efectuind
    operatiile de la stinga la dreapta in ordinea in care apar si se va afisa valoarea calculata codificata conform listei de coduri date.

    5.4.Dintr-un fisier de intrare se citeste o propozitie terminata printr-un punct. Propozitia este formata din cuvinte ce contin doar litere mari. Cuvintele sunt separate prin unul sau mai multi separatori din multimea blanc,'\t','\n'. Stiind ca propozitia are cel mult 30 de cuvinte, sa se afiseze grupurile de cuvinte in care fiecare membru reprezinta anagrama altui membru din grup. Un grup va contine numarul maxim de membrii, iar membrii sunt distincti.

    Sus
    <<Pagina Materiale


    Copyright © 2001-2002. Carmen Holotescu
    All rights reserved. Published by Timsoft