Informatika2-2013/Osszefoglalas1 6

A MathWikiből
(Változatok közti eltérés)
1. sor: 1. sor:
___NOTOC___
+
__NOTOC__
  
 
== Menetrend ==
 
== Menetrend ==

A lap 2013. április 4., 22:59-kori változata


Menetrend

Most írom a konzultáció feladatát, majd kommentezem is, utána a gyakokról feladatokat oldok meg és kommentezve írom ki ide.

A tervezettbõl eddig kész: 40%

Várható befejezés: 01:30

1. gyakorlat

A gyakorlat elején gcc-vel fordítottunk egy "hello world" programot. Hasznos tudni, hogy hogyan lehet így terminálból fordítani egy C programot.

Majd megtanultuk a Codeblocks / Codelite használatát, ezekbõl nem igazán tudnánk mit visszakérdezni, ezeket a kényelem kedvéért mutattuk meg.

A gyakorlat végén pedig egy nagyon egyszerû kiegészítendõ feladatot oldottunk meg, aminek annyi volt a lényege, hogy lássátok hogyan kell deklarálni változókat (pl: int x;) és hogyan kell használni egyszerû elágazást.

2. gyakorlat

Megtanultuk hogyan lehet scanf-el beolvasni:

int z;
scanf("%d", &z);

Ekkor még nem tudtuk miért kell az & jel a z elé, de mostmár tudjuk, hogy ez azért kellett, hogy a változóba beleírhassa a felhasználó által beírt értéket. Emlékezzük vissza miért nem lehet ezt pointer nélkül megoldani:

void swap(int x, int y){
    int temp = x;
    x = y
    y = temp;
}
 
void swap2(int* x, int* y){
    int temp = *x;
    *x = *y
    *y = temp;
}
 
int main(void){
    int a = 6;
    int b = 8;
    swap(a, b);
    printf("%d %d", a, b); // 6 8-at ír ki
    swap2(&a, &b);
    printf("%d %d", a, b); // 8 6-ot ír ki
    return 0;
}

Itt az elsõ swap függvén igaz úgy tûnik hogy megcseréli a változók értékét, de valójában csak a róluk készült másolatok értéket cserélte meg, és így a main-ben nem történt csere. Viszont a swap2 pointereken keresztül jól megcseréli a valódi a és b változó értékét.

A gyakorlat része volt még a ciklusokkal való ismerkedés:

for(inicializálás; feltétel; inkrementálás){
    utasítások
}
 
while(feltétel){
    utasítások
}
 
do{
    utasítások
} while(feltétel);

A for ciklust sokszor használtuk, tömbökön való végigjáráshoz, leszámolásokhoz, mindenféléhez. while-t kevésbé, de végülis helyettesíthetõ egy for(;feltétel;) ciklussal. do while-t pedig mégkevésbé használtuk, ennek ugye a sajátossága, hogy amikor belép a ciklusba elõször akkor nem ellenõrzi a feltételt, tehát ha egy mindig hamis feltételünk van a ciklus magja akkor is lefut egyszer.

Ciklusokkal megkerestük folyamatosan érkezõ számoknak a minimumát vagy maximumát, ez azon az egyszerû ötleten alapult, hogy mindig mentettük az eddig talált legkisebb számot (minimum esetén) és ezzel hasonlítottuk össze az éppen érkezõt. Majd aszerint hogy kisebb volt az eddigi legkisebbnél a most vizsgált vagy sem, beállítottuk ezt a legkisebbnek, vagy csak mentünk tovább.

3. Gyakorlat

A gyakorlat elején megtudtuk, hogy a változóink végesek, így nem tárolhatunk bennük akármekkora számot.

Írtunk for ciklusokkal pár feladatot, majd áttértünk a gyakorlat anyagára, amik a típusok voltak.

Tömböket is megtanultunk használni, egy egyszerû példa:

#include<stdio.h>
 
int main(void) {
    int t[20];     // Itt hozzuk letre a tombot, elore megadjuk a meretet
    int i;
    t[5] = 5 * 5;             // Igy tudunk egy elemenek erteket adni
    t[6] = t[5] + 11;         // Vagy felhasznalni ertekkent
    for(i = 0; i < 20; i++) { // Ez a ciklus vegzi el a munkankat
        t[i] = i * i;
    }
    return 0;
}

4. Gyakorlat

A gyakorlat két nagyon fontos dolgot vezetett be, a függvényeket és a pointereket.

v_ért fv_név(p_típus1 p_név1, p_típus2 p_név2){
    /*  */
    return érték;
}

Függvényeknek definíciója a visszatérési értékükkel kezdõdik, majd a függvény neve és zárójelben a bemeneti paraméterek. Mint minden blokkal rendelkezõ szerkezetnél itt is kapcsos zárójellel kell elkezdeni és bezárni a blokkot, azaz a függvény magját. Ha a függvényben valahol return-ölünk egy értéket, a függvény visszatér, kilép, azaz a return utáni rész már nem fut le. Ezért az alábbi két függvény ekvivalens:

int fv(int a){
    if(a < 0){
        return -a;
    }
    else{
        return a;
    }
}
 
int fv2(int a){
    if(a < 0){
        return -a;
    }
    return a;   // Ez csak akkor fut le ha az if feltétele hamis volt, mert különben a függvény visszatér -a-val
}

Függvényeket lehet értékként is használni, így ha van egy átlag függvényünk, nem kell külön változóba elmenteni az általa visszaadott értéket:

printf("%lf", atlag(3.2, 6));

Pointerekrõl már írtam korábban, amit még megemlítenék, hogy a tömbök pointerek és a pointerek tömbök. Így ha t egy tömb vagy pointer, akkor t[0] és *t ekvivalens, továbbá, ha létezik i. indexû eleme, akkor t[i] és *(t+i) is ekvivalensek.

5. Gyakorlat

A gyakorlat elsõ felében dinamikus memóriakezelésrõl volt szó. Korábban csak fix méretû tömböket tudtunk létrehozni:

int t[20];

Ha dinamikusan foglalunk le memóriát akkor bármilyen pozitív egész változó méretû tömböt lefoglalhatunk:

int m;          // ebbe olvassuk be a tömb méretét
scanf("%d",&m);  
int *vec = (int *)malloc(m * sizeof(int)); // itt foglaljuk le a memóriát a tömbnek

Itt még megemlíteném, hogy igaz gyakorlatokon csak a malloc-ot használtuk, így a többit nem fogjuk kérdezni gyakorlati feladatokban. De elméleti feladatba bõven belefér pl, hogy mire való a calloc, realloc stb.

A gyakorlat másik felében raktár kezelõ függvényeket írtunk, ezeknek a megoldása megtalálható a megfelelõ házifeladat oldalán.

6. Gyakorlat

A gyakorlat 3 dologról szólt, file kezelés, argumentumok és struktúrák.

A file kezelést nem nehéz elsajátítani, ha a scanf és printf-ekkel már tisztában van az ember:

FILE* fp;            // Letrehozzuk a file pointerunket
fp = fopen("test.txt", "w");  // Megnyitjuk a test.txt-t irasra

Ezek után a sorok után használhatjuk az fprintf függvényt, hogy írjunk a test.txt file-ba. Ha olvasni szeretnénk egy file-ból akkor a "w" helyett "r"-et írjuk, ekkor az fscanf használható. Ha nem szeretnénk felülírni a file-t akkor használhatjuk az "a"-t, ami a file végére ír.

fprintf(fp, "Most irunk a file-ba.\n");

Ha "r"-el van megnyitva:

fscanf(fp, "%d", &z);         // Kiolvasunk a file-bol egy int-et

Az argumentum kezelésrõl a módosított main függvény fejét mindenképp érdemes megjegyezni:

int main(int argc, char* argv[])

Ha így definiáljuk a main függvényt, akkor argv[0]-ban a program neve lesz, argv[1]-tõl pedig a programnak adott argumentumok találhatók. Ha pl "./prog_neve teszt 20" paranccsal futtatjuk a prog_neve nevû programunkat, akkor az argv[1] a teszt string lesz, az argv[2] pedig a 20 string, tehát nem a 20 szám, hogy számként használhassuk az atoi függvényt kell rá használnunk:

int m = atoi(argv[2]);

Az argc-ben amit igazából nem használtunk az argumentumok száma szerepel, szóval az elõzõ példában pl 2.

A gyakorlat vége struktúrákról és a typedef-rõl szólt.

typedef int egesz;

Ezután a sor után használhatjuk az egesz kifejezést bárhol int helyett, pl:

egesz i;
egesz n;

Struktúrák több változót zárnak egységbe, például létrehozhatunk egy dátum változót, amiben tároljuk az évet, hónapot és napot:

struct Datum{
    int ev;
    int honap;
    int nap;
};

Ezután a következõ képpen hozhatunk létre egy ilyen változót és állíthatjuk be az adattagjait:

struct Datum d1;
d1.ev = 2013;
d1.honap = 4;
d1.nap = 4;

Amint látható a struct kulcsszót is ki kell írni mikor deklarálunk egy változót, ezt nem igazán szeretjük, így typedef-el szoktuk "megjavítani", az elõzõ struktúra definíció helyett:

typedef struct{
    int ev;
    int honap;
    int nap;
} Datum;

Ezután létrehozható Datum változó és ugyanúgy mûködik mint korábban:

Datum d1;
d1.ev = 2013;
d1.honap = 4;
d1.nap = 4;

Ami a typedef-nél történik, hogy azt az egész struktúrát nevezzük el Datum-nak, pont mint amikor az int-et neveztük el egesz-nek.

A gyakorlat végén egy Vektor struktúrával dolgoztunk, írtunk hozzá függvényeket, a házi is errõl szólt, így a kapcsolódó házi oldalán megtalálható pár függvény megoldása.


Konzultáció feladat

Személyes eszközök