Vizsgák 2012
A vizsgafeladatok és megoldásaik.
A vizsgákra ne a régi sorok megoldásainak olvasgatásával készülj! Annak hasznossága nem közelítőleg nulla, hanem pontosan nulla. Lásd itt.
1 Elővizsga (dec. 12.)
1. Beugró
Definiálj pointert, mely alkalmas egy, a qsort() által összehasonlításra alkalmazható függvény címének tárolására!
Megoldás
int (*pfv)(void const *, void const *);
Mennyi 21^3? Add meg a számokat kettes, az eredményt kettes és tízes számrendszerben is!
Megoldás
10101 ^00011 ------ 10110 = 22
Írj véletlenbetű generáló függvényt! A függvény az ‘a’..’z’ tartományban állítson elő véletlenszerűen egy kisbetűt az ASCII táblából, és ezt visszatérési értékként adja! A megoldáshoz használd a szabványos könyvtárban található véletlenszám generáló függvényt!
Megoldás
char veletlenbetu(void) { return 'a' + rand()%('z'-'a'+1); }
Írj függvényt, amely átvesz két sztringet paraméterként, és összefűzi ezeket! Az összefűzött sztring legyen a függvény visszatérési értéke. Ne foglalj a szükségesnél több memóriát!
Megoldás
char *osszefuz(char *egyik, char *masik) { char *uj = (char*) malloc((strlen(egyik)+strlen(masik)+1)*sizeof(char)); if (uj==NULL) return NULL; strcpy(uj, egyik); strcat(uj, masik); return uj; }
Definiálj egyszeresen láncolt listát, amely dinamikusan foglalt sztringeket tárol! Írj függvényt, amely felszabadít egy ilyen listát!
Megoldás
typedef struct lista {char *szo; struct lista *kov;} lista; void szabad(lista *elso) { lista *lemarado; while(elso != NULL) { lemarado=elso; elso=elso->kov; free(lemarado->szo); free(lemarado); } }
Definiálj bináris fa típust, amelynek csúcspontjai valós számokat tárolnak! Írj függvényt, mely a gyökerével átvett fáról visszaadja, hogy hány levele van!
Megoldás
typedef struct elem { double adat; struct elem *bal, *jobb; } elem; int level(elem *gy) { int gyerekeknel; if (gy == NULL) return 0; gyerekeknel=level(gy->bal)+level(gy->jobb); return (gyerekeknel == 0)? 1 : gyerekeknel; }
2. Mátrix
Definiálj típust, amely egy tetszőlegesen nagy, valós számokból álló mátrixot képes tárolni kétdimenziós dinamikus tömbben! Tárold el a típusban a mátrix szélességét és magasságát is! Írj egy olyan függvényt, amely paraméterként kap egy mátrixot, amelyet át kell méreteznie az ugyancsak paraméterként kapott szélességűre és magasságúra. Ha az új mérete eredetinél kisebb, a jobb/alsó szélek adatai eldobandóak; ha nagyobb, akkor pedig legyenek az új helyek nullákkal feltöltve!
Rajzold le, hogyan tároltad a kétdimenziós tömböt! Mutass rá példát, hogyan kell használni a függvényt!
Megoldás
#include <stdlib.h> typedef struct Matrix { int sz, m; double **adat; } Matrix; void atmeretez(Matrix *matr, int uj_sz, int uj_m) { int min_sz = uj_sz<matr->sz ? uj_sz : matr->sz, min_m = uj_m<matr->m ? uj_m : matr->m; int x, y; double **uj_adat; /* új foglalás, direkt nullázva */ uj_adat = malloc(uj_m * sizeof(double*)); for (y = 0; y < uj_m; ++y) uj_adat[y] = calloc(uj_sz, sizeof(double)); /* számok másolása */ for (y = 0; y < min_m; ++y) for (x = 0; x < min_sz; ++x) uj_adat[y][x] = matr->adat[y][x]; /* régi felszabadítása */ for (y = 0; y < matr->m; ++y) free(matr->adat[y]); free(matr->adat); /* admin */ matr->sz = uj_sz; matr->m = uj_m; matr->adat = uj_adat; } Matrix m; atmeretez(&m, 12, 30);
3. Hexadump
Írj programot, amely megnyit egy, az első parancssori paraméterében megadott nevű bináris fájlt, és kiírja annak hexadecimális „dump”-ját! Ebben soronként bal oldalon 16 hexadecimális szám szerepel (a bájtok értékei), jobb oldalon pedig ugyanezek a bájtok karakterként. (Ha a karakter kódja 32-nél kisebb, akkor az egy vezérlőkarakter, amely helyett egy pontot kell kiírnia a programnak.) Figyelj arra, hogy a kiírás utolsó (valószínűleg töredék) sora is szép legyen! Figyelj a hibakezelésre!
Például ha egy fájl egy „Hello, vilag!!!!!!!” szöveget, és egy entert tartalmaz, az alábbi a program kimenete:
48 65 6c 6c 6f 2c 20 76 69 6c 61 67 21 21 21 21 | Hello, vilag!!!! 21 21 21 0a | !!!.
Megoldás
#include <stdio.h> int main(int argc, char *argv[]) { FILE *file; unsigned read; char data[16]; if (argv[1]==NULL) { printf("Nem kaptam fajlnevet\n"); return 1; } file = fopen(argv[1], "rb"); if (file == NULL) { printf("A fajl megnyitas problemaja\n"); return 2; } while ((read = fread(data, sizeof(char), 16, file)) != 0) { int i; for (i = 0; i < read; ++i) { printf("%02x ", data[i]); } if (read < 16) { for (i = 0; i < 16 - read; ++i) printf(" "); } printf(" | "); for (i = 0; i < read; ++i) { if (data[i] >= 32) printf("%c", data[i]); else printf("."); } printf("\n"); } fclose(file); return 0; }
4. CD adatbázis
Definiálj láncolt listát, amely zenei albumok adatait tárolja! Egy elem tárolja el az album előadóját (maximum 50 karakter), az album címét (maximum 50 karakter), és a megjelenés évét (előjel nélküli egész)!
Írj függvényt, amely úgy építi fel a fenti listát, hogy az rögtön rendezve legyen az album címe szerint ábécé sorrendben!
Írj függvényt, amely paraméterként kapott nevű szöveges fájlba menti az albumok adatait az album címe szerint ábécé sorrendben!
Írj programot, amely beolvassa tetszőleges számú album adatait a felhasználótól, és beteszi azokat egy listába a függvényével, majd a listát a parancssori paraméterként megadott nevű szöveges fájlba menti a kiíró függvény segítségével. Ne feledkezz meg a dinamikusan foglalt memória felszabadításáról!
A kommunikáció a felhasználóval lehet szép, de nem pontozzuk.
Megoldás
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct album { char eloado[50+1]; char cim[50+1]; unsigned megjelenes; struct album *kov; } album; void beszur(album *lista, album const *uj){ album *p, *lemarado; lemarado = lista; lista = lista->kov; while (lista != NULL && strcmp(lista->cim, uj->cim) < 0) { lemarado = lista; lista = lista->kov; } p = (album*) malloc(sizeof(album)); if (p == NULL) exit(1); *p = *uj; p->kov = lemarado->kov; lemarado->kov = p; } void ment(album *lista, char *fajlnev) { FILE *fp = fopen(fajlnev, "wt"); if (fp==NULL) exit(1); lista = lista->kov; /* strazsa atugrasa */ while (lista!=NULL) { fprintf(fp, "%s;%s;%u\n", lista->eloado, lista->cim, lista->megjelenes); lista = lista->kov; } fclose(fp); } int main(int argc, char **argv) { album start, temp; start.kov = NULL; /* eleje strazsa */ while (scanf(" %[^\n] %[^\n] %u", temp.eloado, temp.cim, &temp.megjelenes)==3) { beszur(&start, &temp); } if(argc>1) { ment(&start, argv[1]); } else { printf("Nincs megadva fajlnev!\n"); } while (start.kov != NULL) { album *temp = start.kov->kov; free(start.kov); start.kov = temp; } return 0; }
2 Első vizsga (dec. 18.)
1. Beugró
Rajzolj egy karácsonyfát!
Megoldás
* / \ / * \ / \ /_* *_\ |_|
Adott egy előjel nélküli egész, amelyben egy 24 biten ábrázolható szám van. Szedd ki bitműveletekkel az alsó, a középső, és a felső 8 bitet (3×8=24 bit) egy-egy változóba! (Definiálj minden változót!)
Megoldás
unsigned long szin = 0xFFE312; unsigned char r, g, b; r = (szin>>16) & 0xFF; /* 0xFF itt elhagyhato */ g = (szin>>8) & 0xFF; b = (szin>>0) & 0xFF; /* >>0 nyilvan elhagyhato */
Definiálj felsorolt típust, amely alkalmas a hét munkanapjainak tárolására!
Megoldás
enum nap { hetfo, kedd, szerda, csutortok, pentek };
Írj függvényt, amely logikai értéket ad vissza, amely igaz, ha a függvénynek paraméterként átadott pozitív egész szám prím, és hamis, ha nem az.
Megoldás
int prim_e(int szam) { int oszto; for (oszto=2; oszto<=szam/2; ++oszto) if (szam%oszto == 0) return 0; return 1; }
Definiálj bináris fát, amely dinamikusan foglalt sztringeket tárol! Írj függvényt, amely felszabadít egy ilyen fát!
Megoldás
typedef struct BiFa { char *sztring; BiFa *bal, *jobb; } BiFa; void favago(BiFa *gy) { if (gy == NULL) return; favago(gy->bal); favago(gy->jobb); free(gy->sztring); free(gy); }
Írj programrészt, amely beolvassa az „intek.dat” nevű bináris fájlt, amely int típusú értékeket tartalmaz, és kiírja azokat a képernyőre! Gondoskodj a hibakezelésről!
Megoldás
FILE *fp = fopen("intek.dat", "rb"); if (fp != NULL) { int i; while (fread(&i, sizeof(int), 1, fp)>0) printf("%d", i); fclose(fp); } else { printf("Nem lehetett megnyitni!"); }
2. Tökéletes
Nagyon tökéletes számoknak nevezzük azokat, amelyek osztói összegének osztóit összegezve az eredeti szám kétszeresét kapjuk. Az első ilyen a 2, mert osztóösszege 1+2=3, aminek osztóösszege 1+3=4, ami az eredeti 2 duplája. Melyik az 5-ödik ilyen? Írj programot, amelyik kiszámítja és kiírja!
Megoldás
#include <stdio.h> int osztoosszeg(int szam) { int oszto, osszeg; osszeg=0; for (oszto=1; oszto<=szam; ++oszto) if (szam%oszto == 0) osszeg+=oszto; return osszeg; } int main() { int szam; int i; szam=1; i=0; while (i<5) { ++szam; if (osztoosszeg(osztoosszeg(szam))==2*szam) ++i; } printf("%d\n", szam); return 0; }
3. π
„Nem a régi s durva közelítés, Mi szótól szóig így kijön Betűiket számlálva.” – így kezdődik Szász Pál, matematikus verse, amely arról ismert, hogy a szavainak hossza a π számjegyeivel egyezik meg. (3141592653589...)
Írj függvényt, amely paraméterként átvesz egy sztringet, és visszatér egy tömbbel, amelyben a sztring szavai hosszainak számát tárolja sorban! A tömb végén legyen egy lezáró -1-es érték. A hosszakba ne vedd bele az írásjeleket! Feltételezheted, hogy az írásjelek mellett pontosan egy szóköz van a szavak között. A szavak az angol ABC betűiből állnak, minden egyéb karaktert írásjelnek tekintünk a whitespace (szóköz, újsor) karaktereken kívül.
Írj teljes programot, amely a függvényt meghívja a sztringre, és aztán a kapott tömb alapján kiírja a π első néhány számjegyét!Megoldás
#include <ctype.h> #include <stdio.h> #include <stdlib.h> int *szohosszak(char *str) { int *szohossz; int p, h, db; db = 0; for (p = 0; str[p] != '\0'; ++p) if (isspace(str[p])) ++db; szohossz = (int*) malloc(sizeof(int) * (db+2)); p = 0; db = 0; while (str[p] != '\0') { h=0; while (str[p] != '\0' && isalpha(str[p])) p++, h++; szohossz[db++] = h; while (str[p] != '\0' && !isalpha(str[p])) p++; } szohossz[db] = -1; return szohossz; } int main() { int *h, i; h = szohosszak("Nem a regi s durva kozelites, mi szotol szoig" " igy kijon betuiket szamlalva."); for (i = 0; h[i]>=0; ++i) printf("%d", h[i]); free(h); return 0; }
4. Gráf
c 1 102 75 c 2 97 34 e 1 2
Írj programot, amely egy képernyőre rajzolt gráfot (élekkel összekötött csúcsokat) tárol el és dolgoz fel! A programnak az alábbi felépítésű szövegfájlt kell beolvasnia, amelyben a sorok tetszőleges sorrendben lehetnek.
A példa fájl azt jelenti, hogy az 1-es csúcs (c) koordinátái x=102 y=75, a 2-es csúcs x=97, y=34, és van egy él (e) az 1-es és 2-es csúcs között. A csúcsok sorszámai egyediek. Mind élből, mind csúcsból tetszőlegesen sok lehet.
- Írj függvényt, amely egy fájlnevet kap, és visszatér a beolvasott gráffal!
- Írj függvényt, amely visszatér a gráf leghosszabb élének hosszával, vagy -1-gyel, ha nincs éle!
- Írj programot, amely kiírja a „graf.txt” fájlbeli gráf leghosszabb élének hosszát!
Megoldás
Itt a csúcs és az él két külön típus! Tehát a csúcsok és az élek listája is. Lásd az első (!) előadást! Aki egy listában próbálta meg tárolni a csúcsokat és az éleket, nem sok pontot tudott gyűjteni.
#include <stdlib.h> #include <stdio.h> #include <math.h> typedef struct Csucs { int x, y, szam; struct Csucs *kov; } Csucs; typedef struct El { int cs1, cs2; struct El *kov; } El; typedef struct Graf { Csucs *csucsok; El *elek; } Graf; Graf beolvas(char *fajl) { Graf g = { NULL, NULL }; Csucs *cs; El *e; char tip; FILE *fp = fopen(fajl, "rt"); while (fscanf(fp, " %c", &tip) == 1) { switch (tip) { case 'c': cs = (Csucs *) malloc(sizeof(Csucs)); fscanf(fp, "%d %d %d", &cs->szam, &cs->x, &cs->y); cs->kov = g.csucsok; g.csucsok = cs; break; case 'e': e = (El *)malloc(sizeof(El)); fscanf(fp, "%d %d", &e->cs1, &e->cs2); e->kov = g.elek; g.elek = e; break; } } fclose(fp); return g; } /* megadja egy keresett szamu csucs ptr-et */ Csucs *csucskeres(Csucs *csucsok, int szam) { while (csucsok != NULL && csucsok->szam != szam) csucsok = csucsok->kov; return csucsok; } double leghosszabb_el(Graf g) { El *e; double maxhossz = -1; for (e = g.elek; e != NULL; e = e->kov) { Csucs *cs1 = csucskeres(g.csucsok, e->cs1); Csucs *cs2 = csucskeres(g.csucsok, e->cs2); double hossz = sqrt(pow(cs1->x - cs2->x, 2) + pow(cs1->y - cs2->y, 2)); if (hossz > maxhossz) maxhossz = hossz; } return maxhossz; } void graf_felszab(Graf g) { while (g.csucsok) { Csucs *lemar = g.csucsok; g.csucsok = g.csucsok->kov; free(lemar); } while (g.elek) { El *lemar = g.elek; g.elek = g.elek->kov; free(lemar); } } int main() { Graf g = beolvas("graf.txt"); printf("Leghosszabb: %f", leghosszabb_el(g)); graf_felszab(g); return 0; }
3 Második vizsga (jan. 8.)
1. Beugró
Definiálj adattípust, amely mondatrészek láncolt listában való eltárolására használható! Egy mondatrészt egy maximum 20 karakteres sztring jellemez és a típusa, ami lehet ALANY, ALLITMANY, JELZO vagy HATAROZO.
Megoldás
typedef struct Mondatresz { char szo[21]; enum {ALANY, ALLITMANY, JELZO, HATAROZO} tipus; struct Mondatresz *kovetkezo; } Mondatresz;
Írj függvényt, ami egy karaktert vesz át és egy logikai értékkel tér vissza, ami akkor legyen igaz, ha a karakter lehet hexadecimális számjegy (egy számjegy 0 és 9 között vagy egy betű A és F között)!
Megoldás
/* isxdigit is elfogadhato */ int hexaszamjegy(char c) { c = toupper(c); return ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')); }
Írj függvényt, amely az átvett egész szám (első paraméter) alsó valahány bitjét (második paraméter) kinullázza, miközben a többi változatlanul marad! Az így kapott érték legyen a visszatérési értéke.
Megoldás
/* lefele shiftelve elvesznek a bitek, visszashiftelve 0-k jonnek be */ unsigned nullaz(unsigned mit, int mennyi) { return (mit >> mennyi) << mennyi; } /* vagy igy is jo: eloallitani egy 11111110000-szeru maszkot, es azt hozzaESelni */ unsigned nullaz(unsigned mit, int mennyi) { return mit & (~0 << mennyi); }
Írj kódrészletet, ami egy program első parancssori paraméterében átvett nevű bináris fájlt hozzáfűzésre megnyitja, beleír egy általad választott valós számot, majd bezárja!
Megoldás
FILE *f; double d = 2.32; f = fopen(argv[1], "ba"); /* binary append */ fwrite(&d, sizeof(double), 1, f); fclose(f);
Írj függvényt, amelynek egy int tömböt vesz át paraméterként és logikai értékkel tér vissza, ami akkor legyen igaz, ha a tömbben van olyan szám, amely 5-tel és 17-tel is osztható!
Megoldás
int oszthato(int *tomb, size_t meret) { size_t i; for (i = 0; i < meret; ++i) if ((tomb[i] % 5 == 0) && (tomb[i] % 17 == 0)) return 1; return 0; }
Definiálj fát, amely maximum 50 karakter hosszú szavakat tárol! Írj függvényt, amely átveszi egy fa gyökerét és egy egész számot! A függvény feladata megadni, hogy a fában mennyi olyan szó szerepel, amely hosszabb, mint a paraméterként átvett érték.
Megoldás
typedef struct Szavak { char szo[51]; struct Szavak *bal, *jobb; } Szavak; int hosszabb(Szavak *gyoker, int hossz) { if (gyoker != NULL) { int sajat_hossz = strlen(gyoker->szo); return hosszabb(gyoker->bal, hossz) + hosszabb(gyoker->jobb, hossz) + (sajat_hossz > hossz ? 1 : 0); } else return 0; }
2. Kukac
o o / \ o vagy o / / o o
Definiálj C-ben egész számokat tároló bináris fa típust! Írj függvényt, amelyik visszatérési értékében logikai igaz értékkel jelzi egy ilyen fáról, hogy listává (egy ágú fává) fajult-e, azaz ahhoz hasonló kukacnak néz-e ki, mint a jobb oldalt látható fák. Írj egy rövid kódrészletet, amelyben definiálsz egy fát hivatkozó változót (a fát magát létrehozni nem kell), és a függvény visszatérési értéke alapján kiírod, hogy lista-e a fa, vagy nem.
Megoldás
#include <stdio.h> #include <stdlib.h> typedef struct Fa { int adat; struct Fa *b, *j; } Fa; /* egyik praktikus megoldas: szokasos baziskriterium+egyszerusites lepesek meghatarozasa. ha talal egy 2gyerekes csomopontot, akkor nem jo. */ int lista_e(Fa *gy) { /* ha ures, akkor igen. ures fa, ures lista. */ if (gy==NULL) return 1; /* ha nincs gyerek, akkor elmegy listanak is. ez ELHAGYHATO, mivel az egyszerusites is kiadja! */ if (gy->b==NULL && gy->j==NULL) return 1; /* ha 2 gyerek van, itt egy elagazas, szoval nem. */ if (gy->b!=NULL && gy->j!=NULL) return 0; if (gy->b != NULL) /* ha balra a folytatas, akkor lehet, hogy jok * vagyunk. pontosabban ha a tobbi resz jo, akkor jo. */ return lista_e(gy->b); else /* amugy jobbra ugyanez, ha ott van valami */ return lista_e(gy->j); /* ide jo akar az is, hogy return lista_e(gy->b) && lista_e(gy->j); */ } Fa *fa = ..........; /* valahonnan lesz egy fa */ printf("%s", lista_e(fa) ? "kukac" : "elagazik");
Másik praktikus megoldás: ha elemszám = emeletszám, akkor kukac. Ehhez meg kell írni az előadáson bemutatott elemszám() és emeletszám() függvényeket is.
Harmadik lehetőség: egy iteratív megoldás. A fáknál a rekurzió
az elágazások miatt kell. Viszont ha ez egy kukac, akkor elvileg nem lesz
benne elágazás, tehát végig kell, hogy lehessen menni rajta egy ciklussal
is. Mindig vagy balra, vagy jobbra lesz a következő csomópont attól függően,
hogy merre nem NULL
a pointer. Ha mindkettő irányba, akkor
egy elágazást találtunk, akkor viszont az egész fa nem lehet kukac:
Fa *mozgo = gyoker; while (gyoker != NULL) { /* ket iranyba lehet menni? akkor nem kukac */ if (gyoker->bal != NULL && gyoker->jobb != NULL) return 0; /* tovabb a "listaban" */ gyoker = gyoker->bal != NULL ? gyoker->bal : gyoker->jobb; } return 1;
3. E-mail
Egy email címzettjei egy sztringben vannak felsorolva úgy, hogy a nevek idézőjelek között vannak, ezután egy szóközzel elválasztva következik az email cím, majd a további címzettek egy vesszővel elválasztva. Ha nincs több címzett, akkor nincs vessző sem, hanem vége a sztringnek. Például: "Alma Anna" almaanna@mail.com, "Citrom Cili" citromcili@mail.com, "Körte Kálmán" kortekalman@mail.com
Írj programot, amiben létrehozol egy ilyen ilyen sztringet és feldolgozod! A tartalmát egy olyan tömbbe tedd, amely struktúrákból épül fel: a mezői a 20 karakteres név és a szintén 20 karakteres email cím. A tömb pontosan akkora legyen, ahány címzett a sztringben szerepelt! Ezután a tömböt rendezd meg a könyvtári qsort függvénnyel! Írj ehhez segédfüggvényt, amelynek a segítségével a qsort az email címek szerint fordított ábécé sorrendbe rendezi a tartalmat!
Megoldás
#include <string.h> #include <stdio.h> #include <stdlib.h> #include <ctype.h> typedef struct { char nev[21]; char email[21]; } Cimzett; int hasonlit(void const *arg1, void const *arg2) { Cimzett *cimzett1 = (Cimzett *)arg1; Cimzett *cimzett2 = (Cimzett *)arg2; return strcmp(cimzett2->email, cimzett1->email); } /* scanf %n-nel adhato egy sokkal egyszerubb megoldas is. */ int main() { char *cimzettek = "\"Alma Anna\" almaanna@mail.com, " "\"Citrom Cili\" citromcili@mail.com, " "\"Körte Kálmán\" kortekalman@mail.com"; Cimzett *cimzett_tomb; int i, pozicio, van_meg, cimzett_it, cimzett_darab; cimzett_darab = 0; for (i = 0; cimzettek[i] != 0; ++i) if (cimzettek[i] == '@') ++cimzett_darab; cimzett_tomb = (Cimzett *) malloc(cimzett_darab * sizeof(Cimzett)); cimzett_it = pozicio = 0; do { while (cimzettek[pozicio] != '"') ++pozicio; pozicio += 1; //átlépjük a nyitó "-t for (i = 0; cimzettek[pozicio] != '"'; ++i, ++pozicio) cimzett_tomb[cimzett_it].nev[i] = cimzettek[pozicio]; cimzett_tomb[cimzett_it].nev[i] = 0; //lezárjuk a nevet pozicio += 1; //átlépjük a lezáró "-t while (isspace(cimzettek[pozicio])) ++pozicio; for (i = 0; cimzettek[pozicio] != ',' && cimzettek[pozicio] != 0; ++i, ++pozicio) cimzett_tomb[cimzett_it].email[i] = cimzettek[pozicio]; cimzett_tomb[cimzett_it].email[i]= 0; //lezárjuk az emailt van_meg = cimzettek[pozicio++] == ','; //ha van még név, akkor továbbmegyünk ++cimzett_it; // növeljük a címzett iterátort } while (van_meg); qsort(cimzett_tomb, cimzett_darab, sizeof(Cimzett), hasonlit); return 0; }
4. Épületek
Az „epuletek.txt” szöveges fájlban rendelkezésünkre állnak a világ legmagasabb épületeinek az
adatai: város (max. 20 betű) és ország (max. 20), magasság méterben és
az építés éve. A fájl sorainak a formátuma a következő: város ország magasság év, szóközökkel
elválasztva. Például: Tokió Japán 634 2012
.
Írj függvényt, ami a paraméterként átvett nevű fájlból beolvassa az épületek adatait és felépít egy listát, amely az építési év és azon belül a magasság szerint van rendezve!
Készíts egy függvényt, amelynek a segítségével megszámlálhatod a listából, hogy egy adott évben (ez a függvény paramétere) hány épület épült!
Készíts egy függvényt, amellyel megszámolhatod a listában, hogy egy adott országban (az országnév a függvény paramétere) hány épület van!
+4 pont jár, ha a fenti két feladatot egy darab generikus, általános számláló függvénnyel, és két neki adható predikátumfüggvénnyel oldod meg.
Megoldás
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Epulet { char varos[20+1], orszag[20+1]; int magassag, ev; struct Epulet *kovetkezo; } Epulet; int felepit(Epulet **epuletek, char const *filenev) { FILE *file; Epulet adat; file = fopen(filenev, "rt"); if (file == NULL) return 0; while (fscanf(file, "%s %s %d %d", adat.varos, adat.orszag, &adat.magassag, &adat.ev) == 4) { Epulet *uj = (Epulet *)malloc(sizeof(Epulet)); *uj = adat; if (*epuletek == NULL) { *epuletek = uj; uj->kovetkezo = NULL; } else { Epulet *mozgo, *lemarado; for (mozgo = *epuletek, lemarado = NULL; mozgo != NULL && (mozgo->ev < uj->ev || (mozgo->ev == uj->ev && mozgo->magassag < uj->magassag)); lemarado = mozgo, mozgo = mozgo->kovetkezo) ; /* üres */ if (lemarado == NULL) { uj->kovetkezo = *epuletek; *epuletek = uj; } else { lemarado->kovetkezo = uj; uj->kovetkezo = mozgo; } } } fclose(file); return 1; } /* a +4 pontos megoldas */ int megszamol(Epulet *epuletek, int (*feltetel)(Epulet *, void *), void *parameter) { Epulet *mozgo; int darab = 0; for (mozgo = epuletek; mozgo != NULL; mozgo = mozgo->kovetkezo) { if (feltetel(mozgo, parameter)) ++darab; } return darab; } int adott_ev(Epulet *epulet, void *pev) { int ev = *((int *) pev); return epulet->ev == ev; } int adott_orszag(Epulet *epulet, void *porszag) { return strcmp(epulet->orszag, (char *) porszag) == 0; } int main() { Epulet *epuletek = NULL; int sikerult; sikerult = felepit(&epuletek, "epuletek.txt"); if (sikerult) { int ev = 2010; printf("2010-ben %d darab épült\n", megszamol(epuletek, adott_ev, &ev)); printf("Kínában %d van\n", megszamol(epuletek, adott_orszag, "Kína")); } return 0; }
4 Harmadik vizsga (jan. 10.)
1. Beugró
Mennyi 55 és 26 binárisan? Mennyi 55^26
hexadecimálisan?
Megoldás
55 = 110111 26 = 011010 55^26 = 101101 = 2D
Írj függvényt, amely megcseréli két double
típusú változó tartalmát, amelyek egy másik függvényben lettek létrehozva! Mutasd be, hogy kell hívni ezt a függvényt!
Megoldás
void csere(double *x, double *y) { double tmp = *x; *x = *y; *y = tmp; } double x=3.14, y=2.71; csere(&x, &y);
Definiálj felsorolt típust közlekedési lámpa állapotainak tárolására. Hozz létre egy zöld lámpát! :)
Megoldás
enum Lampa { piros, piros_sarga, zold, sarga }; enum Lampa l; l=zold;
Definiálj láncolt listát, amely dinamikusan foglalt sztringeket tud tárolni! Írj függvényt, amely a paraméterlistán kapott sztringet lemásolva létrehoz és beszúr egy ilyen elemet a szintén paraméterként kapott listaelem után!
Megoldás
typedef struct lista { char *string; struct lista *kov; } lista; void beszur(lista *regi, char *string) { lista *uj = (lista*) malloc(sizeof(lista)); uj->string = (char*) malloc(sizeof(char)*(strlen(string) + 1)); srtcpy(uj->string, string); uj->kov = regi->kov; regi->kov = uj; }
Írj függvényt, ami egészeket tartalmazó tömböt és egy n egész számot vesz át a paraméterlistán. A függvény cserélje meg a tömb n db első és utolsó elemét, az elemek sorrendjén nem változtatva! (Pl: n=2, [1,2,3,4,5,6,7,8] → [7,8,3,4,5,6,1,2].)
Megoldás
void swap(int tomb[], int meret, int n) { int i; for (i = 0; i < n; i++) { int tmp = tomb[i]; tomb[i] = tomb[meret-n+i]; tomb[meret-n+i] = tmp; } }
Írj függvényt, ami a paraméterlistán átvett sztringről megállapítja, hogy az palindrom-e (visszafelé ugyanaz, pl. keretkarakterek)! Térjen vissza logikai igazzal/hamissal eszerint!
Megoldás
int palindrom(char string[]) { int i, j; for (i = 0, j = strlen(string)-1; i < j; i++, j--) { if (string[i] != string[j]) { return 0; } } return 1; }
2. Pitagorasz
Pitagoraszi számhármasnak nevezzük azokat a természetes számokból álló hármasokat, amelyekre igaz, hogy a<b<c
, valamint a2+b2=c2
(pl. 32+42=52
). Pontosan egy olyan számhármas létezik, amire a+b+c=1000
.
Írj teljes programot, amelyik kiszámítja és kiírja ezt a számhármast! Határozd meg a kapott három szám legnagyobb közös osztóját!
Megoldás
#include <stdio.h> void triplet(int *pa, int *pb, int *pc) { int s = 1000; int a, b, c; for (a = 3; a < s/3; a++) { for (b = a+1; b < (s-1-a)/2; b++) { c = s-a-b; if (c*c == a*a+b*b) { *pa=a; *pb=b; *pc=c; return; /* a feladat szerint pontosan 1 van */ } } } } /* bruteforce lnko */ int lnko(int a, int b) { int i; i = a<b ? a : b; /* a kisebbiktol visszafele keres */ while (a%i != 0 || b%i != 0) i-=1; return i; } int main() { int a, b, c, lko; triplet(&a, &b, &c); printf("a=%d b=%d c=%d\n", a, b, c); lko = lnko(a, lnko(b, c)); printf("lnko=%d\n", lko); return 0; }
3. HTML
Készíts C programot egy HTML fájl feldolgozására! Ebben a félkövérrel szedett szövegrészeket a következő módon jelölik:
<b>szöveg</b>
. A program vegyen át egy fájlnevet parancssori argumentumként, és írja ki a félkövér szövegrészeket!
A feladatot állapotgéppel oldd meg! Add meg az állapotátmeneti táblát és írd meg a nyitó elemhez (<b>
) tartozó állapotok, továbbá a kiírást is végző állapot programkódját! A program többi részét (parancssori argumentumok átvétele, fájlkezelés stb.) is ki kell dolgozni!
Megoldás
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { FILE *html; enum allapot { ALAP, NYITO_KM, NYITO_B, KOVERBEN, ZARO_KM, ZARO_PER, ZARO_B } allapot = ALAP; int c; if (argc != 2) { printf("Helyes hívás: %s html_fajl\n", argv[0]); return 1; } html = fopen(argv[1], "rt"); if (html==NULL) return 1; while (EOF != (c = fgetc(html))) { switch (allapot) { case ALAP: if (c == '<') allapot = NYITO_KM; break; case NYITO_KM: if (c == 'b') allapot = NYITO_B; else allapot = ALAP; break; case NYITO_B: if (c == '>') allapot = KOVERBEN; else allapot = ALAP; break; case KOVERBEN: if (c == '<') allapot = ZARO_KM; else putchar(c); break; /********** EDDIG KELLETT AZ ALLAPOTGEP **********/ case ZARO_KM: if (c == '/') allapot = ZARO_PER; else allapot = KOVERBEN; break; case ZARO_PER: if (c == 'b') allapot = ZARO_B; else allapot = KOVERBEN; break; case ZARO_B: if (c == '>') allapot = ALAP; else allapot = KOVERBEN; break; } } fclose(html); return 0; }
4. Időjárás
Készíts időjárási adatokat feldolgozó programot!
Az adatok szövegfájlban tárolódnak. Minden naphoz egy bejegyzés tartozik.
Egy sor egy bejegyzés, ami tartalmaz egy időpontot éééé-hh-nn formában,
egy hőmérsékletet Celsiusban, egy szélsebességet m/s-ban és az időjárás
jellegét, amit egy karakter tárol (n: napsütés, f: felhő, e: eső, h: hó).
Az elemeket ;
választja el.
Készíts függvényt, ami a beolvas egy ilyen fájlt (a neve a program parancssori paramétere), és visszatér egy listával, amely az adatokat tartalmazza!
Készíts függvényt, ami visszaadja a legmelegebb, 5 m/s-nál szelesebb,
esős nap bejegyzésére mutató pointert! Ha nincs ilyen, NULL
-t.
Készíts függvényt, ami megszámolja, hány csapadékos nap szerepel az adatbázisban!
Megoldás
#include <stdio.h> #include <stdlib.h> typedef struct rekord { char idopont[11]; double homerseklet; double szelseb; char jelleg; struct rekord *kov; } rekord; rekord* beolvas(char *fajlnev) { FILE *fp; rekord *top, *p, *t; t = (rekord*)malloc(sizeof(rekord)); t->kov = NULL; top = t; fp = fopen(fajlnev,"rt"); while (fscanf(fp, "%[^;];%lf;%lf;%c", t->idopont, &t->homerseklet, &t->szelseb, &t->jelleg)==4) { p = t; t = (rekord*)malloc(sizeof(rekord)); t->kov = NULL; p->kov = t; } p->kov = NULL; free(t); fclose(fp); return top; } rekord* legmelegebb(rekord *top) { rekord *max, *p; max = NULL; for (p = top; p != NULL; p = p->kov) { if (p->szelseb>5 && p->jelleg=='e') if (max==NULL || p->homerseklet > max->homerseklet) max=p; } return max; } int csapszamol(rekord *top) { int db; rekord *p; db = 0; for (p = top; p!=NULL; p=p->kov) if (p->jelleg=='e' || p->jelleg=='h') db++; return db; } void felszab(rekord *top) { rekord *p, *t; p = top; while(p != NULL) { t = p->kov; free(p); p = t; } } int main(int argc, char *argv[]) { rekord *top, *max; top = beolvas(argv[1]); max = legmelegebb(top); printf("%d csapadekos nap van az adatbazisban.\n", csapszamol(top)); felszab(top); return 0; }
5 Negyedik vizsga (jan. 15.)
1. Beugró
Írj programot, amely kiírja, hogy kapott-e parancssori argumentumot, amikor az operációs rendszerből indították!
Megoldás
/* vagy if argv[1]!=NULL. a parameterek nevei tetszolegesek, csak a tipus szamit. */ #include <stdio.h> int main(int argc, char **argv) { if (argc > 1) printf("kapott.\n"); else printf("nem kapott.\n"); return 0; }
Írj kódrészletet, ami megállapítja, és a szabványos kimenetre kiírja, hogy létezik-e és olvasható-e az "in.txt" nevű fájl!
Megoldás
FILE *f; f = fopen("in.txt", "rt"); if (f != NULL) { printf("van.\n"); fclose(f); } else printf("nincs.\n");
Definiálj adatszerkezetet, amely egy vasúti vonal egy állomások közötti szakaszának következő tulajdonságait tudja tárolni: megengedett sebesség, tartózkodik-e rajta vonat, és ha igen, milyen irányban halad (balra, jobbra), valamint a szomszédos szakaszok memóriacíme!
Megoldás
typedef struct szakasz { double max_seb; enum {nincs, balra, jobbra} vonat; struct szakasz *bal, *jobb; } szakasz;
Írj egy programot, amely 1-től 100-ig kiírja a számokat, mindegyiket külön sorba. 3 többszörösei helyett fizz, 5 többszörösei helyett buzz legyen kiírva. Ha egy szám mindkettőnek többszöröse, akkor fizzbuzz.
Megoldás
#include <stdio.h> int main() { int i; for (i=1; i<=100; ++i) { if (i%3==0) printf("fizz"); if (i%5==0) printf("buzz"); if (i%3!=0 && i%5!=0) printf("%d", i); printf("\n"); } return 0; }
Írj függvényt, amely átvesz egy sztringet, és visszaadja a benne található egész szám értékét. Ha a sztring értelmezhetetlen karaktert tartalmaz -1-et, ha üres, 0-t adj vissza! Könyvtári függvényt nem használhatsz.
Megoldás
int decval(char *be) { int val=0, hiba=0; while (!hiba && *be != '\0') { if (*be >='0' && *be <= '9') val = val*10 + *be-'0'; else hiba=1; be++; } return hiba ? -1 : val; }
Definiálj adatszerkezetet, mely alkalmas egész számok bináris fában való tárolására! Írj függvényt, amely átveszi egy, a struktúrából felépülő fa gyökerét, és visszaadja, hogy a fában hány NULL pointer van!
Megoldás
typedef struct Fa { int adat; struct Fa *bal, *jobb; } Fa; int nullszam(Fa *gyoker) { if (gyoker != NULL) { return nullszam(gyoker->bal) + nullszam(gyoker->jobb); } else return 1; }
2. Hamming
a=97→01100001 C=67→01000011
Két azonos bitszámú egész, így pl. karakterkódok Hamming-távolságán azt értjük, hogy hány azonos helyiértéken szereplő bitben különböznek. Pl. az „a” és a „C” karakterek kódjainak Hamming-távolsága 2.
Írj függvényt, amely két karakter Hamming-távolságát adja vissza!
Ezt felhasználva írj függvényt, amely a qsort()
függvénynek összehasonlító függvényként átadható, és segítségével egy karaktertömb elemei a d
karakterhez mért Hamming-távolságuk szerint növekvő sorrendbe rendezhetőek.
Egészítsd ki a fentieket programmá úgy, hogy az kiírja a Neptun-kódod eredeti alakban, valamint a qsort() és az előző függvény segítségével rendezett karakterekkel is!
Megoldás
#include <stdio.h> #include <stdlib.h> #include <string.h> int htav(unsigned char a, unsigned char b) { unsigned char diff = a^b; int tav = 0; while (diff != 0) { tav += diff & 1; diff >>= 1; } return tav; } int d_hamming(const void *a, const void *b) { int da = htav(*(unsigned char *) a, 'd'); int db = htav(*(unsigned char *) b, 'd'); return (da > db) ? 1 : (da < db) ? -1 : 0; /* vagy akár return da-db */ } int main() { char t[] = "MZPERX"; printf("%s\n", t); qsort(t, strlen(t), sizeof(char), d_hamming); printf("%s\n", t); return 0; }
3. Megszentségteleníthetetlenségeskedéseitekért
Írj programot, mely a szabványos bemenetről fájl végéig olvas egy szöveget, a benne található leghosszabb szót megtalálja, és a futás végén a standard kimenetre írja! Egy szó alatt a bemeneti karakterfolyam olyan szakaszát értjük, melyben csak angol betűk vannak. A szavak bármilyen hosszúak lehetnek! (Javasolt saját függvényt írni a sztringhez karakter hozzáfűzéshez és sztring értékadáshoz.)
Megoldás
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> void hozzafuz(char **str, char mit) { char *uj = malloc(strlen(*str) + 2); sprintf(uj, "%s%c", *str, mit); free(*str); *str = uj; } void masol(char **hova, char *mit) { free(*hova); /* a szabvany szerint szabad null ptr-t */ *hova = malloc(strlen(mit) + 1); strcpy(*hova, mit); } int main() { char *akt = NULL, *legh = NULL; int c; masol(&akt, ""); masol(&legh, ""); while ((c=getchar()) != EOF) { if (isalpha(c)) hozzafuz(&akt, c); else { if (strlen(akt) > strlen(legh)) masol(&legh, akt); masol(&akt, ""); } } printf("leghosszabb: %s\n", legh); free(akt); free(legh); return 0; }
4. LNKO
Definiálj típust, mely alkalmas prímtényezők (alap, kitevő) láncolt listában való tárolására!
Írj függvényt, mely átvesz egy ilyen listát, és kiír egy prímtényezős felbontást a következő alakban: 2^2*3^1*5^1
.
Írj függvényt, mely átvesz egy pozitív egészet, és visszaadja a prímtényezős felbontását tényezők szerint növekvő sorrendben egy listában!
Írj egy függvényt, mely paraméterként átvesz két prímtényezős felbontást, és a legnagyobb közös osztó prímtényezős felbontását adja vissza egy új listában!
Egészítsd ki a fentieket teljes programmá, melyben két pozitív egész felbontásán és legnagyobb közös osztójának meghatározásán keresztül példát mutatsz az elkészült függvények alkalmazására!
+4 pont jár, ha O(n) időben, összefésülés algoritmusával oldod meg a két listából a legnagyobb közös osztó lista létrehozását.
Megoldás
#include <stdio.h> #include <stdlib.h> typedef struct Tenyezo { int alap, kitevo; struct Tenyezo *kov; } Tenyezo; Tenyezo *vegere(Tenyezo *lista, int alap, int kitevo) { Tenyezo *uj = (Tenyezo *) malloc(sizeof(Tenyezo)); uj->alap = alap; uj->kitevo = kitevo; uj->kov = NULL; if (lista == NULL) lista = uj; else { Tenyezo *iter; for (iter = lista; iter->kov != NULL; iter = iter->kov) { /* ures */ } iter->kov = uj; } return lista; } Tenyezo *felbontas(int n) { Tenyezo *lista = NULL; /* ures lista */ int oszto = 2; while (n > 1) { int kitevo = 0; while (n % oszto == 0) { /* amig osztja, leosztjuk */ n /= oszto; kitevo++; /* es szamoljuk, hanyszor */ } if (kitevo > 0) /* ha ez oszto volt, listaba vele */ lista = vegere(lista, oszto, kitevo); oszto++; } return lista; } void kiir(Tenyezo *l) { Tenyezo *iter; for (iter = l; iter != NULL; iter = iter->kov) { printf("%d^%d", iter->alap, iter->kitevo); if (iter->kov != NULL) printf(" * "); } printf("\n"); } Tenyezo *lnko(Tenyezo *egyik, Tenyezo *masik) { /* a +4 pontos megoldas */ Tenyezo *lista = NULL; /* amig mindket listabol van, potencialis kozos oszto */ while (egyik != NULL && masik != NULL) { if (egyik->alap == masik->alap) { /* egyenlo alapok? kozos oszto resze! */ lista = vegere(lista, egyik->alap, egyik->kitevo < masik->kitevo ? egyik->kitevo : masik->kitevo); egyik = egyik->kov; masik = masik->kov; } else if (egyik->alap < masik->alap) /* kisebb az egyik? azzal lepunk, hatha elerunk kozoset */ egyik = egyik->kov; else /* se kisebb, se egyenlo, akkor nagyobb - a masik ptr lep */ masik = masik->kov; } return lista; } void felszab(Tenyezo *l) { while (l != NULL) { Tenyezo *kov = l->kov; free(l); l = kov; } } int main() { Tenyezo *egyik, *masik, *kozososzto; egyik = felbontas(360); masik = felbontas(16); kozososzto = lnko(egyik, masik); kiir(egyik); kiir(masik); kiir(kozososzto); felszab(egyik); felszab(masik); felszab(kozososzto); return 0; }
6 Ötödik vizsga (jan. 22.)
1. beugró
Írj függvényt, amelynek nincs paramétere, és első meghívásakor azt írja a szabványos kimenetre, hogy A, második meghívásakor azt, hogy B, harmadik hívásakor ismét A, és így tovább, „ABABAB...”!
void f(void) { static int A = 1; printf("%c", A ? 'A' : 'B'); A = !A; }
Írj kifejezést, amely nem tartalmazhat függvényhívást, és logikai igazra értékelődik ki, ha a c nevű változóban kisbetű van, egyéb esetben hamisra! Definiáld a változót!
char c; c >= 'a' && c <= 'z'
Definiálj duplán láncolt listaelemet, amely egy tört számlálóját és nevezőjét tartalmazza!
typedef struct Tort { int szaml, nev; struct Tort *elozo, *kovetkezo; } Tort;
Írj függvényt, ami egy egész számokból álló tömböt vesz át paraméterként és visszaad egy új tömböt, amiben az előző tömbből csak a negatív elemek vannak benne!
int *negativak(int *tomb, int meret, int *neg) { int i, j; int *uj_tomb; *neg = 0; for (i = 0; i < meret; ++i) if (tomb[i] < 0) ++*neg; uj_tomb = (int *) malloc(*neg * sizeof(int)); for (i = j = 0; i < meret; ++i) if (tomb[i] < 0) uj_tomb[j++] = tomb[i]; return uj_tomb; }
Írj függvényt, amely megszámolja, hogy a paraméterként átvett előjel nélküli egészben hány 1-es értékű bit van, és ezt a darabszámot visszatérési értékként adja!
int egyesek(unsigned egesz) { int db = 0; do if (egesz & 1) ++db; while (egesz >>= 1); return db; }
Definiálj adatszerkezetet bináris fa létrehozásához! Írj függvényt, amely egy bináris fa gyökérelemének címét veszi át, és visszaadja a fa mélységét (vagy más szóval: magasságát)!
typedef struct Bfa { struct Bfa *bal, *jobb; } Bfa; int melyseg(Bfa *gyoker) { if (gyoker == NULL) return 0; else { int b = melyseg(gyoker->bal), j = melyseg(gyoker->jobb); return 1 + (b>j ? b : j); /* a nagyobbik */ } }
2. Sztring csere
Írj függvényt, amely paraméterként kap három sztringet, és az elsőben megkeresi a második összes előfordulását, majd a harmadikra cseréli ezeket! Pl. be: „Minden alma szalma, nagyobb lesz a hatalma.”, „alma” „meggy”, ki: „Minden meggy szmeggy, nagyobb lesz a hatmeggy.” Írj rövid programrészt, amelyben használod a függvényt!
#include <string.h> #include <stdio.h> /* a memmove(dst, src, b) fuggveny b bajtot mozgat src->dst teruleten, * ugy, hogy atfedhetik egymast. ezt meg is lehetett irni. */ void csere(char *miben, char const *mit, char const *mire) { int mibenhossz = strlen(miben); int mithossz = strlen(mit); int mirehossz = strlen(mire); int i; i = 0; while (i != mibenhossz) { if (strncmp(miben+i, mit, mithossz)==0) { /* a mogotte levo reszt hatrebb, lezaro nullaval egyutt */ memmove(miben+i+mirehossz, miben+i+mithossz, mibenhossz-i-mithossz+1); /* helyere ezt */ memmove(miben+i, mire, mirehossz); /* hossza megno; index lep */ mibenhossz += mirehossz-mithossz; i += mirehossz; } else { i += 1; } } } int main() { char t[100] = "Minden alma szalma, nagyobb lesz a hatalma."; csere(t, "alma", "meggy"); printf("[%s]", t); return 0; }
Baba
Egy baba fejlődését vizsgáló program írása a feladat. A program a szabványos bemenetről érkező számhármasokat olvas be fájlvége jelig: időpont (long int-ként tárolandó), etetés előtti súly (valós szám), etetés utáni súly (valós szám).
Definiálj adatszerkezetet az adatok láncolt listában való tárolására! Olvasd be az adatokat láncolt listába, majd számítsd ki, hogy egy-egy etetés alkalmával átlagosan mennyit evett a baba (az etetés utáni és előtti súly különbsége adja a megevett mennyiséget). Írd ki az átlagos megevett mennyiséget, továbbá írd ki az összes időpontot, amikor a baba az átlag felénél kevesebbet evett, és minden ilyen időponthoz a megevett mennyiséget is!
#include <stdio.h> #include <stdlib.h> typedef struct elem { long t; double elott, utan; struct elem *next; } elem; int main(){ double sum = 0.0; int n = 0; elem *start = (elem*)malloc(sizeof(elem)); start->next = NULL; while (scanf("%ld %lg %lg", &start->t, &start->elott, &start->utan)==3) { elem *temp; n++; sum += start->utan - start->elott; temp = (elem*)malloc(sizeof(elem)); temp->next = start; start = temp; } sum /= n; printf("Atlagos fogyasztas: %g\n", sum); for (temp = start->next; temp != NULL; temp = temp->next) if (temp->utan - temp->elott < sum) printf("alatt: %ld idopontban %g mennyiseget\n", temp->t, temp->utan - temp->elott); while (start != NULL) { elem *temp = start->next; free(start); start = temp; } return 0; }
4. Pontok
Egy programban térbeli pontok koordinátáit (x, y, z, három valós szám) és minden ponthoz annak nevét (sztringként, max. 23 betűs) tároljuk. A feladatok a következők:
- Beolvasni egy pontokból álló fájlt egy tömbbe. A bemeneti fájl neve az 1. parancssori paraméterben adott, és egy bináris fájl. Első adata long int típusú, és a pontok számát adja. Ezt követik a pontokhoz tartozó rekordok. Rendezni a tömbben lévő pontokat egy bizonyos ponttól való távolság, √Δx2+Δy2+Δz2 szerint. Ennek a pontnak a koordinátái a 3, 4 és 5. parancssori paraméterben adottak. Kiírni a rendezett pontokat egy fájlba, amelynek minden sora egy pont koordinátáit tartalmazza. A fájl egy szövegfájl, és neve a 2. parancssori paraméterben adott.
Valósítsd meg a részfeladatokat külön függvényekben, és írd meg a főprogramot is! A programban ne használj globális változót!
#include <stdio.h> #include <stdlib.h> typedef struct { double x, y, z; char nev[24]; } pont; void beolvas(char *fajlnev, pont **ptomb, long *pn) { pont *tomb; long n; FILE *fp; fp = fopen(fajlnev, "rb"); fread(&n, sizeof(long), 1, fp); tomb = (pont*) malloc(sizeof(pont) * n); fread(tomb, sizeof(pont), n, fp); fclose(fp); *ptomb = tomb; *pn = n; } double tav(pont a, pont b) { return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z); } void rendez(pont t[], long n, pont p){ long i, j, min; for (i = 0; i < n; i++) { min = i; for (j = i + 1; j < n; j++) if (tav(t[i], p) < tav(t[min], p)) min = j; if (min != i){ pont temp = t[min]; t[min] = t[i]; t[i] = temp; } } } void kiir(char *fajlnev, pont *tomb, long n) { int i; FILE *fp; fp = fopen(fajlnev, "wt"); for (i = 0; i < n; i++) fprintf(fp, "%g %g %g %s\n", tomb[i].x, tomb[i].y, tomb[i].z, tomb[i].nev); fclose(fp); } int main(int argc, char **argv) { pont *tomb, p; long n; beolvas(argv[1], &tomb, &n); sscanf(argv[3], "%lg", &p.x); sscanf(argv[4], "%lg", &p.y); sscanf(argv[5], "%lg", &p.z); rendez(tomb, n, p); kiir(argv[2], tomb, n); free(tomb); return 0; }