7. gyakorlat Fájlkezelés IO haladó Függvények haladó
Fájlkezelés A C-ben a fájlkezelés ún. fájlstream-eken keresztül történik, melyek puffereltek ha valamit a streamre küldünk, nem biztos, hogy rögtön kiíródik a fájlba. A 3 eddig tanult iostream stdin - standard bemenet (billentyűzet) stdout - standard kimenet (konzol) stderr - standard hibakimenet (konzol) Ha mást szeretnénk használni új parancsokra lesz szükségünk.
Fájlkezelés A fájlstreamek megnyitásához létre kell hozni egy FILE* típusú változót, majd az fopen függvénnyel meg kell nyitnunk a fájlt. Példa: FILE* fajlom; fajlom = fopen("név", "mód"); A név a fájl elérési útja, (abszolút, vagy relatív, relatív esetén a kezdőpont (az aktuális mappa) a program futtatható állományának mappája) a mód pedig a fájl megnyitásának módját jelzi. Használat után a streamet MINDEN ESETBEN le kell zárni az fclose(stream); paranccsal. (Pl. fclose(fajlom);) A puffer ürítésére használható az fflush(stream); parancs, ami azonnal kiír mindent a fájlba, amit még nem írt ki a pufferből. Ez stream lezárásakor automatikusan megtörténik, kézzel csak pl. olvasás és írás közötti váltáskor kell meghívni.
fopen paraméterezése A mód 1-3 karakteres sztring, formája: 1. karakter: r, ha olvasásra nyitjuk meg fájlnak léteznie kell a parancs kiadásakor w ha írásra a fájlt létrehozza, ha nem létezik, ha már létezett, korábbi tartalma törlődik a, ha hozzáfűzésre a fájlt létrehozza, ha nem létezik. Ha már létezett, az új adatok a fájl végére kerülnek 2. karakter: +. Ha szerepel, a stream a másik műveletet is támogatni fogja r+ írható is lesz (de csak létező fájl nyitható meg és megnyitáskor a tartalma megmarad) w+ olvasható is lesz (de megnyitáskor a korábbi tartalma törlődik) a+ szintén támogatni fogja az olvasást, de az olvasás a fájl korábbi részén, az írás pedig az az utáni részen történik. 3. karakter: b, ha a fájl bináris fájl (pl. egy program, ebben bármilyen karakterek bárhol szerepelhetnek), t, ha szöveges fájl (speciális sorvégjelekkel, és fájl vége jellel). Ha elhagyjuk, szövegesnek tekinti a fájlt, mintha t-t írtunk volna. A 2. és 3. karakter felcserélhető, tehát pl. r+b és wt+ is érvényes módok.
F: Írj egy programot, ami beolvas két egész számot, majd kiírja az összegüket és a szorzatukat. #include <stdio.h> int a, b; scanf("%d %d", &a, &b); printf("osszeg: %d\nszorzat: %d\n", a+b, a*b);
F: Módosítsuk úgy a programot, hogy használja az stdin, stdout, fscanf és fprintf függvényeket. #include <stdio.h> int a, b; fscanf(stdin, "%d %d", &a, &b); fprintf(stdout, "Osszeg: %d\nszorzat: %d\n");
F: Módosítsuk úgy a programot, hogy valódi fájlokat használjon. #include <stdio.h> int a, b; FILE *infile; FILE *outfile; infile = fopen("be.txt", "r"); outfile = fopen("ki.txt", "w"); fscanf(infile, "%d %d", &a, &b); fprintf(outfile, "Osszeg: %d\nszorzat: %d\n", a + b, a * b); fclose(infile); fclose(outfile);
F: Hibakóddal lépjen ki a program, ha valamelyik fájl megnyitása nem sikerült. #include <stdio.h> int a, b; FILE *infile; FILE *outfile; if(!(infile = fopen("be.txt", "r"))) { return 1; if(!(outfile = fopen("ki.txt", "w"))) { fclose(infile); return 1; fscanf(infile, "%d %d", &a, &b); fprintf(outfile, "Osszeg: %d\nszorzat: %d\n", a + b, a * b); fclose(infile); fclose(outfile);
Vége a fájlnak? Ha szeretnénk megállapítani, hogy elértük-e már a fájl végét, erre két módszerünk is van: a feof(file) függvény igazat ad vissza, ha az átadott FILE* típusú változó által mutatott streamben elértük a fájl végét a legtöbb beolvasó függvény az EOF konstanssal tér vissza, ha semmit nem tudott beolvasni, mivel elérte a fájl végét. Módszer 1: while (!feof(fajlom)) { fgetc (fajlom); //csinálunkvalamit Módszer 2: do { c = fgetc (fajlom); //csinálunkvalamit while (c!= EOF);
IO haladó A printf és scanf függvények nevében az f formázott műveleteket jelöl: megadhatunk egy "formátumsztringet", ami a várt input/kívánt output szerkezetét megadja, illetve különböző argumentumokat rendelhetünk a "formátum tagekhez". A formátumtagek % karakterrel kezdődnek. Erről kimerítő leírás olvasható a cplusplus.com printf, illetve scanf oldalán.
F: Írj egy programot, ami beolvas egy előjeltelen short int értéket, és nyolcas számrendszerbe átváltva írja ki. #include <stdio.h> unsigned short int v; scanf("%hu", &v); printf("%ho\n", v);
F: Írj egy programot, ami beolvas egy hexadecimális egész számot, majd 15 karakter szélességben kiírja a decimális értékét, mindenképpen előjellel és vezető nullákkal. #include <stdio.h> unsigned int v; scanf("%x", &v); printf("%+015u\n", v);
F: Olvass be egy double és egy egész értéket, majd a valós értéket írasd ki az egészben megadott pontossággal. #include <stdio.h> double ertek; int pontossag; scanf("%lf %d", &ertek, &pontossag); printf("%1.*lf\n", pontossag, ertek);
F: Olvass be egy csupa kisbetűből álló, legfeljebb 20 karakteres sztringet, majd írasd ki 10 karakteren jobbra igazítva az első legfeljebb 8 karakterét. A bemeneten a kisbetűket közvetlenül bármi követheti. #include <stdio.h> char str[21]; scanf("%20[a-z]", str); printf("%10.8s\n", str);
F: Egy sor kiíratási formátuma: "nev: %s; pont: %d;". Olvasd be a kiírt számot úgy, ha tudod, hogy a kiírt sztring nem tartalmazhat pontosvesszőt. Ellenőrízd le, hogy az input sor valóban helyes-e. #include <stdio.h> int val, ret; ret=scanf("nev: %*[^;]; pont: %d;", &val); if(ret==1) { printf("a szam: %d\n", val); else { printf("helytelen formatum\n");
Egyéb függvények getchar: egy karakter beolvasása char c = getchar(); putchar: egy karakter kiírása putchar('a'); gets: egy sztring beolvasása char str[20]; gets(str); Egy egész sort beolvas, a végén az új sor karaktert NEM menti bele a stringbe (de a pufferből kiveszi). Vigyázni kell, hogy az átadott str változó elég nagy legyen. A C99 szabványtól kezdve használata nem ajánlott, a C11-ből pedig hiányzik, helyette a biztonságosabb gets_s használható benne. puts: egy sztring kiírása puts("ez egy szöveg"); Egy egész sort kiír, tehát végül kiír egy további újsor karaktert is.
F: Írasd ki a fájlvége jelig (^D) tartó bemenetet úgy, hogy a számjegyeket törlöd belőle. A végén írd ki, hogy hány számjegyet töröltél. #include <stdio.h> int c, d=0; while((c=getchar())!=eof) { if('0'<=c && c<='9') { d++; else { putchar(c); printf("\n--\n%d torolve\n", d);
Rekurzív függvények Egy függvény önmagát is meghívhatja, ezt rekurziónak, az ilyen függvényt rekurzív függvénynek nevezzük. Ez olyan esetekben hasznos, ha egy probléma vele azonos, de a megoldáshoz közelebb álló problémára vezethető vissza, mígnem egy olyan problémát kapunk, ami már triviálisan megoldható. Rekurzív függvényeknél NAGYON FONTOS, hogy minden esetben legyen kilépési feltétel (ami előbb utóbb teljesül is), tehát egy olyan eset, amikor nem történik több rekurzív hívás.
F: Fibonacci-sorozat n. elemének kiszámítása rekurzív módszerrel #incude <stdio.h> int fib(int n) { if(n==1 n==2) { return 1; else { return fib(n-1) + fib(n-2); int n; printf("n erteke?:\t"); scanf("%d", &n); printf("a Fibonacci-sorozat %d. eleme:\t%d", fib(n));
Feladatok - Add meg N-dimenziós vektorok sorozatának összegét. A program először bekéri a vektorok méretét (max 100), majd a vektorokat. A vektorok a végpont valós koordinátáival adottak. A sorozat végét a nulla vektor jelzi. A program fájlból olvassa az adatokat és az eredményt is fájlba írja! A bemeneti fájl első sorában 2 szám van szóközzel elválasztva: az első a vektor mérete (N), a második a vektorok száma (M). Ezután M sor található, mindegyikben N db számmal, ezek az egyes vektorok koordinátái. (Egy sor egy vektor). Ezesetben végjelre (0 vektorra a sorozat végén) nincs szükség. A kimeneti fájlban egy sor legyen, benne (szóközökkel elválasztva) az összegvektor koordinátái. Hogyan lehetne azt megoldani, hogy a vektorok számát ne kelljen megadni, és végjel se legyen?
Feladatok Írd meg az alábbi függvényeket úgy, hogy a megvalósításuk a main függvény mögött legyen. Írj egy főprogramot, amelyik mindegyik függvényt legalább egyszer meghívja. fact : kiszámolja egy szám faktoriálisát rec : kiszámolja egy szám reciprokát sqr : kiszámolja egy szám négyzetét cube : kiszámolja egy szám köbét add : kiszámolja két szám összegét sub : kiszámolja két szám különbségét mul : kiszámolja két szám szorzatát per : kiszámolja két szám hányadosát div : kiszámolja két szám egészosztásának hányadosát mod : kiszámolja két szám egészosztásának maradékát
Puzzle #include <stdio.h> void e(int); int a = 3; e(a); putchar('\n'); void e(int n) { if (n > 0) { e(--n); printf("%d ", n); e(--n); Melyik a program outputja? Miért? a) 0 1 2 0 b) 0 1 2 1 c) 1 2 0 1 d) 0 2 1 1
Puzzle2 int foo(int x, int n) { int val = 1; if (n > 0) { if (n % 2 == 1) val *= x; val *= foo(x * x, n / 2); return val; Mit számol ki a foo függvény? Miért? a) x^n b) x*n c) n^x d) Egyik sem