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<stdio.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("%d\n",min(4,34));
return 0;
}
Egy kis körítéssel:
#include <stdio.h>
#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) ) ); // exp - math.h-ból jön - a paraméterben kapott szám a hatványkitevője e-nek
// pow - math.h-ból jön - a paramáterben kapott első számnak a hatványa.
// - a paraméterben kapott második szám a hatványkitevő
return 0;
}
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 <stdio.h>
#include <math.h>
int main() {
printf("MIN(e^3, 3^2):\t%f\n", ((exp(3))<(pow(3, 2))?(exp(3)):(pow(3, 2))) );
return 0;
}
A zárójelek fontosságára az alábbi példa mutat rá:
#include <stdio.h>
#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 MAX( 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));
return 0;
}
Írjuk meg a negyzet(a) makrót!
#include <stdio.h>
#define negyzet(a) (a*a)
int main()
{
int a = 5;
printf("negyzet(%d) = %d",a,negyzet(a));
return 0;
}
Lehetőségünk van makrók segítségével megválasztani, hogy mely programrészek fussanak le és melyek ne.
Az alábbi programban szerepel egy #define, mellyel létrehozzuk a TRIAL_VERSION nevű makrót. Ezután található egy #ifdef parancs mely egy makrót vár közvetlen utána. Abban az esetben, ha a megadott makró létezik, akkor lefut az #ifdef utáni rész. Abban az esetben, ha ez a makró nem létezik, akkor az #else után szerepló kódrészlet fog lefutni. Egy #ifdef parancsot mindig egy #endif kell, hogy zárjon.
#include <stdio.h>
#define TRIAL_VERSION 1
#ifdef TRIAL_VERSION
void calculate(int a,int b)
{
printf("Ez csak próbaverzió! Az összes funkció eléréséhez fizess!\n");
}
#else
void calculate(int a,int b)
{
printf("%d és %d számtani közepe : %f\n",a,b,(float)a/2 + (float)b/2);
}
#endif
int main()
{
calculate(10,20);
return 0;
}
Használható még az #if és #elif parancsok is, melyek az if és else if parancsnak felelnek meg. Valamint az #ifndef parancs, mely alapból egy makró definiálást vár és az utána lévő rész egész a következő #endif-ig lefog futni, ha csak nincs közben (tehát benne) másik, az előbbihez hasonló "if" ág.
Egy C program egy vagy több modulból áll. A modulok valamelyikének tartalmaznia kell a main függvényt, ami továbbra is a program belépési pontja lesz, vagyis ez kezd el végrehajtódni. Minden modul külön file, de függhetnek egymástól. Több modul használata nagy programok esetén szükségszerű. A moduláris programozás lényege, hogy minden modul önálló fordítási egységet képez, melyeknél érvényesül az adatrejtés elve.
Tehát lényegileg több forrásból szeretnénk felépíteni egy programot. Az előállított header fájlokat a program elején tudjuk be include-olni. Így tudjuk elérni a "külső" fájlokban lévő szügkséges kódrészeket.
Az alábbi példa egy 3 fájlból felépülő programot mutat be:
A következő 3 fájl felépítése:
- lib.h : függvények deklarációja, a függvényekhez kommentek - lib.c : a lib.h -ban deklarált függvények implementálása - libmain.c : olyan program, amely használja a "lib" függvénykönyvtárunkat
Elkészítés a következőképpen zajlik:
$ gcc -Wall -pedantic -c lib.c $ gcc -Wall -pedantic -c libmain.c $ gcc -Wall -pedantic -o lm lib.o libmain.o vagy: $ gcc -Wall -pedantic -o lm lib.c libmain.c
==============================================================================
== BEGIN lib.h ===============================================================
#ifndef LIB_H
#define LIB_H 1
/*
* Olyan függvény, mely az első paraméterében kapott sztringet megfordítva
* beleteszi a második paraméterében kapott sztringbe.
* */
void megfordit(char *str, char *forditott);
/*
* Olyan függvény, amely kiszámolja a paraméterében kapott tömb átlagát.
* */
float atlag(int *t, int meret);
#endif
== END lib.h =================================================================
==============================================================================
==============================================================================
== BEGIN lib.c ===============================================================
#include "lib.h"
void megfordit(char *str, char *forditott)
{
int i,j;
for(i=0;str[i]!='\0';i++)
;
i--;
for(j=0;i>=0;--i,j++)
forditott[j] = str[i];
forditott[j] = '\0';
}
float atlag(int *t, int meret)
{
float atlag = 0.0;
int i=0;
while(i<meret)
{
atlag += *(t+i);
i++;
}
atlag /= meret;
return atlag;
}
== END lib.c =================================================================
==============================================================================
==============================================================================
== BEGIN libmain.c ===========================================================
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "lib.h"
int main()
{
char *sz1 = "Discovery Channel";
char *sz2 = (char*)calloc(strlen(sz1)+1,sizeof(char));
int tomb[] = {-2, 10, 23, -45, 67, 0, 0, 34, 99 };
megfordit(sz1,sz2);
printf("%s megfordítva : %s\n",sz1,sz2);
free(sz2);
printf("A tömb átlaga : %f\n",atlag(tomb,9));
return 0;
}
== END libmain.c =============================================================
==============================================================================
Képzeljünk el egy lelátót (legyen ez most nézőtér, pl.: moziban), amely két részre van osztva, középen egy sávval. Mindkét oldal 10x10 helyet tartalmaz. Kirajzolva a képernyőre a teljes lelátót, 1-essel vannak jelölve azok a helyek, amelyek foglaltak, és 0-val azok, amelyek szabadok. A lelátót egy random generátorral töltsük fel [0,1].
1. Rész: Egy barátommal ketten mennénk moziba. Mindketten szeretnénk a belső sávnál ülni, mert középtájról a legjobb a látvány. Úgy szeretnénk helyet fogalalni, hogy ő a nézőtér egyik felén ül a középső sáv mellett, én pedig a másik oldalon, hogy melyik sorban az mindegy. Hány olyan üreshely kombináció van és hol, ahol tudnánk a követelésinknek megfelelően helyet foglalni?
2. Rész: Úgy döntünk, hogy inkább mégse szeretnénk külön oldalon ülni, illetve mindenképp egymás mellé szeretnénk helyet foglalni. Rajzoljuk ki a képernyőre a lelátót olyan formában, hogy 0-val legyen jelölve, ahol van egymás mellett két szabad hely, tehát ide foglalhatunk, és szerepeljen 1-es ott, ahova az előző kritériumok alapján ne foglaljunk jegyet.
Egy lehetséges futási eredmény:
1 0 0 1 0 1 1 1 1 0 1 0 1 0 0 1 1 0 1 1 1 1 1 1 0 1 1 1 1 0 0 0 1 0 1 0 1 1 1 0 0 1 1 0 1 1 0 0 1 1 0 1 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 1 1 0 0 0 1 0 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 0 1 1 1 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 1 1 0 1 1 1 0 1 1 0 1 0 1 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0 1 1 1 1 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 1 Szabad a 2. sor 10. oszlop es a 2. sor 1. oszlop Szabad a 4. sor 10. oszlop es a 4. sor 1. oszlop Szabad a 8. sor 10. oszlop es a 8. sor 1. oszlop 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 1
Egy lehetséges megoldás letöltése .
A házi feladatot megoldani nem kötelező és bemutatni sem kell, viszont a következő gyakorlaton visszakérhető (kikérdezés, táblához hívás, stb. formájában)! Ha a hallgató megoldása ötletes, szép kivitelezésű, plusz pont adható. Amennyiben viszont nem tudja megoldani gyakorlaton a házi feladatban szereplő példákat vagy nem tud válaszolni az azzal kapcsolatban feltett kérdésekre, mínusz pont adható. Plusz és mínusz pontból is egyaránt maximum 10 pontot gyűjthet össze egy-egy hallgató.
A házi feladat és további gyakorló példák elérhetőek a PUB-ban ( /n/pub/ProgramozasAlapjai/Gyakorlat/ )
Bárkinek bármi kérdése adódik a feladatokkal kapcsolatban írjon nyugodtan! ( Gyakoroljatok sokat! )
Téma:
3. - 10. gyakorlat anyaga.
Gyakorlásra:
A honlapomon a 3. - 10. gyakorlathoz tartozó anyag, magyarázatokkal, példákkal.
A gyakorlatok végén lévő házi feladat és gyakorló feladatok megoldása.
A honlapom mellet további feladatok találhatóak a PUB-ban. (/n/pub/ProgramozasAlapjai/Gyakorlat/ - erős átfedés van az "itt" és "ott" található feladatok között).
Egyéb infó:
Előreláthatóan 50 percetek lesz a feladatok megoldására és beadására (tehát 9:00-ig/12:50-ig). A feladatokat a BÍRÓ rendszeren keresztül fogjátok megkapni és beadni is, és az értékelést is a bíró fogja csinálni ott helyben. Tehát egyből látni fogjátok a pontszámokat amiket a bíró adott. Aki késik, az is csak a fenti időintervallum alatt írhatja a ZH-t, mivel a bíró rendszer nyit, majd automatikusan zár is. Hiányozni csak igazolással lehet, de a ZH akkor sem pótolható!
Vissza a lap tetejére.