Függvény pointer Több feladat közül futási időben döntöm el, hogy melyiket hajtom végre. A függvényre mutató pointer a függvény kódjának a címére mutat, azon keresztül meghívhatom a függvényt. A pointernek tudnia kell a függvény típusát (paraméterek és visszatérési érték típusa). Pl.: double fgv(double, double); /* függvény deklarációja */ double (*fptr)(double, double); /* ilyen típusú függvényre mutató pointer deklarációja */ fptr = fgv; /* a függvény nevét adom kezdőértékül, a fordító persze ebből címet állít elő */ fptr(x, y); /* meghívom a függvényt a pointeren keresztül */ Feladat: Egy tömbben soroljunk fel függvényeket, és hívjuk meg valahányszor.
#include <math.h> /* sinus négyzet - beépített függvénnyel */ double sin2(double x) double sinx = sin(x); return sinx*sinx; /* kettes alapú logaritmus - beépített függvénnyel */ double log2(double x) return log(x) / log(2); /* cosinus négyzet - beépített függvénnyel */ double cos2(double x) double cosx = cos(x); return cosx*cosx; typedef double (*fgvtip)(double); /* függvényre mutató pointer típusa */ /* melynek double a visszatérési értéke és double típust vár a paraméterlistában */ fgvtip tabla[] = /* ilyen pointerek tömbje */ sin2, /* a függvény neve értékül adható függvényre mutató pointernek */ log2, cos2 ; int main() int f, x; char* valasztek = " 1: sin2x \n 2: log2x \n 3: cos2x \n"; /* karakterekre mutató pointer, lényegileg egy string */ printf("melyik fuggveny legyen?:\n%s?:\t", valasztek); scanf("%d", &f); printf("argumentum erteke?:\t"); scanf("%d", &x); printf("a fuggveny erteke az adott pontban:\t%lf\n", tabla[f-1](x) ); /* a tömbben lévő pointeren keresztül hívom a függvényt */ /* 1-től 3-ig várt bemenetet a program. 0-tól való indexelés miatt levon 1-et [f-1] és paraméterként átadódik az úgyszint beolvasott érték (x) */
Feladat: Egy tömbbe olvassunk be, majd írassuk ki az elemeket úgy, hogy a tömb bejárását egy függvény végezze, ami megkapja a műveletet. #define N 10 typedef void (*muvelettipus)(int*); /* függvényre mutató pointer típusa */ /* melynek nincs visszatérési értéke (void) és int-re mutató pointert vár a paraméterlistában */ /* egy tömböt vár illetve a bejar függvény alatt található művelet függvények egyikét */ void bejar(int* tomb, muvelettipus muvelet) int i; for(i=0; i<n; i++) (*muvelet)(tomb+i); // ide kerül behelyettesítésre a paraméterként kapott művelet-függvény, mely saját bemeneti paraméterét is megkapja. // azért kerül 'tomb+i' a paraméterlistába, mert a 'tomb' alapjáraton a paraméterként kapott tömb kezdőpozíciójára mutat, // így a for ciklusban végig haladva, mindig i-t hazzáadva mindig a tömb rákövetkező elemét kapjuk void beolvas(int* v) scanf("%d", v); void kiir(int* v) printf("%d\n", *v); void duplaz(int* v) (*v) *= 2; int main() int t[n]; bejar(t, beolvas); bejar(t, kiir); bejar(t, duplaz); bejar(t, kiir);
Parancssori paraméterek A main függvénynek három paramétere lehet. Az első egy int, a parancssorban kapott argumentumok száma + 1 (a program neve maga is egy argumentum). A második egy olyan pointer-tömb, mely azokra a memóriaterületekre mutat, ahol sztringként vannak letárolva a parancssori argumentumok. A harmadik hasonló a másodikhoz, csak ez a környezeti változók címeit tartalmazza. Feladat: Írjuk ki a parancssorban lévő argumentumokat. main(int argc, char **argv) // vagy így is lehet az argv-t deklarálni: // main(int argc, char *argv[]) int i; printf("argc = %d\n\n",argc); for (i=0; i<argc; ++i) printf("argv[%d]: %s\n", i, argv[i]); Majd fordítsuk le, és futtassuk az alábbi módon: $ gcc -o arg arg.c $./arg alma korte szilva barack palinka argc = 6 argv[0]:./arg argv[1]: alma argv[2]: korte argv[3]: szilva argv[4]: barack argv[5]: palinka Feladat: Írj egy programot, mely összeadja a parancssori paramétereket.
#include <stdlib.h> int main(int argc, char* argv[]) int i; int arg = 0; printf("osszesen %d programargumentumot kaptam!\n",argc); for(i = 0; i< argc; i++) printf("%d : %s\n",i, argv[i]); if(argc > 1) for(i = 1; i< argc; i++) arg += atoi(argv[i]); printf("az argumentumok osszege : %d\n", arg); Feladat: Írj egy programot, amely n-szer egymás után fűzi ugyanazt az s sztringet, ahol n és s is parancssori paraméter.
#include <stdlib.h> #include <string.h> int main(int argc, char* argv[]) int i; char *er; if(argc < 3) printf("használat: %s <valami szám> <valami sztring>\n", argv[0]); return 1; er = (char*) calloc ( atoi(argv[1]) + 1, strlen(argv[2]) ); strcpy(er,argv[2]); for(i=0;i<atoi(argv[1])-1;i++) strcat(er,argv[2]); printf("%s\n",er); free(er); Makrók A #define direktívákat arra használjuk, hogy "beszédes" azonosítókkal lássunk el C konstansokat, kulcsszavakat, illetve gyakran használt utasításokat és kifejezéseket. A makrónevekre ugyanaz a képzési szabály vonatkozik, mint más azonosítókra. A makróneveket csupa nagy betűvel ajánlott írni, hogy a szövegben elkülönüljenek a programban használt azonosítóktól. Az alábbi program meghatározza két szám közül, hogy melyik a kisebb. #include <math.h> #define min(x,y) ((X)<(Y)?(X):(Y)) // makró - paraméterben kaphat két számot. A visszatérési értéke az utóbbi zárojelben lévő kiértékelés eredménye int main() printf("min(e^3, 3^2):\t%f\n", min( exp(3), pow(3, 2) ) ); - a paraméterben kapott szám a hatványkitevője e-nek a paramáterben kapott első számnak a hatványa. a paraméterben kapott második szám a hatványkitevő // exp - math.h-ból jön // pow - math.h-ból jön - // -
Az előfeldolgozó (preprocesszor) minden programsort átvizsgál, hogy az tartalmaz-e valamilyen korábban definiált makrónevet. Ha igen, akkor azt lecseréli a megfelelő helyettesítő szövegre, majd halad tovább a vizsgálattal. A preprocesszálás eredménye megtekinthető (mindig a frissen létrejövő *.i fájl végén található a saját kódunk - ez a mi esetünkben az utolsó 4 sor): gcc -E makrofgv.c tail -4>makrofgv.i Használat függvényen belül: #include <math.h> int main() printf("min(e^3, 3^2):\t%f\n", ((exp(3))<(pow(3, 2))?(exp(3)):(pow(3, 2))) ); A zárójelek fontosságára az alábbi példa mutat rá: #define MAX(a,b) (((a) > (b) )? (a) : (b)) #define MIN(a,b) (((a) > (b) )? (b) : (a)) #define MIN3(a,b,c) (((a) < (b))? MIN(a,c) : MIN(b,c)) /* * MINDENT zárójelezni kell, ugyanis ha így írnánk: * #define MAX(a,b) a > b? a : b * * akkor MIN( a-3, a?1:3 ) esetén az eredmény: * a-3 > a?1:3? a-3 : a?1:3, ami nem az, amit szeretnénk! * */ int main() int a,b,c; a = -23; b = 44; c = 0; printf("max(%d,%d)=%d\n",a,b,max(a,b)); printf("min(%d,%d)=%d\n",b,c,min(b,c)); printf("min3(%d,%d,%d)=%d\n",a,b,c,min3(a,b,c)); Írjuk meg a negyzet(a) makrót!
#define negyzet(a) (a*a) int main() int a = 5; printf("negyzet(%d) = %d",a,negyzet(a));