Capitolul 5.12. Pointeri pe functii

Vezi subiectul anterior Vezi subiectul urmator In jos

Capitolul 5.12. Pointeri pe functii

Mesaj  zooky la data de Mier Mar 18, 2009 1:51 pm

In C functia in sine nu este o variabila, dar exista posibilitatea de a defini un pointer pe o functie, care poate fi manipulat, transmis functiilor, plasat in tablouri etc. Vom ilustra aceasta modificind procedura de sortare scrisa mai anterior in acest cap, in asa fel incit fiind dat argumentul optional-n sa se sorteze liniile input memorie, nu linii copiate.
De obicei, un sort consta in trei parti-o comparatie care realizeaza ordonarea oricarei perechi de obiecte, o schimbare, prin care se inverseaza oridinea obiectelor si un algoritm de sortare care face comparatii si schimbari pina cind obiectele sint definitiv ordonate. Algoritmul de sortare este independent de operatiile de comparare si schimbare, astfel incit prin transmiterea functiei de comparare si schimbare catre el, se va putea realiza sortarea pe diferite criterii. Acest lucru ni-l propunem in noul sort.

Compararea lexicografica a doua linii este realizata prin strcmp iar schimbarea prin swap; avem nevoie de o rutina numecmp care compara doua linii pe baza valorilor numerice si returneaza un indice de conditie de acelasi fel ca si strcmp.
Aceste trei functii sint declarate in main iar pointerii pe ele sint transmisi la sort. Sort la rindul sau apeleaza functiile prin sort, la rindul sau apeleaza functiile prin pointeri. Am sarit peste procesul de tratare a arguentelor eronate, concentrindu-ne astfel pe rezolvarea problemelor principale.

#define LINES 1000 /* maximum de linii de sortat */
main(argc, argv) /* sortarea linii input */
int argc;
char *argv[];
{
char *lineptr[LINES]; /* pointeri pe liniile de text */
int nlines; /* nr linii-input citire */
int strcmp(), numecmp(); /* fc de comparare */
int swap(); /* fc de schimbare */
int numeric = 0; /* 1 daca este sort numeric */
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'n')
numeric = 1;
if ((nlines = readlines(lineptr, LINES)) >= 0)
{
if (numeric)
sort(lineptr, nlines, numecmp, swap);
else
sort(lineptr, nlines, strcmp, swap);
writelines(lineptr, nlines);
} else
printf("intrare prea mare pentru sort\n");
}

strcmp, numecmp si swap sint adrese de functii; din moment ce ele sint cunoscute ca fiind functii, operatorul & nu este necesar la fel cum el nu este necesar inaintea numelui unui tablou. Compilatorul este cel care rezolva transmiterea adresei functie.
Al doilea pas este modificarea lui sort:

sort(v, n, comp, exch)
/* sorteaza sirurile v[0]. . . v[n-1] */
char *s[];
int n;
int (*comp)(), (*exch)();
{
int gap, i, j;
for (gap = n/2; gap > 0; gap /= 2)
for (i = gap; i < n; i++)
for (j = i - gap; j >= 0; j -= gap)
{
if ((*comp)(v[j], v[j+gap]) <= 0)
break;
(*exch)(&v[j], &v[j+gap]);
}
}

Declaratiile vor fi studiate cu grija.

int (*comp)()

spune ca comp este un pointer pe o fc ce returneaza un int. Primul set de paranteze este necesar; fara ele

int *comp()

ar spune ca cmp este o functie ce returneaza un pointer pe un integer, ceea ce este cu totul altceva. Utilizarea lui comp in linia

if ((*comp)(v[j], v[j+gap]) <= 0)

este comparabila cu declaratia potrivit careia cmp este u pointer pe o functie; *comp este functie, iar

(*comp)(v[j], v[j+gap])

este apelul ei. Parantezele sint necesare pentru asocierea corecta a componentelor.
Am ilustrat deja prin strcmp compararea a doua siruri.
Iata numecmp care compara doua siruri numerice pe baza valorii numerice:

numcmp(s1, s2) /* compara numeric s1 cu s2 */
char *s1, *s2;
{
double atof(), v1, v2;
v1 = atof(s1);
v2 = atof(s2);
if (v1 < v2)
return(-1);
else if (v1 > v2)
return(1);
else
return(0);
}

Pasul final este adaugarea functiei swap care schimba doi pointeri. Aceasta este adoptata direct din ceea ce am prezentat mai devreme in acest capitol.

swap(px, py) /* interschimba *px si *py **/
char *px[], *py[];
{
char *temp;
temp = *px;
*px = *py;
*py = temp;
}

Exista o varietate de alte optiuni care pot fi adaugate la programul de sortare; unele dintre ele pot fi reincercate ca exerctii.

Exercitiul 5.11. Modificati sort in asa fel incit sa gestioneze un flag, -r care indica sortarea in ordine inversa (descrescatoare). Bineinteles -r trebuie sa fie compatibil cu -n.

Exercitiul 5.12. Adaugati optiunea -n pt a prelucra impreuna literele mari si literele mici adica sa nu se mai faca distinctia intre aceste doua tipuri de caractere grafice intimpul sortarii; datele cu litere mari si cee cu litere mici sint sortate impreuna, in asa fel incit a si A apar adiacent, nu separate prin intregul alfabet al literelor mici sau mari.

Exercitiul 5.13. Adaugati optiunea -d ("ordinea din dictionar") care realizeaza comparari doar pentru litere, numere si flancuri. Asiguarti-va ca -d merge impreuna cu -f.

Exercitiul 5.14. Adaugati o faclitatea legata de gestionarea cimpurilor, in asa fel incit sortarea sa poata fi facuta pe cimpuri si interiorul liniilor, fiecare corespunzind unui set independent de optiuni. (Indexul acestei carti fost sortat cu -df pt ordinea alfabetica si cu -n pentru paginilor.)
avatar
zooky
Moderator
Moderator

Numarul mesajelor : 147
Data de inscriere : 15/03/2009
Varsta : 24
Localizare : Cernatesti City

Vezi profilul utilizatorului http://e-learning.forumhit.ro

Sus In jos

Vezi subiectul anterior Vezi subiectul urmator Sus


 
Permisiunile acestui forum:
Nu puteti raspunde la subiectele acestui forum