Programozás I. Széchenyi István Egyetem, Gy r 2013. november 4.
Objektumok attribútumai objektum Konstans vagy változó érték(ek)et tartalmazó, azonosítható memóriaterület. deklaráció Kapcsolatot teremt az objektum és azonosítója (neve) között. Meghatározza az objektum attribútumait. deníció (deníciós deklaráció) Memóriafoglalással járó deklaráció. inicializáció Kezd értékadás az objektumnak. Objektumok rendelkeznek: azonosítóval attribútumokkal: típussal, mely rögzíti a lefoglalandó memória mennyiségét az információ bels ábrázolásának módját tárolási osztállyal, élettartammal, hatáskörrel, láthatósággal, kapcsolódással.
Tárolási osztály Tárolási osztály meghatározza az objektum: élettartamát hatáskörét és kapcsolódását. Tárolási osztály specikátorok: auto, register, extern, static, typedef. Megadható expliciten, de a deklaráció forráskódon belüli helye impliciten is megadja: blokkon belül deklarált objektum mindig auto deníció, blokkon belül deklarált függvény mindig extern deklaráció függvénydeníciók, és függvényen kívüli objektum/függvénydeklarációk extern, statikus tárolási osztályúak. Alapvet en kétféle tárolási osztály létezik: automatikus (auto, register) statikus (static, extern)
Automatikus tárolási osztály élettartam: lokális hatókör: blokkra lokális kapcsolódás: nincs memóriafoglalás automatikusan megtörténik (=deníció) függvény formális paraméterei is automatikus tárolási osztályúak helyfoglalás a program vermében történik nincs implicit inicializáció, de az explicit inicializáció a blokkba lépve mindig megtörténik (hacsak át nem ugorják, ld. goto) blokkon belül deniált objektumok impliciten auto tárolási osztályúak az auto (aé.) és register kulcsszavak csak lokális hatókör objektumok deklarálására használhatóak register: gyakran használt adatot próbálja regiszterben tartani a fordító (ha nem megy: auto) sebesség, méret register típusú változó címére hivatkozni nem lehet
Prímszámok Megállapítja, hogy x prímszám-e. Logikai értékkel tér vissza. int prime(register x) { register osz = 2; if(x < 4) return 1; while(osz*osz <= x) { if(!(x%osz)) return 0; ++osz; if(!(osz&1)) ++osz; } return 1; }
Fibonacci-sorozat Másodrendben rekurzív sorozat. Képzeletbeli nyúlcsalád növekedése: hány pár nyúl lesz n hónap múlva, ha az els hónapban csak egyetlen újszülött nyúl-pár van, az újszülött nyúl-párok két hónap alatt válnak termékennyé, minden termékeny nyúl-pár minden hónapban egy újabb párt szül, és a nyulak örökké élnek. F n = 0, ha n = 0 1, ha n = 1 F n 1 + F n 2 ha n > 1
Fibonacci-sorozat iteratív változat fibonacci.c #include<stdio.h> #define MAX 20 int main(void) { unsigned i=0, j=1, k, n; printf("a Fibonacci-sorozat els %d " "elemének értéke:\n0 1 ", MAX); for(n=2; n<max; n++) { printf("%d ", k=i+j); i=j; j=k; } putchar('\n'); return 0; } Kimenet A Fibonacci-sorozat els 20 elemének értéke: 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
Fibonacci-sorozat rekurzív változat fiborek.c #include<stdio.h> #define N 9 unsigned fiborek(unsigned n) { if(n<2) return n; return fiborek(n-1)+fiborek(n-2); } int main(void) { printf("a Fibonacci-sorozat %d. eleme: %d\n", N+1, fiborek(n)); return 0; } Kimenet A Fibonacci-sorozat 10. eleme: 34
Statikus tárolási osztály Az ilyen objektumok hatókörüket tekintve lehetnek: blokkra lokálisak blokkokon át küls k Élettartam: statikus memóriafoglalás és inicializálás egyszer, a program indításakor történik. Implicit inicializálás: minden bit zérus. Függvényen belüli változó static kulcsszóval tehet statikussá (deníció) Függvényen kívüli deklarációk implicit módon küls (extern), statikus tárolási osztályú objektumokat deniálnak extern: deníció másik fordítási egységben, vagy befoglaló hatáskörben; objektumok esetén explicit módon használva nem történik memóriafoglalás! A static a küls objektumokat és függvényeket lokálissá teszi a fordítási egységre
Fibonacci-sorozat statikus változat fibostat.c #include<stdio.h> #define MAX 20 unsigned fibostat(void) { static unsigned i, j=1; unsigned k=i+j; i=j; return j=k; } int main(void) { unsigned n; printf("a Fibonacci-sorozat els %d " "elemének értéke:\n0 1 ", MAX); for(n=2; n<max; n++) printf("%d ", fibostat()); putchar('\n'); return 0; } Kimenet A Fibonacci-sorozat els 20 elemének értéke: 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
Egyszer számológép pelda20.c, 1. rész #include <stdio.h> #define MAXLINE 20 int getline(char s[], int i); double atof(char s[]); void main(void) { double sum = 0.0; char line[maxline+1]; /* A sor */ printf("gépeljen be egy valós számot!\n" "Közöljük az eddigi összeget.\n" "Vége: EOF vagy üres sor.\n"); while(getline(line,maxline) > 0) printf("\t%.2f\n", sum+=atof(line)); } int getline(char s[], int lim) { int c, i; for(i=0; i<lim && (c=getchar())!=eof && c!='\n'; ++i) s[i]=c; s[i] = '\0'; while(c!=eof && c!='\n') c=getchar(); return(i); }
Egyszer számológép pelda20.c, 2. rész double atof(char s[]) { /* s karakterlánc átalakítása */ double val, power; /* double-lé. Ezt kapjuk vissza. */ int i, sign; /* Üres helyek átlépése a karakterlánc elején */ for(i=0; s[i]==' ' s[i]=='\t'; ++i); /* Az el jel elintézése */ sign = 1; if(s[i]=='+' s[i]=='-') sign=(s[i++]=='+')?1:-1; /* Az egész rész intézése */ for(val=0.0; s[i]>='0'&&s[i]<='9'; i++) val=10.0*val+s[i]-'0'; if(s[i]=='.') i++; /* A tört rész */ for(power=1; s[i]>'0' && s[i]<='9'; i++) { val = 10.0*val+s[i]-'0'; power *= 10.0; } return(sign*val/power); }
Fordított lengyel logikájú (RPN) kalkulátor (1 + 2) (3 + 4) = 1 2 + 3 4 + = Algoritmus while (a következ operátor vagy operandus nem az állomány vége) if (szám) told a verembe else if (operátor) léptesd ki az operandusokat végezd el a m veletet told a verembe az eredményt else hiba
Fordított lengyel logikájú (RPN) kalkulátor puffer.c #define BUFSIZE 100 #include <stdio.h> static char buf[bufsize]; /* Az ungetch() puffere */ static int bufp=0; /* A köv. szabad pozíció a pufferben */ int getch(void) { /* Kiolvas egy (esetleg visszaírt) karaktert */ return((bufp>0)?buf[--bufp]:getchar()); } void ungetch(int c) { /* Karakter visszahelyezése a bemenetre */ if(bufp>bufsize) printf("ungetch: Túl sok karakter!\n"); else buf[bufp++]=c; }
Fordított lengyel logikájú (RPN) kalkulátor verem.c #define MAXVAL 100 /* Értékverem max. mérete */ #include <stdio.h> static int sp=0; /* Veremmutató */ static double val[maxval]; /* Értékverem */ void clear(void); double push(double f) { /* Operandus az értékverembe */ if(sp<maxval) return(val[sp++]=f); else { printf("hiba: a verem megtelt!\n"); clear(); return(0); } } double pop(void) { /* A legfels operandus */ if(sp>0) return(val[--sp]); /* kivétele a veremb l*/ else { printf("hiba: a verem üres!\n"); clear(); return(0); } } void clear(void) { /* A verem ürítése */ sp=0; }
Fordított lengyel logikájú (RPN) kalkulátor kalkulal.c, 1. rész #include <stdio.h> #include <stdlib.h> #define MAXOP 20 /* Operandusok es operátorok max. mérete */ #define NUMBER '0' /* Szám észlelésének jelzése */ #define TOOBIG '9' /* A karakterlánc túl nagy jelzése */ void main(void); double push(double); double pop(void); void clear(void); int getop(char s[], int lim); void main(void) { int type; double op2; char s[maxop]; printf("lengyel kalkulátor.\neof-ig dolgozik!\n\n"); while((type=getop(s, MAXOP))!= EOF) switch(type) { case NUMBER: push(atof(s)); break;...
Fordított lengyel logikájú (RPN) kalkulátor kalkulal.c, 2. rész... case '+': push(pop()+pop()); break; case '*': push(pop()*pop()); break; case '-': op2=pop(); push(pop()-op2); break; case '/': op2=pop(); if(op2!=0.0) push(pop()/op2); else printf("az osztó zérus!\n"); break; case '=': printf("\t%f\n", push(pop())); break; case 'c': clear(); break; case TOOBIG: printf("%s...túl hosszú!\n", s); break; default: printf("%c Ismeretlen parancs!\n", type); break; } }
Fordított lengyel logikájú (RPN) kalkulátor kalkulal.c, 3. rész int getch(void); void ungetch(int c); int getop(char s[], int lim) {/* A köv. operátor/operandus beolvasása */ int c, i; /* Szóközök, tabok és újsor karakterek átlépése */ while((c=getch())==' ' c=='\t' c=='\n'); /* Ha a köv. karakter nem pont és nem számjegy, akkor operátor */ if(c!='.' && (c<'0' c>'9')) return(c); /* Egyébként összegy jtjük a numerikus karakterláncot */ s[0] = c; for(i=1; (c=getch())>='0' && c<='9';i++) if(i<lim) s[i]=c; /* Tizedespont lehet a numerikus karakterláncban */ if(c=='.') { if(i<lim) s[i]=c; for(i++; (c=getch())>='0' && c<='9'; i++) if(i<lim) s[i]=c; } /* A szám rendben van */ if(i<lim) { ungetch(c); s[i] = '\0'; return(number); } /* A karakterlánc túl hosszú. A további része elveszik. */ else { while(c!='\n' && c!=eof) c=getch(); s[lim-1] = '\0'; return(toobig); } }
Élettartam (lifetime, duration) Élettartam: az a periódus a futásid alatt, amíg az objektum/függvény létezik (memóriafoglalás). Típusai: statikus (static, extern) az objektumhoz memóriát rendelnek a futás kezdetét l a végéig ilyen az összes függvény, és a fájl hatáskör változók a többi is ilyenné tehet static, extern kulcsszavakkal implicit inicializálás: minden bit zérus lokális (auto, register) blokkba belépést l annak elhagyásáig rendelnek memóriát hozzájuk függvényparaméterek is ilyenek csak a blokkokon belüli változók el tt szerepelhet az auto kulcsszó, de felesleges kiírni lokális élettartam lokális hatókör, lokális hatókör lokális vagy statikus élettartam register egyúttal auto is (jut neki regiszter?) csak explicit inicializáció történhet dinamikus stdlib.h malloc(), calloc(), free(), realloc()
Hatáskör (érvényességi tartomány, scope) Meghatározza, hogy az objektumot a program mely részén lehet elérni; deklarációtól és annak helyét l függ en: blokk (lokális, bels ) függvény deklarációtól a tartalmazó blokk végéig, ideértve a beágyazott blokkokat is ilyenek pl. a függvény formális paraméterei csak az utasításcímkéknek van ilyen! függvény prototípus csak a függvény prototípusában lév azonosítóknak van ilyen! azonosítók használata technikailag felesleges, de dokumentációs célra jó lehet getline() prototípusok int getline(char[], int); int getline(char beolvasottszoveg[], int dbkorlat); fájl (globális, küls ) minden függvény testén kívül deklarált azonosítók; deklarációs ponttól a fájl végéig
Láthatóság (visibility) és névterület (namespace) Láthatóság: a forráskód területe, melyben az azonosító elérhet, hivatkozható hatáskör és láthatóság ált. fedik egymást, de beágyazott blokkban deklarált azonosító ideiglenesen elrejtheti az objektumot Névterület: ezen belül kell az azonosítóknak egyedinek lenniük
Kapcsolódás (csatolás, linkage) Az azonosítók el fordulásának objektumokhoz, függvényhez rendelése a kapcsoló-szerkesztés során. Kapcsolódási attribútumok: Részletek: küls (external) minden példány ugyanazt az obj.-t/fv.-t reprezentálja az egész programban bels (internal) az azonosító csak egy fordítási egységen belül jelenti ugyanazt az obj.-t/fv.-t nincs kapcsolódás (no) expliciten static-nek deklarált, fájl hatáskör obj./fv. azonosítók bels kapcsolódásúak explicit extern tárolási osztályú obj./fv. kapcsolódása egyezik a látható, fájl hatáskör deklarációval. Ha ilyen nincs küls kapcsolódású lesz. fv. explicit extern specikátorral és anélkül is küls kapcsolódású fájl hatáskör obj. azonosító tárolási osztály specikátor nélkül küls kapcsolódású blokkon belüli, extern nélküli azonosítónak nincs kapcsolódása, egyedi entitás nincs kapcsolódása továbbá: nem obj./fv. névvel deklarált azonosítónak, pl. typedef, fv. paramétereknek