Adatbázisrendszerek I. Fájlszintű adattárolás C-ben

Hasonló dokumentumok
Adatbázisrendszerek I. File-szintű adattárolás C-ben. 1. gyakorlat

Programozás 6. Dr. Iványi Péter

Programozás II. Fájlkezelés

A C programozási nyelv VI. Parancssori argumentumok File kezelés

7. gyakorlat Sorozatok, Fájlkezelés

Mérnöki programozás 7. Szerkesztette: dr. Vass Péter Tamás

Objektumorientált programozás Pál László. Sapientia EMTE, Csíkszereda, 2014/2015

Programozás alapjai C nyelv 5. gyakorlat. Írjunk ki fordítva! Írjunk ki fordítva! (3)

Programozás alapjai C nyelv 8. gyakorlat. Mutatók és címek (ism.) Indirekció (ism)

Mutatók és címek (ism.) Programozás alapjai C nyelv 8. gyakorlat. Indirekció (ism) Néhány dolog érthetőbb (ism.) Változók a memóriában

Miről lesz ma szó? A PROGAMOZÁS ALAPJAI 1. Dinamikus változók. Dinamikus változók. Dinamikus változók. Dinamikus változók. 7.

11. gyakorlat Sturktúrák használata. 1. Definiáljon dátum típust. Olvasson be két dátumot, és határozza meg melyik a régebbi.

Listák, szótárak, fájlok Listák, szótárak, fájlok

5. Gyakorlat. struct diak {

Dr. Pál László, Sapientia EMTE, Csíkszereda WEB PROGRAMOZÁS 6.ELŐADÁS. Fájlkezelés PHP-ben

Programozás alapjai 9.Gy: Struktúra 2.

Programozás alapjai C nyelv 9. gyakorlat. Rekurzió. Rekurzív algoritmus

Adatbázis rendszerek Gy: Az adattárolás fejlődése

Pénzügyi algoritmusok

OOP: Java 11.Gy: Enumok, beágyazott osztályok. 13/1 B ITv: MAN

6. gyakorlat Egydimenziós numerikus tömbök kezelése, tömbi algoritmusok

1. Feladat: beolvas két számot úgy, hogy a-ba kerüljön a nagyobb

Rekurzió. Programozás alapjai C nyelv 9. gyakorlat. Rekurzív algoritmus. Rekurzív algoritmus fajtái. Példa: n! (2) Példa: n!

Programozás alapjai 6. előadás. Wagner György Általános Informatikai Tanszék

A programozás alapjai 1 Rekurzió

Tartalom Keresés és rendezés. Vektoralgoritmusok. 1. fejezet. Keresés adatvektorban. A programozás alapjai I.

10. ÓRA. Fájlok használata

Keresés és rendezés. A programozás alapjai I. Hálózati Rendszerek és Szolgáltatások Tanszék Farkas Balázs, Fiala Péter, Vitéz András, Zsóka Zoltán

Programozás II. segédlet

7/8. gyakorlat Karaktertömbök és sztringkezelés

Programozási Nyelvek: C++

OOP #14 (referencia-elv)

A C programozási nyelv V. Struktúra Dinamikus memóriakezelés

Például számokból álló, egyszeresen láncolt lista felépítéséhez az alábbi struktúra definíciót használhatjuk:

Programozás I. gyakorlat

10. gyakorlat Tömb, mint függvény argumentum

Programozás II gyakorlat. 6. Polimorfizmus

Függvények. Programozás alapjai C nyelv 7. gyakorlat. LNKO függvény. Függvények(2) LNKO függvény (2) LNKO függvény (3)

7. gyakorlat. Fájlkezelés IO haladó Függvények haladó

Programozás alapjai C nyelv 7. gyakorlat. Függvények. Függvények(2)

ELTE SAP Excellence Center Oktatóanyag 1

Függvény pointer. Feladat: Egy tömbben soroljunk fel függvényeket, és hívjuk meg valahányszor.

Struktúrák (struct) A struktúra szerkezetét meghatározó deklaráció általános formája:

Mutatók és mutató-aritmetika C-ben március 19.

Dinamikus memóriakezelés Fájlkezelés

Programozás I gyakorlat

3. Osztályok II. Programozás II

C programozási nyelv Pointerek, tömbök, pointer aritmetika

Programozási nyelvek Java

Programozás alapjai 8.Gy: Program struktúra

Példák tematikus csoportosításban

Programozás C nyelven FELÜLNÉZETBŐL elhullatott MORZSÁK. Sapientia EMTE

Rekurzió. Dr. Iványi Péter

Programozás 5. Dr. Iványi Péter

Láncolt lista. az itt adott nevet csak a struct deklaráción belül használjuk

/* Az iter függvény meghívása és a visszatérő érték átadása a gyok változóba */ gyok = iter( n, a, e ) ;

C programozás. 6 óra Függvények, függvényszerű makrók, globális és

Programozási nyelvek Java

Szövegek C++ -ban, a string osztály

Országzászlók (2015. május 27., Sz14)

Preprocesszor. Programozás alapjai C nyelv 11. gyakorlat. Makrók (2) Makrók (#define) Makrók (3) #include

Programozás alapjai C nyelv 11. gyakorlat. Preprocesszor. Makrók (#define)

HORVÁTH ZSÓFIA 1. Beadandó feladat (HOZSAAI.ELTE) ápr 7. 8-as csoport

Információs Technológia

C programozás. { Márton Gyöngyvér, 2009 } { Sapientia, Erdélyi Magyar Tudományegyetem }

1. Alapok. Programozás II

Programozás. (GKxB_INTM021) Dr. Hatwágner F. Miklós május 6. Széchenyi István Egyetem, Gy r

Programozás I gyakorlat

Programozás I. Szöveges fájlok kezelése Felsorolástípus Objektumtömb Gyakorló feladatok

Algoritmusok és adatszerkezetek gyakorlat 06 Adatszerkezetek

Programozás I gyakorlat

Programozás Minta programterv a 1. házi feladathoz 1.

A C programozási nyelv I. Bevezetés

A C programozási nyelv I. Bevezetés

Bevezetés a programozásba I 10. gyakorlat. C++: alprogramok deklarációja és paraméterátadása

1. feladat Készítse el szövegszerkesztővel, majd mentse osztály.txt néven a következő tartalmú szöveges fájlt:

Objektum Orientált Programozás. 11. Kivételkezelés 44/1B IT MAN

500. AA Megoldó Alfréd AA 500.

C++ programozási nyelv

Fejlett programozási nyelvek C++ Iterátorok

10. gyakorlat Struktúrák, uniók, típusdefiníciók

Vezérlési szerkezetek

Mit tudunk már? Programozás alapjai C nyelv 4. gyakorlat. Legnagyobb elem keresése. Feltételes operátor (?:) Legnagyobb elem keresése (3)

II. Mérés SZÉCHENYI ISTVÁN EGYETEM GYŐR TÁVKÖZLÉSI TANSZÉK

Programozás alapjai gyakorlat. 4. gyakorlat Konstansok, tömbök, stringek

Programozás I. gyakorlat

BME MOGI Gépészeti informatika 13.

Programozás alapjai C nyelv 4. gyakorlat. Mit tudunk már? Feltételes operátor (?:) Típus fogalma char, int, float, double

Programozás alapjai C nyelv 10. gyakorlat. Standard függvények. Union

Pénzügyi algoritmusok

Járműfedélzeti rendszerek II. 3. előadás Dr. Bécsi Tamás

Mintavételes szabályozás mikrovezérlő segítségével

Programozas 1. Strukturak, mutatok

Bevezetés a C programozási nyelvbe. Az Általános Informatikai Tanszék C nyelvi kódolási szabványa

STL gyakorlat C++ Izsó Tamás május 9. Izsó Tamás STL gyakorlat/ 1

Adatbázis Rendszerek II. 2. Ea: Gyakorló környezet

Programozás alapjai 5. gyakorlat Vezérlési szerkezetek egymásba ágyazása

Programozási segédlet

7. fejezet: Mutatók és tömbök

és az instanceof operátor

Átírás:

Adatbázisrendszerek I. Fájlszintű adattárolás C-ben Feladat: Tervezzen meg egy fájlszintű adatnyilvántartó rendszert és implementálja C nyelven. A tárolandó adatok: autó rendszáma, típusa, színe, gyártási éve és ára. 1. Adatszerkezet megtervezése typedef struct car { char rendszam[6]; char tipus[20]; char szin[10]; int gyart_ev; double ar; Car; Figyelem! Ha scanf függvénnyel történik az adatbeolvasás, a sztring nem tartalmazhat space-t. 2. Adattárolás fájlban C-ben az adatok tárolhatók ASCII szövegfájlban, vagy bináris fájlban. Fájl létrehozása: FILE *fopen(const char *fajl_nev, const char *megnyitas_mod); Megnyitási módok (szövegfájlok esetén): r (reading) olvasás w writing) írás a (append) hozzáfűzés r+ olvasás a fájl elejétől + írás w+ írás+olvasás, felülírjuk a fájlt a+ írás + olvasás, hozzáfűzünk Bináris fájloknál a betűk után még egy b betűt is oda kell írni, pl.: rb vagy wb+. Ha a fájl megnyitása sikerült egy FILE struktúrára mutató pointert kapunk vissza, ha nem sikerült, akkor NULL pointert. FILE *fp=fopen("cars.bin","ab"); if (!fp) { printf("error: cannot open file."); return -1; Fájl lezárása: int fclose(file *fp); A szöveges fájlban (txt) olvasható formátumban, soronként vannak tárolva az adatok. Egy sor állhat egyetlen karakterből: int fputc( int c, FILE *fp ); vagy egy sztringből: int fputs( const char *s, FILE *fp ); int fprintf(file *fp,const char *format, ); A szövegfájl tartalmának olvasásához az alábbi függvények használhatók. Egy karakter olvasása: int fgetc( FILE * fp );

Sztring olvasása: n-1 karakter (+a lezáró \0 ) olvasása. Ha újsor karaktert vagy fájl vége jelet olvas, a függvény befejezi futását : char *fgets( char *buf, int n, FILE *fp ); Sztring olvasása (space-ig!): int fscanf(file *fp, const char *format, ); Bináris fájlban az adatok nem olvasható formátumban tárolódnak. Az eltárolt objektumok nem csak szekvenciálisan érhetők el, azaz az aktuális fájl pozíció a kívánt helyre mozgatható. A nagyobb adategységek (tömbök, struktúrák) írása, olvasása egyszerűbb (nem igényel sztringkezelő műveleteket). Jelen esetben a struktúra objektum egyetlen függvényhívással írható, olvasható, amelynek adattagjaira a szokásos módon hivatkozhatunk. Szemben a szövegfájllal, ahol a struktúra adattagjait vagy egy sztringbe összefűzve írhatjuk a fájlba, illetve olvashatjuk ki onnan; vagy több függvényhívással egyenként tároljuk és olvassuk vissza. Bináris fájlok írása és olvasása: size_t fwrite(const void *ptr, size_t meret, size_t darab, FILE *fp); size_t fread(void *ptr, size_t meret, size_t darab, FILE *fp); Egy autó struktúra fájlba írása: fwrite(&car, sizeof(car), 1, fp); Egy autó struktúra fájlból olvasása: Pozicionálás fájlban: int fseek(file * fp, long int offset, int origin); Az első paraméter a FILE pointer, a második a pozíció eltolásának mértéke. Ez az elem bájtokban mért nagyságának egész számú többszöröse. Az origin azaz az eltolás kezdete a következő makrókkal adható meg: SEEK_SET, SEEK_CUR és SEEK_END. Ezek jelentése: fájl elejétől, aktuális pozíciótól, illetve a fájl végétől számítjuk az offsetet, ami negatív is lehet. 3. Adatokon végrehajtandó műveletek: 1. Adatok listázása 2. Új adat felvitele 3. Adat törlése 4. Keresés 3.1 Listázás A fájlt az elejétől kezdve végig kell olvasni és minden adatot kiírni a képernyőre. a) Bináris fájlból A fájl megnyitása után (megnyitási mód: rb) az elejéről indulva minden ciklusiterációban eggyel előre mozgatjuk a fájl pointert ( i a ciklusváltozó) és kiolvassuk az aktuális adatot. De mi lesz a ciklus kilépési feltétele? Addig dolgozom fel a tárolt adatokat, amíg el nem érek a fájl végére. printf(...); A fájl méretének meghatározása úgy történik, hogy a végére pozicionálunk és az aktuális pointer pozíció értékét elosztjuk a struktúra méretével.

fseek(fp, 0L, SEEK_END); int filesize = ftell(fp)/sizeof(car); b) Szövegfájlból A fájl megnyitása után (megnyitási mód: rt) az elejéről indulva minden ciklusiterációban kiolvasunk egy sort a fájlból. A tárolt sorok számának meghatározása: int number_of_lines = 0; while((ch = fgetc(fp))!= EOF) { if(ch == '\n') number_of_lines++; Ezt követően újra a fájl elejére lépünk (rewind) és soronként kiíratjuk a fájl tartalmát. rewind(fp); for (i=0; i<number_of_lines; i++) { if (fscanf(fp, "%s %s %s %d %lf", car.rendszam, car.tipus, car.szin, &car.gyart_ev, &car.ar)==0) { printf("hiba"); break; printf("\nrendszám: %s, Tipus: %s, Szin: %s, Gyártási év: %d, Ár: %.0f", car.rendszam, car.tipus, car.szin, car.gyart_ev, car.ar); 3.2 Új adat felvitele Adatfelvitelhez a fájlt hozzáfűzés módban (a) nyitjuk meg. Ennél a feladatnál a legfontosabb feladat az adatbevitel ellenőrzése. A megadott adatok szintaktikai ellenőrzéséhez azt kell tudni, hogy a scanf függvény visszatérési értéke a sikeresen beolvasott értékek száma. De van-e lehetőség az adatok szemantikai ellenőrzésére? Jelen esetben a rendszám az autók egyedi azonosítója. Tehát az adatok fájlba írása előtt meg kell nézni, hogy a megadott rendszám létezik-e már. Vagyis végig kell olvasni a fájlt és minden tárolt rendszámot össze kell hasonlítani azzal, amit most szeretnénk felvinni. Ha nincs találat, a rendszám egyedi és a megadott adatok eltárolhatók. a) Felvitel bináris fájlba Egymás után bekérjük a struktúra adattagjait, majd az fwrite függvénnyel az egész struktúrát egyben eltároljuk. fwrite(&car, sizeof(car), 1, fp); Felvitel előtt a rendszám ellenőrzése: if (strcmp(car.rendszam, rsz) == 0) return 1; /* már létezik */ else return 0; /* nem létezik */ a) Felvitel szövegfájlba Egymás után beolvassuk a struktúra adattagjait, majd az fprintf függvénnyel az egész struktúrát egy sorban eltároljuk.

fprintf(fp, "%s %s %s %d %f\n", car.rendszam, car.tipus, car.szin, car.gyart_ev, car.ar); Felvitel előtt a rendszám ellenőrzése: while (!feof(fp)) { fscanf(fp, "%s %s %s %d %lf", car.rendszam, car.tipus, car.szin, &car.gyart_ev, &car.ar); if (strcmp(car.rendszam,rsz) == 0) return 1; 3.3 Adat törlése Egy autó struktúra eltávolítása a fájlból nem triviális feladat. Szükségünk van egy segédfájlra: ebbe átmásoljuk a törlendő struktúrán kívül az összes többi adatot. Majd az eredeti fájlunkat újraírási módban (w) megnyitva, visszaírjuk ide a segédfájl tartalmát. Az újraírási mód azt jelenti, hogy a nem létező fájl létrejön, a létező pedig felülíródik. Figyelem! A segédfájlt mindig újra kell írni, és mivel vissza is kell olvasni a tartalmát a megnyitási mód: w+. 1. lépés: segédfájlba átírás (bináris fájlkezelés) if (strcmp(car.rendszam, rendszam)!= 0) /* ha nem a törlendő */ fwrite(&car, sizeof(car), 1, fp_tmp); 2. lépés: visszaírás az eredeti fájlba (bináris fájlkezelés) for (i=0; i<filesize-1; i++) { fseek(fp_tmp,sizeof(car)*i,seek_set); fread(&car,sizeof(car),1,fp_tmp); fwrite(&car, sizeof(car), 1, fp); 3.4 Keresés A keresésnél először azt kell eldönteni, hogy mi alapján keresünk (rendszám, típus, stb.). Mivel a rendszám egyértelműen kijelöl egy struktúrát, ha rendszám szerint keresünk biztosan 1 autó lesz a keresés eredménye. Ha a többi adattag szerint akarunk szűrni, valószínűleg egynél több találatot kapunk. A rendszám alapján történő keresésnél ugyanaz a kód használható, mint a rendszám ellenőrzésnél. A típus alapján történő keresés bináris fájl esetén: if (strcmp(car.tipus,tipus) == 0) return 1; A feladat megoldását a C_bin_fajlkezeles ill. a C_txt_fajlkezeles CodeBlocks projektek tartalmazzák.

Önállóan megoldandó feladatok: 1. Valósítsa meg az adattörlés és keresés funkciókat szövegfájl esetén is. 2. Adatfelvitel előtt végezzen szemantikai ellenőrzést a gyártási évre: 1997 <= gyártási év <= 2017. 3. Számítsa ki a fájlban eltárolt autók átlagárát. 4. Kérdezze le az eltárolt piros autók darabszámát. 5. Keresse meg a legdrágább autót a fájlban. 6. Csökkentse az összes autó árát 10%-al. Adatmódosítás: az aktuális fájl pozícióra kell ráírni a módosított adatokat, ekkor a fájl megnyitási mód r+. Bináris fájl esetén fájlba írás (fwrite) előtt vissza kell lépni egy fájlpozíciót: fseek(fp,sizeof(car)*-1,seek_cur); Házi feladat: Az autók mellett tároljuk el a tulajdonosok adatait is külön fájlban. Ehhez definiáljunk egy új struktúrát. typedef struct tulaj { int id; char nev[20]; char cim[50]; Tulaj; A definícióból látható, hogy minden tulajdonos struktúrához hozzárendelünk egy sorszámot (int id). Ez segít az adatsorok egyértelmű beazonosításban. Hiszen sok Szabó Tamás él Magyarországon, akik akár ugyanazon a lakcímen is élhetnek (apa és fia). Ez a sorszám akkor használható azonosítóként, ha minden sorszámot csak egyszer osztunk ki. A tulajdonosok adatainak kezelése egyébként az autó adatok kezeléséhez hasonló (listázás, felvitel, törlés, keresés). Azért, hogy a két feladatrész elkülönüljön, az adatkezelő műveleteket megvalósító függvényeket külön forrásfájlokban (modulokban) definiáljuk. Így a két nyilvántartást külön, egymástól függetlenül vezetjük. Ha azt szeretnénk, hogy az autók a tulajdonosaikkal össze legyenek kapcsolva, azaz az autókat lekérdezve a tulajdonos adatait is lássuk, illetve a tulajdonosok listáján a hozzájuk kapcsolódó autók adatai is szerepeljenek, a struktúra definíción kell változtatni. Ha a tulajdonos struktúrába felveszek egy autója rendszáma adattagot, akkor ez azt jelenti, hogy egy emberhez csak egy autót tudok kötni. Hogyan tudom megadni, ha több autója van? 1. Vegyem fel többször a tulajdonost a nyilvántartásba? 2. Az autója rendszáma adattag legyen tömb? Mekkora legyen a tömb mérete? Egyik sem tökéletes megoldás, mert felesleges memóriafoglalással jár és például a tulajdonos több példányban történő eltárolása a törlésnél problémát okozhat. Próbáljuk meg inkább az autó struktúrában tárolni a tulajdonost. Ha tulajdonos alatt az autó üzembentartóját értjük, akkor igaz az az állítás, hogy minden autónak csak egy üzembentartója van. Felmerül a kérdés, hogy akkor az autó struktúrán belül legyen a tulajdonos struktúra definiálva (beágyazott struktúra)? Ha abból indulunk ki, hogy minden autónak van tulajdonosa, akkor igen. De vizsgáljuk meg a kérdést a tulajdonos szemszögéből is. Minden tulajdonosnak egy autója van? Ha nem, akkor minden autó objektumnál újra fel kell venni az adatait és el kell tárolni. Tehát célszerű a két struktúrát külön definiálni és az autó struktúrában csak egyetlen adattaggal hivatkozni a tulajdonosára. Milyen típusú legyen ez az adattag? Célszerű a tulajdonost egyértelműen azonosító adatot választani (jelen esetben az id adattagot).

typedef struct car { Car; char rendszam[7]; char tipus[20]; char szin[10]; int gyart_ev; double ar; int tulaj_id; //új adattag: autó tulajdonosa Feladatok: 1. Vezessen be ellenőrzést az autók felvitelénél: csak létező (a tulajdonos fájlban megtalálható) tulajdonos azonosítót lehessen megadni. 2. A tulajdonosok törlése előtt végezzen ellenőrzést: ne lehessen olyan tulajdonost törölni, akire van hivatkozás az autó nyilvántartásban (azonosítója szerepel az autó tulajdonosok között). 3. Készítsen összefésült listákat: 3.1 Az autók listázásánál a tulajdonos adatait is lássuk. 3.2 A tulajdonosok listázásánál a hozzájuk tartozó autók adatai is jelenjenek meg.