Programozás I. Adatállományok dr Póder Margit f. docens Rendszer és Szoftvertechnológia Tanszék
Számítástechnika Tanszék Pécs, Adatállományok kezelése Szöveges állományok: A szöveges file tetszőleges hosszúságú sorokból épül fel, a sor végét (MS-DOS állományok esetén) CR/LF zárja, az állomány végét az EOF vezérlő karakter jelzi. Például ilyenek a C++ forrásfileok, a txt kiterjesztésű fileok, stb. Bináris állományok: A bináris állományok byteokból épülnek fel. (A szöveges állomány is feldolgozható, mint bináris file.).
Számítástechnika Tanszék Pécs, Adatállományok kezelése Bináris állományok: A bináris állományok byteokból épülnek fel. (A szöveges állomány is feldolgozható, mint bináris file.) Alapvető különbség van a két file-típus között pl. a számok tárolásában. A 2002 egy szöveges állományban a ’2’, ’0’, ’0’, ’2’ karakterek sorozatával kerül letárolásra, míg bináris állományban a szám a short int típusnak megfelelően, 2 byton kerül letárolásra úgy, ahogyan a memóriában megjelenik. Példa: €?..\MUNKA\BINFILE.CPPĽ???TC86 Borland C++ C:\BORLANDC.310\INCLUDE\_NFILE.H-
Számítástechnika Tanszék Pécs, Adatállományok kezelése A file-kezelés lépései: 1. a file-t azonosító mutató definiálása 2. az állomány megnyitása 3. az állomány tartalmának feldolgozása file-műveletek (olvasás, írás, pozicionálás, stb. ) felhasználásával. 4. az állomány lezárása.
Számítástechnika Tanszék Pécs, Adatállományok kezelése A file mutató definiálása A programban mindegyik felhasználni kívánt állományhoz egy külön file mutatót kell létrehozni. FILE * típusú file-mutató azonosítja az állományt. A definició: #include..... FILE * f1
Számítástechnika Tanszék Pécs, Adatállományok kezelése A file megnyitása A háttértárolón lévő file tartalmához csak a file megnyitása után férhetünk hozzá. A megnyitáskor meg kell adni a file típusát (szöveges vagy bináris) és a hozzáférés módját. A megnyitás általános formája: FILE *fopen (const char *filename, const char *mode); ahol filename az állomány neve, ahogyan az operációs rendszerben használjuk (tartalmazhatja a teljes elérési útvonalat is, ekkor figyelni kell arra, hogy a \ karakter string konstansban való megadása: \\) mode : ez is egy string, amely a file elérését és típusát határozza meg.
Számítástechnika Tanszék Pécs, Adatállományok kezelése A file megnyitása, a mode string Szöveges file Bináris file ”r”, ”rt” "rb” Létező file megnyitása olvasásra ”w”, wt””wb” Új file megnyitása írásra. Ha a file már létezik, akkor a tartalma elvész. ”a”, ”at””ar” A file megnyitása a file végéhez való hozzáírásra. Ha a file nem létezik, akkor a file létrejön. ”r+”, ”a+t””r+b” Létező file megnyitása írásra és olvasásra. ”w+”, ”w+t””w+r” Új file megnyitása írásra és olvasásra (update). Ha a file már létezik, tartalma elvész. ”a+”, ”a+t” ”a+r” A file megnyitása a file végén végzett írásra és olvasásra (update). Ha a file nem létezik, akkor létrejön.
Számítástechnika Tanszék Pécs, Adatállományok kezelése A file megnyitása Az fopen függvény visszatérési értéke FILE * típusú mutató, amely sikeres megnyitás esetén kijelöli a filehoz tartozó FILE struktúrát a memóriában, s ezután következhetnek a file kezelés lépései. Sikertelen file nyitás esetén az fopen függvény NULL pointert ad vissza: FILE *f1; f1 = fopen (”C:\\MUNKA\\ADAT1.DAT”, ”rt”); if (f1 == NULL) { printf (”\nSikertelen file nyitási kísérlet ”); exit (0); }
Számítástechnika Tanszék Pécs, Adatállományok kezelése A file lezárása A használat végén fclose függvény hívással le kell zárnunk az írásra és/vagy olvasásra megnyitott fileokat. A file lezárásakor a memóriában a filehoz tartozó pufferek és más területek automatikus felszabadítása is megtörténik. Ha az állományon írási műveletet hajtottunk végre, akkor zárás előtt a memóriában található átmeneti pufferek tartalmát célszerű a fileba írni. FILE *f1;.... fflush (f1); fclose (f1);
Számítástechnika Tanszék Pécs, Adatállományok kezelése A file végének vizsgálata A file olvasásakor az feof függvény 1 értéke jelzi a file vége esemény bekövetkezését. int feof (FILE *f); A file vége figyelést általában while ciklusban végezzük. while (! feof (f1)) { fscanf (f1,......); // olvasás a fileból } close (f1);
Számítástechnika Tanszék Pécs, Adatállományok kezelése Pozicionálás a fileban A file elejére a rewind függvénnyel pozícionálhatunk: rewind (f1); Tetszőleges pozíció kiválasztása az fseek függvénnyel történhet: int fseek (FILE -stream, long offset, int honnan); ahol offset a file pozíció relatív távolsága a honnan paraméter által kijelölt pozícióhoz képest. a honnan paraméter lehetséges értékei: SEEK-CURaz aktuális pozícióhoz képest SEEK-ENDa file végéhez képest SEEK-SETa file elejéhez képest. Az aktuális pozíció lekérdezhető az ftell függvénnyel: long ftell (FILE *stream);
Számítástechnika Tanszék Pécs, Adatállományok kezelése Hibakezelés A hibák kezelésére az alábbi függvényeket használhatjuk: feof (fp)0 a visszatérési érték, ha elértük a file végét (ez nem mindig jelent hibát !) ferror (fp)0 a visszatérési érték, ha az utolsó file művelet során hiba volt. (A stream hiba-jelző adatát teszteli.) clearerror (fp) alaphelyzetbe állítja a stream hiba- és file-vége jelzőjét.
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése A megnyitott szöveges adatállományok írására és olvasására az alábbi függvényeket használhatjuk: Karakter írása és olvasása:int fputc (int c, FILE *stream); int fgetc (FILE *stream); String írása és olvasásaint fputs (const char *s, FILE *stream); char * fgets (char *s, int n, FILE *stream); Formázott adatok írása és olvasása: int fprintf (FILE *stream, const char *format,...); int fscanf (FILE *stream, const char *format,...);
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése String írása és olvasása: 7.1. feladat Olvassa be a billentyűzetről, majd soronként írja egy szöveges állományba az egyik kedvenc versének első versszakát. Olvassa vissza a fileból a szöveget és írassa a képernyőre soronként. Számolja meg, hogy egy input adatként bekért magánhangzó hányszor fordul elő a szövegben.
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.1. feladat void main (void) { FILE *ft; char puffer [80]; int i=1; char ch, mgh; clrscr (); if ((ft = fopen ("C:\\MUNKA\\vers.txt","w+")) == NULL) { //megnyitás: írás+olvasás printf ("\nNem sikerült megnyitni a C:\MUNKA\vers.txt állományt"); exit (-1); }
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.1. feladat printf ("\nKérem a szöveget soronként, * végjelig."); do { printf ("\nAz %2d. sor:",i); gets (puffer); if (puffer [0] != '*') { strcat (puffer, "\n"); fputs (puffer, ft); } i++; } while (puffer [0] != '*'); fflush (ft);
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.1. feladat clrscr (); rewind (ft); //pozicionálás a file elejére !! i=0; printf ("\nA letárolt szöveg:\n"); fgets (puffer, 80, ft); while (!feof (ft)) { i++; printf ("%d. sor: %s",i, puffer); fgets (puffer, 80, ft); }
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.1. feladat rewind (ft); //pozicionálás a file elejére újra i=0; printf ("\nMelyik magánhangzót keressük:\n"); fflush (stdin); mgh = getche (); ch = fgetc (ft); //olvasás a fileból karakterenként while (!feof(ft)) { if (ch == mgh) i++; ch = fgetc (ft); } printf ("\nA szövegben %d db '%c' karakter van",i,mgh);
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.1. feladat fclose (ft); //a file lezárása getch (); }
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése Formázott adatok írása és olvasása: 7.2. feladat Olvassa be billentyűzetről és írja text fileba egy tanulócsoport tagjairól az alábbi adatokat:Név, 3 db zh pontszáma. Készítsen listát a felvitt adatokról. Számítsa ki külön az első, a második és a harmadik zh átlagát.
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.2. feladat //1. struct csopzh { char nev [21]; int zh [3]; }; void main (void) { //2. void felvitel (char *); int lista (char *); int atlagok (char *, float[]);
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.2. feladat //3. char filenev [] = "C:\\munka\\zh2002.txt" ; int i, menu = 1; float atlag [3]; //4. do { clrscr (); switch (menu) { case 1 : felvitel (filenev); break;
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.2. feladat case 1 : felvitel (filenev); break; case 2 : if (!lista (filenev)) printf ("\nNem sikerült megnyitni a %s állományt",filenev); break; case 3 : if (!atlagok (filenev, atlag)) printf ("\nNem sikerült megnyitni a %s állományt",filenev); else for (i=0;i<3;i++) printf ("\nAz %d. zh átlaga:%8.2f",i+1, atlag [i]); break; }
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.2. feladat //5. getch (); clrscr (); printf ("\n1 Felvitel"); printf ("\n2 Lista"); printf ("\n3 Átlagok"); printf ("\nBármely más billentyűre: vége\n"); printf ("\n\nKérem, válasszon !"); fflush (stdin); menu = getche ()-48; } while (menu >1 && menu < 4); printf ("\nKöszönöm az együttműködést !\n\nVÉGE");
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.2. feladat //6. void felvitel (char *fn) { FILE *ft; struct csopzh csoport; int i; if ((ft = fopen (fn,"w")) == NULL) //megnyitás: írásra return;
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.2. feladat do { printf ("\nKérem az egytagú nevet(*, ha nincs több):"); fflush (stdin); gets (csoport.nev); if (csoport.nev[0] == '*') continue; printf ("\nKérem a három pontszámot vesszővel elválasztva:"); fflush (stdin); scanf ("%d,%d,%d",&csoport.zh[0],&csoport.zh[1],&csoport.zh[2]); fprintf (ft, "%s\n", csoport.nev); for (i=0;i<3;i++) fprintf (ft, "%3d\n",csoport.zh[i]); } while (csoport.nev[0] != '*');
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.2. feladat //9. puffer ürítés, majd file zárás... fflush (ft); fclose (ft); }
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.2. feladat //10. int lista (char *fn) { FILE *ft; struct csopzh cs; int i; if ((ft = fopen (fn,"r")) == NULL) return 0; printf ("\nL I S T A\nNév zh1 zh2 zh3");
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.2. feladat //11. fscanf (ft, "%s", cs.nev); while (!feof (ft)) { for (i=0; i<3; i++) fscanf (ft, "%d",&cs.zh[i]); printf ("\n%-20s%5d%5d%5d",cs.nev, cs.zh[0],cs.zh[1],cs.zh[2]); fscanf (ft, "%s", cs.nev); } printf ("\n\nBillentyűre vár..."); getch (); fclose (ft); return 1; }
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.2. feladat //13. int atlagok (char *fn, float atl[]) { FILE *ft; struct csopzh cs; int i, db=0; //db:meg kell számolni, mennyien vannak a hallgatók //14. if ((ft = fopen (fn,"r")) == NULL) return 0; printf ("\nÁ T L A G O K számítása\n"); for (i=0;i<3;i++) atl[i] = 0;
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.2. feladat fscanf (ft, "%s", cs.nev); //Miért kell... while (!feof (ft)) { for (i=0; i<3; i++) { fscanf (ft, "%d",&cs.zh[i]); atl [i] += cs.zh [i]; } db++; fscanf (ft, "%s", cs.nev); }
Számítástechnika Tanszék Pécs, Szöveges állományok kezelése 7.2. feladat //15. for (i=0;i<3;i++) atl [i] = atl [i]/db; printf ("\n\nBillentyűre vár..."); getch (); fclose (ft); return 1; }
Számítástechnika Tanszék Pécs, Bináris állományok kezelése A bináris állományok kezelése byteonként, vagy blokkonként végezhető el. A byteos kezeléshez az fgetc és az fputc függvények adnak lehetőséget. A memóriablokkok fileba írása az fwrite, fileból visszaolvasása az fread függvénnyel végezhető: size_t fread (void *ptr, size_t size, size_t n, FILE *stream); size_t fwrite (const void *ptr, size_t size, size_t n, FILE *stream); Mindkét függvény adott size méretű adat-elemekkel dolgozik, ezekből n darabot ír ki vagy olvas be a függvényhívás során. A függvények visszatérési értéke a ténylegesen kiírt vagy a visszaolvasott elemek (nem byteok!) számát adja meg. Mivel a C-ben nem létezik a rekordos file fogalma, ezért a rekordok írására és olvasására is a fenti függvényeket használjuk.
Számítástechnika Tanszék Pécs, Bináris állományok kezelése 7.3. feladat Olvassa be billentyűzetről és írja bináris fileba egy tanulócsoport tagjairól az alábbi adatokat: Név, 3 db zh pontszáma. Készítsen listát a felvitt adatokról. Számítsa ki külön az első, a második és a harmadik zh átlagát.
Számítástechnika Tanszék Pécs, Bináris állományok kezelése 7.3. feladat //1. typedef struct csopzh { char nev [21]; int zh [3]; } cszh; void main (void) { //2. void felvitel (char *); int lista (char *); int atlagok (char *, float[]);
Számítástechnika Tanszék Pécs, Bináris állományok kezelése 7.3. feladat //3. char filenev [] = "C:\\munka\\zh2002.dat" ; int i, menu = 1; float atlag [3]; //4. do { clrscr (); switch (menu) { case 1 : felvitel (filenev); break;
Számítástechnika Tanszék Pécs, Bináris állományok kezelése 7.3. feladat switch (menu) { case 1 : felvitel (filenev); break; case 2 : if (!lista (filenev)) printf ("\nNem sikerült megnyitni a %s \ állományt",filenev); break; case 3 : if (!atlagok (filenev, atlag)) printf ("\nNem sikerült megnyitni a %s \ állományt",filenev); else for (i=0;i<3;i++) printf ("\nAz %d. zh átlaga:%8.2f",i+1, atlag [i]); break; }
Számítástechnika Tanszék Pécs, Bináris állományok kezelése 7.3. feladat //6. void felvitel (char *fn) { FILE *fb; cszh csoport; int i, rsz; if ((fb = fopen (fn,"w+b")) == NULL) //megnyitás: írásra return;
Számítástechnika Tanszék Pécs, Bináris állományok kezelése 7.3. feladat //7. do { printf ("\nKérem az egytagú nevet(*, ha nincs több):"); fflush (stdin); gets (csoport.nev); if (csoport.nev[0] == '*') continue; printf ("\nKérem a három pontszámot vesszővel elválasztva:"); fflush (stdin); scanf ("%d,%d,%d",&csoport.zh[0],&csoport.zh[1],&csoport.zh[2]); rsz = fwrite (&csoport, sizeof (cszh), 1, fb); } while (csoport.nev[0] != '*');
Számítástechnika Tanszék Pécs, Bináris állományok kezelése 7.3. feladat //9. puffer ürítés, majd file zárás... fflush (fb); fclose (fb); }
Számítástechnika Tanszék Pécs, Bináris állományok kezelése 7.3. feladat //10. int lista (char *fn) { FILE *fb; cszh cs; int i, rsz = 1 ; if ((fb = fopen (fn,"r+b")) == NULL) return 0; printf ("\nL I S T A\nNév zh1 zh2 zh3");
Számítástechnika Tanszék Pécs, Bináris állományok kezelése 7.3. feladat while (rsz) { rsz = fread(&cs, sizeof (cszh), 1, fb); if (rsz) printf ("\n%-20s%5d%5d%5d",cs.nev, cs.zh[0],cs.zh[1],cs.zh[2]); } printf ("\n\nBillentyűre vár..."); getch (); //12. fclose (fb); return 1; }
Számítástechnika Tanszék Pécs, Bináris állományok kezelése 7.3. feladat //13. int atlagok (char *fn, float atl[]) { FILE *fb; cszh cs; int i, db=0; //db:meg kell számolni, mennyien vannak a hallgatók int rsz = 1; if ((fb = fopen (fn,"r+b")) == NULL) return 0; printf ("\nÁ T L A G O K számítása\n"); for (i=0;i<3;i++) atl[i] = 0;
Számítástechnika Tanszék Pécs, Bináris állományok kezelése 7.3. feladat while (rsz) { rsz = fread(&cs, sizeof (cszh), 1, fb); if (!rsz) break; for (i=0; i<3; i++) atl [i] += cs.zh [i]; db++; } for (i=0;i<3;i++) atl [i] = atl [i]/db; printf ("\n\nBillentyűre vár..."); getch (); fclose (fb); return 1; }
Számítástechnika Tanszék Pécs, Adatállományok - teszt 1. A szöveges állomány is feldolgozható, mint bináris file. 2. A file megnyitása után következik a file-t azonosító mutató definiálása 3.A megnyitáskor a file típusát (szöveges vagy bináris) kell csak megadni 4.A bináris állományok kezelése byteonként, vagy blokkonként végezhető 5. A C-ben nem létezik a rekordos file fogalma.
Számítástechnika Tanszék Pécs, Adatállományok - teszt 1. A szöveges állomány is feldolgozható, mint bináris file. 2. A file megnyitása után következik a file-t azonosító mutató definiálása 3.A megnyitáskor a file típusát (szöveges vagy bináris) kell csak megadni 4.A bináris állományok kezelése byteonként, vagy blokkonként végezhető 5. A C-ben nem létezik a rekordos file fogalma.