Programozás alapjai gyakorlat 2014-2015/1

12. gyakorlat



    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 <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 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));

    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;
}


    IF-ELSE kicsit másképp

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.



    Modulok

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 =============================================================
==============================================================================




Jövő héten - 2014.11.24. - NagyZH!!!

Egész órán (135 perc). Az előre kiadott feladatokból kap mindenki egyet.

A bírón mindenkinek van 3-3 darab feltöltési lehetősége mind a 10 feladathoz, 2014.11.23. 23:59:59-ig .




MarkMyProfessor

A MarkMyProfessor egy weboldal, ahol oktatókat lehet értékelni. Van egy ETR-es értékelés is, de azt ki tudja mikor kapom meg, illetve sokan nem hisznek az ETR-en keresztül történő anoním értékelésben ("nem is értem miért").

Az alábbi linken elérhető az én adatlapom is. Itt az első értékelőnek létre kell hozni a tanított tárgyakhoz a "Programozás alapjai"-t (és persze utána értékelni), a többieknek már csak ki kell választani és értékelni.

Pl.: ilyen és ehhez hasonló érvek alapján: megtartottam-e az órákat, értelmesen adtam-e elő, tudtam is az anyagot vagy csak össze vissza beszéltem, lehetett-e kérdezni, tudtam-e válaszolni a kérdésekre, igyekeztem-e segítséget nyújtani ZH-kon, mennyire voltam segítőkész órákon/órák után/hét közben, válaszoltam-e az email-ekre, mennyire voltak élvezhetőek az órák, mennyire voltam jó arc, stbstb..

Szeretném kérni, hogy a szöveges megjegyzéshez is írjatok valamit, mivel csak úgy van igazán értelme, a számok nem sokat mondanak. :)


     Vissza a lap tetejére.