Documente Academic
Documente Profesional
Documente Cultură
Limbajul C
CURS 10
Pointeri la funcii Fiiere text
Pointeri la funcii
Problem: funcie care s poat apela o funcie cu nume necunoscut, dar cu prototip i efect cunoscut. Exemple:
Funcie care s sorteze un vector tiind funcia de comparare a dou elemente ale unui vector. Funcie care s determine o rdcin real a oricrei ecuaii (neliniare). Funcie "listf" care poate afia (lista) valorile unei alte funcii cu un singur argument, ntr-un interval dat i cu un pas dat.
int main () { listf (sin, 0., 2*M_PI, M_PI/10.); listf (exp,1., 20., 1.); return 0; }
Programarea calculatoarelor
Observaii
Prin convenie, n limbajul C, numele unei funcii nensoit de o list de argumente (chiar vid) este interpretat ca un pointer ctre funcia respectiv (fr a se folosi operatorul de adresare '&')! "sin" este adresa funciei "sin(x)" n apelul funciei "listf". O eroare de programare care trece de compilare i se manifest la execuie este apelarea unei funcii fr paranteze; compilatorul nu apeleaz funcia i consider c programatorul vrea s foloseasc adresa funciei! Exemplu: if ( test ) break; // gresit, echiv. cu if (1) break; if ( test() ) break; // iesire din ciclu daca funcia test intoarce true
Programarea calculatoarelor
Definirea funciei "listf": void listf (double (*fp)(double), double min, double max, double pas) { double x, y; for (x=min; x<=max; x=x+pas) { y=fp(x); // sau: y=(*fp)(x); printf ("\n%20.10lf %20.10lf, x, y); } }
Programarea calculatoarelor
Observaii
Parantezele sunt importante, deoarece absena lor modific interpretarea declaraiei: Declaraie funcie cu rezultat pointer, nu pointer la funcie!! tip * f (lista_arg_formale) Pentru a face programele mai explicite se pot defini nume de tipuri pentru tipuri pointeri la funcii, folosind declaraia typedef. typedef double (* ftype) (double); void listf (ftype fp, double min, double max, double pas) { double x, y; for (x=min; x<=max; x=x+pas) { y = fp(x); printf ("\n%20.10lf %20.10lf, x,y); } }
Programarea calculatoarelor
Funcii callback
O funcie C transmis, printr-un pointer, ca argument unei alte funcii F se numete i funcie callback, pentru c ea va fi apelat napoi de funcia F. De obicei, funcia F este o funcie de bibliotec, iar funcia C este parte din aplicaie. Funcia F poate apela o diversitate de funcii, dar toate cu acelai prototip, al funciei C.
Programarea calculatoarelor
Exemplu
program cu meniu de opiuni; operatorul alege una din funciile realizate de programul respectiv:
#include<stdio.h> #include<stdio.h> typedef void (*funPtr) (); // funcii ptr. operatii realizate de program void unu () { printf ("unu\n"); } void doi () { printf ("doi\n"); } void trei () { printf ("trei\n"); }
Programarea calculatoarelor
Exemplu - continuare
// selectare i apel funcie int main () { funPtr tp[ ]= {unu,doi,trei}; // vector de pointeri la funcii short option=0; do { printf(Optiune (1/2/3):); scanf ("%hd", &option); if (option >=1 && option <=3) tp[option-1](); // apel funcie (unu/doi/trei) else break; } while (1); return 0; }
Programarea calculatoarelor
Exemplu - observaie
Secvena echivalent (cu switch) este : do { printf(Optiune (1/2/3):); scanf ("%hd", &option); switch (option) { case 1: unu(); break; case 2: doi(); break; case 3: trei(); break; } } while (1);
Programarea calculatoarelor
Directive preprocesor
sunt interpretate ntr-o etap preliminar compilrii (traducerii) textului C, de un preprocesor nu se foloseste caracterul ; pentru terminarea unei directive! #define ident text inlocuiete toate apariiile identificatorului ident prin irul text #define ident (a1,a2,...) text definete o macroinstructiune cu argumente #include fiier include n compilare coninutul fiierului sursa fiier #if expr compilare condiionat de valoarea expresiei expr #if defined ident compilare condiionat de definirea unui identificator (cu #define) #endif terminarea unui bloc introdus prin directiva #if
Programarea calculatoarelor
Fiier
Colecie de date memorate pe un suport extern (floppy, harddisk, etc) identificat printr-un nume. Entiti ale sistemului de operare: numele lor respect conveniile sistemului, fr legtur cu un limbaj de programare anume Coninutul:
texte (ex. programe surs) numere alte informaii binare: programe executabile, numere n format binar, imagini sau sunete codificate numeric s.a.
Numrul de elemente ale unui fiier este variabil (poate fi nul). Se folosesc pentru
date iniiale sau rezultate mai numeroase pstrarea permanent a unor date de interes pentru anumite aplicaii
Programarea calculatoarelor
Operarea cu fiiere
De obicei "fiier" = fiier disc (pe suport magnetic sau optic) Noiunea de fiier este mai general i include orice flux de date (stream) din exterior spre memorie sau dinspre memoria intern spre exterior. Stream (flux de date, canal) sinonim cu file (fiier): pune accent pe aspectul dinamic al transferului de date Programatorul se refer la un fiier printr-o variabil; tipul acestei variabile depinde de limbajul folosit i chiar de funciile utilizate (n C). Asocierea dintre numele extern (un ir de caractere) i variabila din program se face la deschiderea unui fiier, printr-o funcie standard.
Programarea calculatoarelor
Tipuri de fiiere n C
Fiiere text
conin o succesiune de linii, separate prin NewLine fiecare linie are 0 sau mai multe caractere tipribile i/sau tab
Fiiere binare
conin o succesiune de octei
Programarea calculatoarelor
Fiiere text
Caracter terminator de linie: fiierele Unix/Linux: un singur caracter terminator de linie \n fiierele Windows i MS-DOS: caracterele \r i \n (CR,LF) ca terminator de linie Un fiier text poate fi terminat printr-un caracter terminator de fiier (Ctrl-Z = EOF = -1) nu este obligatoriu acest terminator Sfritul unui fiier disc poate fi detectat i pe baza lungimii fiierului (numr de octei), memorat pe disc. Se realizeaz conversia automat din/n format extern (ir de caractere) n/din format intern (binar virgul fix sau virgul mobil)
Programarea calculatoarelor
Fiiere binare
Pot conine
numere n reprezentare intern (binar) articole (structuri de date) fiiere cu imagini grafice, n diverse formate, etc
Citirea i scrierea se fac fr conversie de format. Pentru fiecare tip de fiier binar este necesar un program care s cunoasc i s interpreteze corect datele din fiier (structura articolelor). Este posibil ca un fiier binar s conin numai caractere, dar funciile de citire i de scriere pentru aceste fiiere nu cunosc noiunea de linie; ele specific un numr de octei care se citesc sau se scriu la un apel al funciei fread sau fwrite.
Programarea calculatoarelor
Operarea cu fiiere
1. se definete o variabil de tip FILE * pentru accesarea fiierului; FILE * un tip structur definit n stdio.h conine informaii referitoare la fiier i la tamponul de transfer de date ntre memoria central i fiier (adresa, lungimea tamponului, modul de utilizare a fiierului, indicator de sfrit, de poziie n fiier) 2. se deschide fiierul pentru un anumit mod de acces, folosind funcia de biblioteca fopen, care realizeaz i asocierea ntre variabila fiier i numele extern al fiierului 3. se prelucreaz fiierul - citire/scriere cu funciile specifice 4. se nchide fiierul folosind funcia de biblioteca fclose.
Programarea calculatoarelor
Sistemele MS-DOS i MS-Windows nu fac deosebire ntre litere mari i litere mici, n cadrul numelor de fiiere Atenie! pentru separarea numelor de cataloage dintr-o cale se vor folosi:
"\\", pentru a nu se considera o secven de caractere "Escape" sau caracterul /. char *numef = "C:\\WORK\\T.TXT"; char *numef = c:/work/t.txt;
Programarea calculatoarelor
Atenie!
nchiderea unui fiier disc este absolut necesar pentru fiierele n care s-a scris ceva! Poate lipsi dac s-au fcut doar citiri din fiier!
Programarea calculatoarelor
Exemplu
#include <stdio.h> int main ( ) { FILE * f; // pentru referire la fiier // deschide un fiier text ptr citire f = fopen ( c:\\t.txt", "rt ); printf ( f == NULL ? "Fiier negasit" : " Fiier gasit"); if (f) // dac fiier existent fclose(f); // nchide fiier return 0; }
Programarea calculatoarelor
Exemplu: scriere sub form de litere mici caracterele dintr-un fiier n alt fiier
numele sursei i destinaiei transmise n linia de comand. #include<stdio.h> #include<ctype.h> int main(int argc, char** argv){ FILE * f1, * f2; int ch; f1= fopen (argv[1], "r"); f2= fopen (argv[2], "w"); if ( f1==0 || f2==0) { puts (" Eroare la deschidere fiiere \n"); return 1;} while ( (ch=fgetc(f1)) != EOF) // citeste din f1 fputc ( tolower(ch),f2); // scrie n f2 fclose(f1); fclose(f2); return 0; } Lansarea n execuie a programului: copiere fiier_sursa.dat fiier_dest.dat
Programarea calculatoarelor
int fprintf (FILE *fp, const char *format,...) identic cu printf cu deosebirea c scrie ntr-un fiier. int fscanf (FILE *fp, const char *format,...) realizeaz citirea cu format dintr-un fiier; analog scanf Exemplu: int a; float b; fscanf ( fp, %d%f ,&a, &b); fprintf ( fp, a= %d \t b=%f \n, a, b);
Programarea calculatoarelor
Programarea calculatoarelor
Exemplu
ntr-un fiier de tip text sunt pstrate valorile reale ale unei msuratori sub forma:
nr_msuratori val1 val2 val3 ...
A) S se scrie programul care afieaz numrul de msurtori i valorile respective. B) Se vor aduga la fiier noi msuratori pn la introducerea valorii 0.
Programarea calculatoarelor
Rezolvare
# include <math.h> # include <stdio.h> # include <stdlib.h> # include <ctype.h> # define MAX 100
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 loadmas (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]); Programarea calculatoarelor }
Rezolvare
int main(){ FILE *fp; double masur[MAX], mas_noua=1; char nume_fis[12]; int nr_mas; printf ("nume fisier:"); gets (nume_fis); if ( (fp = fopen(nume_fis, "r+") ) == 0 ){ printf ("nu exista fisierul\n"); exit (1); } loadmas (fp,&nr_mas,masur); afiseaza (masur,nr_mas); fclose(fp); if ( (fp = fopen(nume_fis, a") ) == 0 ){ printf ("nu exista fisierul\n"); exit (1); }
Programarea calculatoarelor
Rezolvare
printf ("\nmasuratori noi:\n); while( nr_mas++<MAX-1){ scanf(%lf,&mas_noua); if(mas_noua) fprintf (fp, "%lf\n", mas_noua); else break; } fclose(fp); if ( (fp = fopen(nume_fis, "r+") ) == 0 ){ printf ("nu exista fisierul\n"); exit (1); } fprintf (fp, "%d", --nr_mas); fclose (fp); return 0; }
Programarea calculatoarelor
Exerciii
Program pentru numrarea liniilor i cuvintelor dintr-un fiier text printr-o singura parcurgere. Cuvintele sunt iruri de orice caractere separate ntre ele prin (oricte) spaii albe. Hint: Se poate folosi funcia de biblioteca "strtok".
Programarea calculatoarelor
Rezolvare tema
//converteste de la sir de caractere la nr real dubla precizie
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;
Programarea calculatoarelor
Rezolvare tema
if (s[i]=='.') { i++; for (putere=1.0; isdigit(s[i]); i++) { val = val + (s[i]-'0)/putere; putere *= 10; } } /*sfirsit parte zecimala*/ val *= semn; return val; }
Programarea calculatoarelor