C nyelven a struktúra (struct) típus több tetszőleges típusú objektum együttese (kivéve a void és a függvény típust). Ezek az objektumok önálló, a struktúrán belül érvényes nevekkel rendelkeznek.
A struktúra szerkezetét meghatározó deklaráció általános formája:
struct struktúra_azonosító { típus1 tag1; típus2 tag2; ... típusN tagN; };
A fenti típussal változót az alábbi módon készíthetünk:
struct struktúra_azonosító struktúra_változó;
Példa: Könyvtárkezelő program készítése során jól alkalmazható az alábbi adatstruktúra:
struct book { char szerzo[20]; char cim[40]; int ev; int ar; };
Változók létrehozása:
struct book macska, gyerek, cprog;
Elég gyakran alkalmazott megoldás a typedef kulcsszóra épül:
typedef struct book { char szerzo[20]; char cim[40]; int ev; int ar; } BOOK;
Változók létrehozása:
BOOK macska, gyerek, cprog;
Egy komolyabb példa:
F: Hozz létre típust egy háromdimenziós térbeli pozíció tárolására. Ezt felhasználva hozz létre egy típust, ami részecskék helyzetét, tömegét, nevét és töltését (pozitív/negatív/semleges) tárolja. Készíts egy függvényt, ami két részecskéről eldönti, hogy melyik nehezebb, és egy másikat, ami megmondja, hogy elektromosan vonzzák vagy taszítják egymást, esetleg nem hatnak egymásra. Inicializálj két részecskét, és használd a függvényeket. ============================================================================== #include <stdio.h> typedef struct { double x, y, z; } pozicio; typedef char nevtipus[30]; typedef enum {negativ = -1, semleges, pozitiv} toltestipus; typedef struct { pozicio helyzet; double tomeg; nevtipus nev; toltestipus toltes; } reszecske; int tomeghasonlitas(reszecske a, reszecske b) { if(a.tomeg < b.tomeg) { return -1; } if(a.tomeg > b.tomeg) { return 1; } return 0; } int vonzas(reszecske a, reszecske b) { if(a.toltes==semleges || b.toltes==semleges) { return 0; } return (a.toltes==b.toltes)?1:-1; } int main() { reszecske p={{0.0, 0.0, 0.0}, 1.0, "proton", pozitiv}; reszecske e={{1.0, 1.0, 1.0}, 0.001, "elektron", negativ}; printf("tomeg: %d\nvonzas: %d\n", tomeghasonlitas(p, e), vonzas(p, e)); return 0; }
F: Adott a síkon 3 pont, mi az általuk meghatározott háromszög területe? ============================================================================== #include <stdio.h> #include <math.h> struct pont { float x; float y; }; float tav(struct pont P, struct pont Q) { return sqrtf((P.x-Q.x)*(P.x-Q.x) + (P.y-Q.y)*(P.y-Q.y)); } int main() { struct pont A, B, C; float a,b,c,s; scanf("%f %f", &A.x, &A.y); scanf("%f %f", &B.x, &B.y); scanf("%f %f", &C.x, &C.y); a=tav(B, C); b=tav(A, C); c=tav(A, B); s=(a+b+c)/2; printf("Terulet: %f\n", sqrtf(s*(s-a)*(s-b)*(s-c))); }
F: Készítsünk komplex számok tárolására alkalmas adatszerkezetet (egész komponensekkel). Készítsünk továbbá olyan függvényeket, melyek feladata: - kiír egy komplex számot az stdout-ra, - összead két komplex számot, és visszaadja az eredményt - összeszoroz két komplex számot, és visszaadja az eredményt ============================================================================== == BEGIN komplex.c =========================================================== #include <stdio.h> typedef struct komplex { int real; int imag; } komplex; komplex add(komplex k1, komplex k2) { komplex e; e.real = k1.real+k2.real; e.imag = k1.imag+k2.imag; return e; } komplex mul(komplex k1, komplex k2) { komplex e; e.real = k1.real*k2.real-k1.imag*k2.imag; e.imag = k1.imag*k2.real+k1.real*k2.imag; return e; } void printk(komplex k) { printf("(%d%+di)\n", k.real, k.imag); } int main() { komplex x1,x2,e; x1.real = 10; x1.imag = 2; x2.real = 20; x2.imag = -3; printk(x1); printk(x2); e = add(x1,x2); printk(e); printk(mul(x1,x2)); return 0; }
F: Láncolt lista. Olvassunk be egész számokat egy láncolt listába egy adott végjelig, majd írassuk ki őket. ============================================================================== == BEGIN linkedlist.c ======================================================== #include <stdio.h> #include <stdlib.h> #define VEGJEL 0 struct cella { int ertek; struct cella *kov; }; int main() { struct cella *elso = NULL; struct cella *p; int i; scanf("%d", &i); while(i!=VEGJEL) { p = (struct cella*)malloc(sizeof(struct cella)); p->ertek = i; p->kov = elso; elso = p; scanf("%d", &i); } for(p=elso; p!=NULL; p=p->kov) { printf("%d\n", p->ertek); } while(elso!=NULL) { p =elso; elso=p->kov; free(p); } return 0; }
Ismerkedjünk meg a union típussal. Igazából nincs sok dolgunk, mivel a struct típussal kapcsolatban ismertetett formai megoldások a union típusra is alkalmazhatóak.
Egyetlen és egyben lényegi különbség az adattagok elhelyezkedése között van. Míg a struktúra adattagjai a memóriában egymás után helyezkednek el, addig az únió adattagjai közös címen kezdődnek (átlapoltak).
short a; int b; long long c; Memóriafoglalás: STRUCT UNION _______ _ | | | | | | long long c | | | _______ _ |_______| _| | | | | | | int b |_______| _ | long long c |_______| _| |_______| _ | int b | |_______| _| short a |_______| _| short a _| _|
A union szerkezetét meghatározó deklaráció általános formája:
union union_azonosító { típus1 tag1; típus2 tag2; ... típusN tagN; };
A fenti típussal változót az alábbi módon készíthetünk:
union union_azonosító union_változó;
F: Mi a különbség a struct és a union között? Deklarálj egy struct és egy union típust ugyanolyan mezőkkel. Adj értéket a mezőknek, majd írasd ki őket! ============================================================================== #include <stdio.h> typedef struct {int i; double d; char c; float f;} st; typedef union {int i; double d; char c; float f;} un; int main() { st s; un u; s.i = u.i = 12345; printf("s.i: %d u.i: %d\n", s.i, u.i); s.d = u.d = 3.141593; printf("s.d: %lf u.d: %lf\n", s.d, u.d); s.c = u.c = 'A'; printf("s.c: %c u.c: %c\n", s.c, u.c); s.f = u.f = 2.718281; printf("s.f: %f u.f: %f\n", s.f, u.f); return 0; }
Így nem látszik semmi. De mi van, ha egyszerre íratjuk ki a mezők értékeit? ============================================================================== #include <stdio.h> typedef struct {int i; double d; char c; float f;} st; typedef union {int i; double d; char c; float f;} un; int main() { st s; un u; s.i = u.i = 12345; s.d = u.d = 3.141593; s.c = u.c = 'A'; s.f = u.f = 2.718281; printf("s.i: %d u.i: %d\n", s.i, u.i); printf("s.d: %lf u.d: %lf\n", s.d, u.d); printf("s.c: %c u.c: %c\n", s.c, u.c); printf("s.f: %f u.f: %f\n", s.f, u.f); return 0; }
F: Írasd ki a mezők kezdőcímét! ============================================================================== == BEGIN union.c ============================================================= #include <stdio.h> typedef struct {int i; double d; char c; float f;} st; typedef union {int i; double d; char c; float f;} un; int main() { st s; un u; printf("s.i: %p u.i: %p\n", &s.i, &u.i); printf("s.d: %p u.d: %p\n", &s.d, &u.d); printf("s.c: %p u.c: %p\n", &s.c, &u.c); printf("s.f: %p u.f: %p\n", &s.f, &u.f); return 0; }
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ék 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 .
Megvalósítandó játék: BLACK JACK (21-ezés)
Kiírás: Egy játékos játszik a számítógép ellen. A játékot francia kártyán játszák, tehát a bejövő lapok értéke 1..11 lehet. Kezdetben mindkét játékosnak 0 lapja van. A két játékos ezután felváltva kérhet lapot. A játékostól kérjük be, hogy szeretne-e még lapot, a számítógépnek pedig legyen beállítva egy felső korlát, hogy milyen lapépérték összegre húzzon még rá. Figyeljünk rá oda, hogy attól, hogy esetleg a játékos már nem kér több lapot, attól még a számítógép kapjon, ha nem érte még el a felső korlátot. Miután mindkét játékos jelezte, hogy már nem kér több lapot, hasonlítsuk össze a lapértékek összegét, majd a Black Jack szabályai alapján hirdessünk nyertest.
Egy lehetséges futási eredmény:
<<< BLACK JACK >>> Kersz-e lapot (1 - igen, 0 - nem)? 1 Lapjaid osszege eddig: 9 Kersz-e lapot (1 - igen, 0 - nem)? 1 Lapjaid osszege eddig: 12 Kersz-e lapot (1 - igen, 0 - nem)? 1 Lapjaid osszege eddig: 21 Kersz-e lapot (1 - igen, 0 - nem)? 0 Te pontszamod: 21 Ellenfel pontszama: 22 Nyertel! A te lapjaid rendre: 9 3 9 Az ellenfel lapjai rendre: 3 7 5 7
Megoldások beküldésének határideje: 2014.11.02., vasárnap éjfél.
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ó.
Házi feladat 01-hazi.txt , 02-hazi.txt .
Téma:
3. - 7. gyakorlat anyaga.
Gyakorlásra:
A honlapomon a 3. - 7. 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ó:
A gyakorlat 8:10-kor kezdődik és a ZH-t 8:15-kor kezdhetitek írni. Előreláthatóan 75 percetek lesz a feladat megoldására és beadására (tehát 9:30-ig). A feladatot 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 (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.