Programozás II. Horváth Ernő

Hasonló dokumentumok
Programozás 6. Dr. Iványi Péter

Programozás I gyakorlat. 10. Stringek, mutatók

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.

Programozás II. Fájlkezelés

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

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

8. gyakorlat Pointerek, dinamikus memóriakezelés

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

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

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

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

*p2; Programozás II. Horváth Ernő

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

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

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

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

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

A helyi információ és az id kezelése

Függvények. Programozás I. Hatwágner F. Miklós november 16. Széchenyi István Egyetem, Gy r

C memóriakezelés. Mutató típusú változót egy típus és a változó neve elé írt csillag karakterrel hozhatjuk létre.

Programozas 1. Strukturak, mutatok

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

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

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.

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

LabVIEW Academy. 6. óra state machine

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

1. Alapok. Programozás II

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

A C programozási nyelv I. Bevezetés

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

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

A C programozási nyelv I. Bevezetés

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

A C programozási nyelv III. Pointerek és tömbök.

Példák tematikus csoportosításban

Programozás II. segédlet

7. gyakorlat Sorozatok, Fájlkezelés

Programozás I gyakorlat

A C programozási nyelv III. Pointerek és tömbök.

Programozás I. gyakorlat

Programozás I gyakorlat

1.1. A forrásprogramok felépítése Nevek és kulcsszavak Alapvető típusok. C programozás 3

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

Programozás II. 2. Dr. Iványi Péter

tétel: különböző típusú adatokat csoportosít, ezeket egyetlen adatként kezeli, de hozzáférhetünk az elemeihez is

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

Programozás I gyakorlat

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

Programozás alapjai. (GKxB_INTM023) Dr. Hatwágner F. Miklós augusztus 29. Széchenyi István Egyetem, Gy r

Típusok és konstansok

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

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

Írjon olyan programot a standard könyvtár alkalmazásával, amely konzolról megadott valós adatokból meghatározza és kiírja a minimális értékűt!

Adatbázis rendszerek Gy: Algoritmusok C-ben

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

C programozás. 1 óra Bevezetés

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)

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

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

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

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

5. Gyakorlat. struct diak {

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

Algoritmusok és adatszerkezetek gyakorlat 06 Adatszerkezetek

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

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

C programnyelv 1. Kedves Kollegina, Kolléga!

Objektumok tulajdonságai

Programozás C nyelven (9. ELŐADÁS) Sapientia EMTE

M veletek és kifejezések

MATLAB. 9. gyakorlat. Cellatömbök, struktúrák, fájlműveletek

Programozás C és C++ -ban

Programozás II. 4. Dr. Iványi Péter

5. gyakorlat. Konstansok Tömbök Stringek

10. gyakorlat. Pointerek Tárolási osztályok

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

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

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

Programozási segédlet

Bevezetés a programozásba I.

Programozási Nyelvek: C++

Programozás alapjai gyakorlat. 2. gyakorlat C alapok

INFORMATIKAI ALAPISMERETEK

7. Laboratóriumi gyakorlat: Vezérlési szerkezetek II.

C string műveletek (string.h alkalmazása)

Programozás C nyelven (13. ELŐADÁS) Sapientia EMTE

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

Programozás alapjai. (GKxB_INTM023) Dr. Hatwágner F. Miklós szeptember 27. Széchenyi István Egyetem, Gy r

Operációs rendszerek. 11. gyakorlat. AWK - szintaxis, vezérlési szerkezetek UNIVERSITAS SCIENTIARUM SZEGEDIENSIS UNIVERSITY OF SZEGED

Programozás I gyakorlat

Programozás alapjai. 6. gyakorlat Futásidő, rekurzió, feladatmegoldás

Programozás C nyelven (10a. ELŐADÁS) Sapientia EMTE

A verem (stack) A verem egy olyan struktúra, aminek a tetejéről kivehetünk egy (vagy sorban több) elemet. A verem felhasználása

Operációs rendszerek. 9. gyakorlat. Reguláris kifejezések - alapok, BASH UNIVERSITAS SCIENTIARUM SZEGEDIENSIS UNIVERSITY OF SZEGED

Karakter- és sztringkezelő függvények, matematikai függvények

Nagy HF u tmutato 2011/2012 II. fe le v

A függvény kód szekvenciáját kapcsos zárójelek közt definiáljuk, a { } -ek közti részt a Bash héj kód blokknak (code block) nevezi.

Programozás C++ -ban 2007/1

Bevezetés a programozásba I.

Átírás:

Programozás II. Horváth Ernő

ANSI C adattípusok Cím szerinti paraméter átadás Mutatók Mutatók és tömbök Mutatótömbök Dinamikus memóriakezelés Malloc, Calloc, Free, Realloc Random Typedef, Struktúrák State machine állapotgép Linked list (láncolt lista) Fájlkezelés Feladat char * 01 Feladat char * 02 Feladat valós zámok tömbbe mutatókkal Feladat memóriafoglalás Feladat - Dinamikus tömb 02 Feladat - Dinamikus tömb 03 Feladat - törlés láncolt listából Feladat - láncolt lista megfordítás Feladat fájlolvasás Feladat - függvénymutató Összes feladatmegoldás Összes feladatleírás 2

A félév 1-3. hét Karaktermutatók. Karakterlánc (string) kezelő függvények. Mutatótömbök. Többdimenziós tömbök. Dinamikus memóriakezelés. Tömbök, mint függvényparaméterek. Parancssori paraméterek. Függvénymutatók. Typedef. Algoritmusok: Pontosan ellenőrzött bemenet. 4-5. hét Struktúrák és függvények. Uniók. Bitmezők. Névterületek. Struktúratömbök pontokhoz, dátumkezeléshez. Dinamikus adatszerkezetek: listák, fák 6-7. hét Magas szintű (stream) bemenet, kimenet. Változó paraméter lista. Fájlok másolása, egyesítése, középre igazítás. 8-9. hét Helyi beállítások, széles karakterek, karakterláncok, időkezelés. 10-14. hét Alacsony szintű (leírós) fájlkezelés. Könyvtárak kezelése, folymatok (process) cső (pipe) kezelése. Jelkezelés (signal), foglalatok (socket).

Elérhetőségek Hatwágner Ferenc Miklós http://www.sze.hu/~hatwagnf/ hatwagnf@sze.hu Horváth Ernő http://www.sze.hu/~herno/ Tanszéki honlap http://it.sze.hu 4

Vizsga Követelmények Vizsgaidőszakban Alapfeladat 2es, minden plusz feladat után egy jeggyel jobb az érdemjegy, de az alapfeladatnak működnie kell szintaktikai hiba nélkül ZH nincs Beadandó feladat aláírásért» elearning.sze.hu Katalógus nincs 5

Programozási nyelvek népszerűsége (2012) C Java Objective-C C++ C# Egyéb 19% 39% 16% 7% 9% 10% Forrás: http://www.tiobe.com 6

1987-től 2012-ig 2012 2007 1997 1987 C 1 2 1 1 Java 2 1 5 - Objective-C 3 43 - - C++ 4 5 2 6 C# 5 7 - - PHP 6 4 - - (Visual) Basic 7 3 3 5 Python 8 8 29 - Perl 9 6 7 - Ruby 10 10 - - Lisp 13 16 10 3 Ada 18 19 16 2 7

C történelem 1970 B - Bell Labs, Ken Thompson 1972 C - Bell Labs, Dennis Ritchie 1973 UNIX kernel C-ben átírva 1978 Brian Kernighan & Ritchie: The C Programming Language 1990 ANSI C Thompson Ritchie Kernighan

Kabinet használat Felhasználó név: EIK Jelszó nincs L:\ - írási jog, vizsgán ide kell a végső kódnak felkerülnie D:\ - írási jog C:\temp - ide érdemes dolgozni K:\GB_IN001_2 vizsgán, órán ezek a feladatok használhatóak

K meghajtó \\x346-1.eik.sze.hu\szakkabinet\kozos\gb_in001_2_programozas_2

ANSI C adattípusok Típus Méret bájtban Méret bitben (minimum) (minimum) Határok: Egész char 1 8-128 127 unsigned char 1 8 0 255 int 2 16-32768 32767 unsigned int 2 16 0 65535 long 4 32-2.147.483.647-2.147.483.647 unsigned long 4 32 0 4.294.967.295 float 4 32 Lebegőpontos ±3.4*10-38 - ±3.4*10 +38 6 7 decimális jegy pontosság double 8 32 long double 10 80 ±1.7*10-308 - ±1.7*10 +308 15 16 decimális jegy pontosság ±1.2*10-4932 - ±1.2*10 +4932 19 decimális jegypontosság

Pointerek, más néven mutatók A mutató olyan változó, amelyik memóriacímet tartalmaz. Létrehozása az indirekció operátorral (*) történik. int-re mutató típusos pointer: int * p; típus nélküli pointer: void * p; A változó nevéből a címképző (&) operátorral kaphatjuk meg a változó címét: int x,*p; p=&x; Forrás: A programozás alapjai - Pohl László, Budapest, 2010

Tömör C kód mutatókkal #include <stdio.h> main(t,_,a)char *a;{return!0<t?t<3?main(-79,-13,a+main(-87,1-_, main(-86,0,a+1)+a)):1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13? main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t, "@n'+,#'/*{w+/w#cdnr/+,{r/*de+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#\ ;#q#n+,/+k#;*+,/'r :'d*'3,{w+k w'k:'+e#';dq#'l \ q#'+d'k#!/+k#;q#'rekk#w'rekk{nl]'/#;#q#n'){)#w'){){nl]'/+#n';drw' i;# \ ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'k {rw' ik{;[{nl]'/w#q#n'wk nw' \ iwk{kk{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'{nlwb!/*de'c \ ;;{nl'-{rw]'/+,##'*#nc,',#nw]'/+kd'+e+;#'rdq#w! nr'/ ') +{rl#'{n' ')# \ '+##(!!/") :t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1) :0<t?main(2,2,"%s"):*a=='/' main(0,main(-61,*a, "!ek;dc i@bk'(q)-[w]*%n+r3#l,{:\nuwloca-o;m.vpbks,fxntdceghiry"),a+1);

Mutatók int n,*p; p=&n; n=6; printf("%d\n", n); // n helyett írhattunk volna *p-t is *p=5; printf("%d\n", n); // n helyett írhattunk volna *p-t is Futás: 6 5 p címe pl. 0x0028F8D8 értéke: 06

Csere mutatókkal void csere(int *px, int *py){ int tmp; tmp = *px; *px = *py; *py = tmp; //a módosítandó értékek címének átadása Main: int a=22, b=1020; csere(&a, &b); printf("%d", b); Futás: 22

NULL pointer A NULL pointer egy olyan speciális mutatót jelent, amely nem mutat semmilyen változóra. Bármilyen típusú pointer lehet NULL értékű. if (ptr!= NULL) printf("valahova mutat.\n"); if (ptr == NULL) printf("sehova sem mutat.\n"); if (ptr) printf("valahova mutat.\n"); if (!ptr) printf("sehova sem mutat.\n");

Cím szerinti paraméter átadás void ertekszerint(char x){ x = 22; void cimszerint(char *x){ *x = 33; void main(){ char e = 1, c = 1; ertekszerint(e); cimszerint(&c); printf("ertek szerint: %d\ncim szerint: %d", e, c); Futás: Ertek szerint: 1 Cim szerint: 33

Mutatók és tömbök A mutatók jól használhatók tömbök bejárására, feldolgozására De a mutatók nem tömbök >> memória foglalás A tömbnevének [ ] nélküli leírása egyenértékű a 0 indexű elem címével. Például: tombom ugyanazt jelenti, mint &tombom[0]. char x[100]; char *m; m=&x[0]; m=x; *(m+1); // egyenértékű x[1]

Mutatók és tömbök példa int tombom[10]; int *p = tombom; *(tombom + 3) = 5; //vagy ugyanez másképp: tombom[3] = 5; *(p + 2) = 8; //ugyanez: p[2] = 8; Gyakorlatilag [] indexelő operátort használva címszámítást és indirekciót (dereferálást) is végzünk. A fordító a kezdőcímhez hozzáadja az adott típusnak megfelelően foglalt memóriarészeket, így éri el az adott elemet.

Feladat legnagyobb - mutatókkal int legnagyobb(int *tomb, int meret){ int n; int max; max=tomb[0]; for( n=1; n<meret; n=n+1 ) if( max<tomb[n] ) max=tomb[n]; return(max); main(){ int t[5]; t[0]=49; t[1]=40; t[2]=22; printf("legnagyobb=%d\n", legnagyobb(t, 3) ); getchar();

Feladatok char * 01 Készítse el az alább felsorolt, ismert C függvények mutatós változatát! A char * visszatérésű függvények az eredmény címével térnek vissza! Sor beolvasása a szabvány bemnetről: int getline(char s[], int lim) int getline(char s*, int lim) c karakter törlése a karakterláncból: void squeeze(char s[], int c) char *squeeze(char s*, int c) Karakterlánc egésszé konvertálása: int atoi(char s[]) int atoi(char s*))

Getline (mutatók nélkül) Szabvány bemenetről egy sor beolvasása. A sor karaktereit rendre elhelyezi az s karaktertömbben. A befejező soremelés karaktert nem viszi át a tömbbe, hanem helyette lánczáró '\0' t ír a karakterlánc végére. Legfeljebb lim karaktert tárol a tömbben, visszatérési értéke az s tömbben elhelyezett karakterlánc hossza.

int getline(char s[],int lim){ int c, i; for(i=0; i<lim && (c=getchar())!=eof &&!='\n'; ++i) s[i]=c; s[i]='\0'; while(c!=eof && c!='\n') getchar(); return(i);

Getline s[] indexelése helyett a t mutatóval haladunk az s karaktertömbön. A t mindig a következő szabad helyre mutat a tömbben, melynek túlírását az n elfogyása akadályozza meg. n-->0 A karakterláncot záró '\0' címéből a tömb kezdőcímét kivonva, éppen a karakterlánc hosszát kapjuk: return(t-s)

int getline(char *s, int n){ int c; char *t=s; while(n-- > 0 && (c=getchar())!=eof && c!='\n') *t++ = c; *t='\0'; while(c!=eof&&c!='\n') c=getchar(); return(t-s);

squeeze void squeeze(char s[], int c){ int i,j; for(i=j=0; s[i]!='\0'; i++) if(s[i]!=c) s[j++]=s[i]; s[j]='\0';

*squeeze char *squeeze(char *s, int c) c karakter törlése az s karakterláncból a saját helyén.

*squeeze main(){ char s[]="ebben vannak n-ek"; printf("%s\n",squeeze(s,'n')); return(0); char *squeeze(char *s, int c){ char *p,*t; p=s;t=s; while(*p){ if(*p==c) p++; else *s++=*p++; *s=0; return(t);

*squeeze char *squeeze(char *s, int c){ char *t, *ment=s; for(t=s; *s; ++s) if(*s!=c) *t++=*s; *t='\0'; return ment;

A klasszikus atoi int atoi(char s[]){ int i,n=0,sign=1; for(i=0;s[i]==' ' s[i]=='\n' s[i]=='\t'; ++i); if(s[i]=='+' s[i]=='-') sign=(s[i++]=='+')? 1 : -1; for(;s[i]>='0'&&s[i]<='9';++i) n=10*n+s[i]-'0'; return(sign*n);

Atoi mutatókkal int atoi(char *s){ int n=0, sign=1; for( ; isspace(*s); ++s); if(*s=='+' *s=='-') sign=(*s++=='+')? 1 : -1; for( ; isdigit(*s); ++s) n=10*n+*s-'0'; return(sign*n);

atoi Eredeti: stdlib.h Karakterlánc egésszé alakítása (isspace >> ctype.h) Íjuk meg ennek is a mutatós változatát!

Feladat char * 02 Készítse el az alább felsorolt, ismert C függvények mutatós változatát! A char * visszatérésű függvények az eredmény címével térnek vissza! Karakterlánc nagybetűssé alakítása: void strupr(char s[]) char *strupr(char *s) továbbá strlwr Karakterlánc megfordítása helyben: void strrev(char s[]) char *strrev(char *s) Karakterlánc feltöltése c karakterrel: void strset(char s[], int c) char *strset(char *s, int c)

strrev (mutatók nélkül) void strrev(char s[]){ int i, j; char kar; for(i = 0, j = strlen(s)-1; i<j; ++i, --j){ kar = s[i]; s[i] = s[j]; s[j] = kar;

strrev s[0] s[1] s[2] s[3] s[4] s[5] s[6] s[7] s[8] s[9] a b c d x 6 7 8 9 '\0' [i=0] 9 2 3 4 x 6 7 8 a '\0' [i=1] 9 8 3 4 x 6 7 b a '\0' [i=2] 9 8 7 4 x 6 c b a '\0' [i=3] 9 8 7 6 x d c b a '\0'

void main(void){ int i,n; float array[size]; printf("\nvalos szamok tombbe olvasasa es visszairasa cimeikkel egyutt.\n"); printf("legfeljebb %d szám van, ill. EOF-fal kevesebb!\n", SIZE); printf("adja meg a szamokat!\n\n"); // A bekérések sorszámozása:

for(n=0; n<size; ++n) if(printf("%4d: ", n+1), (i=getfloat(array+n))==eof) break; else if(!i) --n; printf("\n\na tombelemek cimei rendre:\n\n"); for(i=0;i<n;i++)printf("%10p", &array[i]); printf("\n\na tombelemek ertekei rendre:\n\n"); for(i=0;i<n;i++)printf("%10.2f", array[i]); putchar('\n'); getchar();

String bejárása - mutatók char *s="szoveg"; for(;*s!='\0'; ++s) printf("%c\n", *s); vagy röviden: for(;*s; ++s) printf("%c\n", *s);

Mutatótömbök Mutatókat tartalmazó tömbök Pl. stringeket is tárolhatunk így tömbben A main() argumentumlistája #include <stdlib.h> #include <stdio.h> void ir( int ennyit, char **ezt ){ int n; for(n=0; n<ennyit; ++n ) printf("%s\n", ezt[n] ); main(){ char *tomb[3]; tomb[0]="szoveg"; tomb[1]="valami"; tomb[2]="xyz"; ir(2, tomb ); getchar();

A main() argumentumlistája Parancssori argumentumok fogadása Minden C programban kell lennie egy a programot elindító függvénynek, mely konzol bázisú alkalmazások esetében a main függvény. A paraméterek elhagyhatóak és nem ANSI szabványosak. Project properties >> Debugging >> Command arguments #include <stdio.h> int main( int argc, char *argv[] ){ int n; for(n=0; n<argc; ++n) printf( "%s ", argv[n] ); printf("\n"); return(0);

Függvény (kód) mutató A C nyelvben a mutatóknak két fajtája van: (adat) objektumra mutató mutatók és függvényre (kód) mutató mutatók void doublerendez(double tomb[], int meret, int (*kisebb_e)(double a, double b)); int kisebb(double a, double b) { return a < b; int abszolutkisebb(double a, double b) { return fabs(a) < fabs(b);... doublerendez(tomb, 10, kisebb);

*argv[] Az argv a paraméter karakterláncokra mutató mutatótömb, ahol az egyes elemek rendre: argv[0]: A futó program (meghajtó névvel és) úttal ellátott azonosítójára mutató mutató. argv[1]: Az első parancssori parameter karakterlancara mutató mutató. argv[2]: Az második paraméter karakterlánc kezdőcíme. argv[argc - 1]: Az utolsó parancssori paraméter karakterláncára mutató mutató. argv[argc]: NULL mutató.

A printf utolsó, *argv++ kifejezése Az argv t a main paraméterként kapja, tehát csak címmásolat, vagyis a main ben akár el is rontható. Az argv típusa char **, és funkcionálisan a parancssori paraméter karakterláncok kezdőcímeit tartalmazó mutatótömb kezdetének cime. A rajta vegrehajtott indirekcióval a típus char * lesz, és épp a mutatótömb első elemet (argv[0]) érjük el. Az utótag ++ operator miatt eközben az argv mar a második mutatótömb elemre (argv[1]) mutat. Elérjük ezt is, es mellékhatásként az argv megint előbbre mutat egy tömbelemmel. Tehát a ciklusban rendre végigjárjuk az összes parancssori paramétert.

sizeof A sizeof egyoperandusos magas prioritású művelet, mely az operandusa tárolásához szükséges memória mennyiségét szolgáltatja bájtban. sizeof(egyoperandusos-kifejezés) pl. sizeof(tomb) sizeof(típusnév) pl. sizeof(int) Az egyoperandusos kifejezés típusát a fordító a kifejezés kiértékelése nélkül határozza meg, azaz ha az operandus tömbazonosító, az egész tömb bájtokban mért helyfoglalásához jutunk.

Dinamikus memóriakezelés A C fordító a memóriát három részre osztja: 1. data segment» elsődleges adatterület» globális objektumok, konstansok 2. stack segment» verem adatterület» lokális objektumok, függvények paraméterei 3. heap segment» dinamikus adatterület» dinamikusan, futásidőben foglalt, változó méretű memóriablokkok Az stdlib.h fejfájl dinamikus memóriakezelést megavlósító függvényei: void *malloc(m), void *calloc(a,b), void free(void *memória), void realloc(c,m) stb.

void *malloc(m), void *calloc(a,b) A malloc-nak egy paramétere van: hány bájtot szeretnénk lefoglalni. Ezzel szemben a calloc-nak két paramétere van, és a kettő szorzata adja a kívánt bájtszámot. A malloc által lefoglalt memóriaterület memóriaszemetet tartalmaz, azaz a dinamikusan lefoglalt változó kezdeti értéke bármi lehet, ahogyan ezt az egyszerű, nem dinamikus változóknál is megszoktuk. A calloc ezzel szemben a lefoglalt terület minden bájtját kinullázza. NULL-lal tér vissza hiba esetén.

void free(void *memória), void realloc(c,m) A free a malloc által lefoglalt területet szabadítja fel. Első paramétere az a mutató, amit még a malloc adott vissza. A realloc a lefoglalt terület méretét változtatja meg. Első paramétere a memóriacím, második pedig az új méret.

memcpy, memccpy void memcpy(void *cél, const void *forrás, size_t darab); a memóriaterület tartalmát másolhatjuk át void memccpy(void *cél, const void *forrás, int keres, size_t darab); a memóriaterület tartalmát másolhatjuk át, adott méret vagy hatójel alapján

Figyeljünk az érvénytelen mutatókra! Súlyos és veszélyes programozási hiba az érvénytelen mutatók használata, például egy free() parancs után. Elképzelhető, hogy elsőre működik a program, mert a felszabadított memóriaterületen még megtalálható a helyes érték. Például hibás kódrészlet: char *fuggveny() { char c = 'a'; return &c; // hiba! char *p = fuggveny(); // hiba!

Feladat memóriafoglalás malloc1.c Két karakterlánc egymás után másolása az általa lefoglalt memóriaterületre A func helyére a fordító a függvény nevét jelző mutatót helyezi. #ifndef func #define func FUNCTION #endif» Nem ANSI C szabványos megoldás.

Feladat 2d dinamikus tömb Írjon olyan függvényt, amely cím szerint átvett paraméterben adja vissza a lefoglalt 2D dinamikus tömbre mutató pointert! void foglal(float ***ptomb, int szeles, int magas) Figyeljünk arra, ha a változó típusa float **, akkor a címének típusa float ***, így cím szerinti paraméterátadásnál is így kell használni.

Feladat 2d dinamikus tömb megoldás void foglal(float ***ptomb, int szeles, int magas) { float **uj; int y, z; uj = (float**)malloc(magas * sizeof(float*)); for (y = 0; y < magas; ++y){ uj[y] = (float*)malloc(szeles * sizeof(float)); for(z = 0; z < szeles; ++z){ uj[y][z] = (float)(y + z); //printf("%.1f\n", uj[y][z]); *ptomb = uj; // *ptomb >> a float** típusú változó!

Feladat mátrixszozás Készítsen programot két mátrix összeadására! A mátrixoknak foglaljon helyet a memóriában! A mátrixok mérete azonban csak futás időben dől el. A számok beolvasásához felhasználható az int getint(int *) függvény, de feltétlenül lássuk el minimális inputellenőrzéssel!

2d tömb indexelése int tomb2d[2][4]={{1,2,3,4,{5,6,7,8; Indexelés: tomb2d[i][j] máshogy: *(tomb2d[i] + j) (*(tomb2d + i))[j] *((*(tomb2d tomb2d+ i)) + j) *(&tomb2d[0][0] + 4*i + j) Tömbreprezentáció: 1 2 3 4 5 6 7 8 A memóriában, sorfolytonosan: 1 2 3 4 5 6 7 8

2D tömb megvalósítások 1. Sorfolytonosan 2. Soronkénti foglalás 3. Leképezés és mutatótömb "jagged array"

Soronkénti foglalás egydimenziós mutatótömbbel #include <stdio.h> #define MERET 3 void main(){ char* muttomb[meret] = {"Egy","két","há"; int i; printf("'muttomb' elemei: \n"); for (i = 0; i<meret; i++) printf("%s (%p ) (% p)\n", muttomb[i], &muttomb[i], &muttomb[i][0]); putchar('\n '); getchar(); 'muttomb' elemei: Egy (0114FE18) (01345858) két (0114FE1C) (0134585C) há (0114FE20) (01345860) Memóriában: 0x0114FE18: 01345858 0134585c 01345860 cccccccc 0x01345858: 00796745 0074e96b 0000e168 20756d27 0x01345858: Egy.két.há.. 0x0134585C: két.há...x 0x01345860: há...xxxxx

Feladat valós számok tömbbe, mutatókkal Készítse el a PELDA24.C-hez hasonlóan a valós számok tömbbe olvasását és visszaírását! Az int getint(int*) függvény int getfloat (float *)-ra változtatandó! Az int bufp; lecserélendő char *bufp;-re! Tegyünk legalább annyi inputellenőrzést a getfloat-ba, hogy legalább egy numerikus karakter meglétét megkövetelje, ill. konvertálhatatlan karakterek esetén ürítsük ki a bemeneti puffert a legközelebbi fehér karakterig!

Random - Véletlenszám #include <stdio.h> #include <time.h> #include <stdlib.h> #define MAX 20 void main(){ int r = 0, i; srand(time(null)); for(i=0; i<20; i++){ r = (rand() % MAX); printf("%d\n", r); getchar();

Random - Véletlenszám A véletlenszám-generátor használata: program elején inicializálni kell (srand) egyszer, és utána a rand() ad egy véletlen számot. A %100 hatására 0..99 között lesz, ehhez 1-et adva kapjuk az 1..100 tartományt. A működéshez a stdio.h, time.h, stdlib.h headerek szükségesek. srand(time(null)); r = rand()%100 + 1;

Feladat Sudoku generálás Generáljunk egy 9 x 9-es tömböt, úgy, hogy 1-től 9-ig legyenek benn számok, de tetszőleges sorban, oszlopban mindegyik szám csupán egyszer forduljon elő. 1 2 3 4 5 6 7 8 9 2 3 4 5 6 7 8 9 1 3 4 5 6 7 8 9 1 2 4 5 6 7 8 9 1 2 3 5 6 7 8 9 1 2 3 4 6 7 8 9 1 2 3 4 5 7 8 9 1 2 3 4 5 6 8 9 1 2 3 4 5 6 7 9 1 2 3 4 5 6 7 8 3 9 1 4 2 7 6 5 8 4 1 2 5 3 8 7 6 9 5 2 3 6 4 9 8 7 1 6 3 4 7 5 1 9 8 2 7 4 5 8 6 2 1 9 3 8 5 6 9 7 3 2 1 4 9 6 7 1 8 4 3 2 5 1 7 8 2 9 5 4 3 6 2 8 9 3 1 6 5 4 7

Typedef #include <stdio.h> typedef int egesz; void main(){ egesz e=42; printf("e=%d\n", e); Az egesz típus közvetlenül az int típusból származik. Persze ez így még nem túl hasznos.

Struktúrák #include <stdio.h> struct Pont{ int x; int y; int z; ; A ; nem véletlen a struktúrák után. void main(){ struct Pont p1, p2; p1.x=8; p1.y=5;

Typedef #include <stdio.h> struct Pont{ int x; int y; int z; ; typedef struct Pont pont; int kiir( pont *p ){ printf("x=%d\ny=%d\nz=%d\n",p->x, p->y, p->z); void main(){ pont p1, p2; p1.x=1; p1.y=42; p1.z=84; kiir(&p1); A Pont egy struktúra, a pont pedig típusdefiníció. A ; nem véletlen a struktúrák után. typedef struct Pont { int x; int y; int z; pont; Elhagyható névtelen struktúra.

Typedef typedef struct { //egy pont a síkban double x; double y; Pont; typedef struct { //szakasz két pont közt Pont eleje; Pont vege; Szakasz; typedef struct { //középpont és sugár Pont kozeppont; double sugar; Kor;

Structure dereference operator Structure dereference (röviden: nyíl) operátor jelentése a mutató által mutatott struktúra adattagja. Egyrészt dereferál, másrészt adattagot is kiválaszt, így rövidebb. (*p).adattag vagy rövidebb jelöléssel: p->adattag A pont "." adattag kiválasztó operátor nagyobb precedenciájú, mint a "*" índirekció operátor. Ezért is kell zárójelezni, a nyíl operátor erre ad könnyebb módot.

Feladat Írjon programot, mely a jelzett adatstruktúrákat használja. Egy double szakaszhossza(szakasz *sz) prototípusú függvény visszatérési értékeként számolja ki a megadott szakasz hosszát! typedef struct{ int x; int y; Pont; //szakasz két pont közt typedef struct{ Pont eleje; Pont vege; Szakasz; Megoldás: szakasz.c

Feladat Írjon programot, mely a jelzett adatstruktúrákat használja. A feladatban tartsuk számon, hogy az osztálytársak kit tartanak a legjobb barátjuknak. Írjon függvényt, mely kiírja, hogy az adott személy barátsága kölcsönös-e. Továbbá listázza az összes személy barátait. typedef struct Barat{ char nev[32]; int baratja; barat; barat baratok[10]; int kolcsonos(int szemely){ if(baratok[baratok[szemely].baratja].baratja==szemely) return 1; else return 0; Megoldás: szakasz.c

State machine - állapotgép Az állapotgép egy gyakran használt tervezési minta (design pattern), A lényege, hogy az adott alrendszer csak egy állapotban lehet egyszerre, ebből az átmenetek és az egyes állapotok tevékenységei pontosan definiáltak. Megadható állapot és tevékenységtáblás, UML diagram és nem szabványos módokon.» http://en.wikipedia.org/wiki/finite-state_machine» http://en.wikipedia.org/wiki/uml_state_machine

Forrás: A programozás alapjai - Pohl László, Budapest, 2010 Szövegfeldolgozó állapotgéppel Tegyük fel, hogy nem tudjuk, milyen hosszú egy sor» nem olvashatunk tömbbe egy sort» karakterenként olvassunk Szűrjük ki a /*-gal kezdőtő és */-ig tartó kommenteket Szöveg* valami /*komment ** és /*/ hh /*a*/ szöveg

4 állapotú state machine implementáció //state machine - állapotgép #include <stdio.h> typedef enum {normal,komment,cs_var,p_var allapotok; int main(void){ int c; allapotok a = normal; //CTR+Z-ig while((c=getchar())!=eof){ switch (a){ case normal: if(c!='/')putchar(c); else a = cs_var; break; case cs_var: if(c=='*') a = komment; else{ putchar('/'); if(c!='/'){ putchar(c); a=normal; break; case komment: if(c=='*') a = p_var; break; case p_var: if(c=='/') a = normal; else if(c!='*') a = komment; break; Forrás: A programozás alapjai - Pohl László, Budapest, 2010

Állapottábla Komment /* */ szűrő Állapot * / egyéb normál normál csillagra vár normál csillagra vár megjegyzés csillagra vár normál megjegyzés perre vár megjegyzés megjegyzés perre vár perre vár normál megjegyzés Tevékenységtábla Állapot * / egyéb normál másol nem másol másol csillagra vár nem másol előző / kiírása, nem másol előző / kiírása, másol Forrás: A programozás alapjai - Pohl László, Budapest, 2010

Komment /* */ szűrő egyéb, '*' '/' egyéb, '/' '*' normal cs_var megj p_var '/' '*' egyéb egyéb '*' '/' Az implementációba be lehet tenni egy plusz állapotot - végállapotot -, amibe bármikor elérhetünk EOF hatására.

Feladat - Dinamikus tömb 02 Írjon programot, amely bekéri, egy sokszög csúcsainak számát, ezután pedig egyesével a csúcsok koordinátáit! A koordinátákat egy struktúrában tárolja, melynek dinamikusan foglaljon memóriát. Inputellenőrzés! (lebege, egesze) typedef struct{ double x, y; Pont; Pont *sokszog; A struktúra méretét megadja az n*sizeof(pont) kifejezés. sokszog=(pont*)malloc(n*sizeof(pont)); Megoldás: dintomb02sokszog.c

Feladat - Dinamikus tömb 03 Írjon programot, amelyben egy int valogat(double *eredeti, int meret, double **ujtomb, int *ujmeret) függvény egy paraméterben kapott double tömbből kiválogatja az átlagnál kisebb értékeket, és egy újonnan lefoglalt dinamikus tömbbe rakja azokat! Az új tömb címével és méretével térjen vissza cím szerint átadott paraméterben! A visszatérési érték legyen IGAZ, ha sikerült a művelet, és HAMIS, ha nem. Megoldás: dintom03valogat.c

Linked list (láncolt lista) Olyan önhivatkozó adatszerkezet, ahol az egyes elemek láncba vannak fűzve azáltal, hogy tárolják a soron következő elem címét. typedef struct elem{ elem; unsigned adat; //egy listaelem //nem csak egy elem lehet struct elem *kov; //itt még kell a struct

Láncolt lista bejárása 1. elem címe: eleje 2. elem címe: eleje->kov (*eleje).kov 3. elem címe: eleje->kov->kov (*(*eleje).kov).kov 4. elem címe: eleje->kov->kov->kov (*(*(*eleje).kov).kov).kov

Egyszerű láncolt lista typedef struct elem { int i; struct elem *kov; elem_t; elem_t *kezd; kezd = malloc(sizeof(elem_t)); kezd->i = 35; kezd->kov = malloc(sizeof(elem_t)); kezd->kov->i = 88;

A lista bejárása ListaElem *mozgo; for (mozgo=eleje; mozgo!=null; mozgo=mozgo->kov){ printf("%d", mozgo->szam); Nézzünk erre egy példát! lancolt00alap.c Forrás: A programozás alapjai - Pohl László, Budapest, 2010

Beszúrás a lista elejére Amit tudnia kell a függvénynek: a lista elejére mutató pointert az új, eltárolandó adatot Az algoritmus: az új elemnek memóriát allokálni, adatait beállítani, a "kov" lesz az új lista elejére mutató pointer üres lista esetén az új elem egymaga lesz a lista meg kell tudnia változtatni az "eleje" mutatót, ezzel tér vissza Lista *lise = NULL; lise = listaelejere(lise, 5); lise = listaelejere(lise, 10);

Beszúrás a lista elejére //lista elejére tesz számokat Lista *listaelejere(lista *eleje, int adat) { Lista *uj=(lista*)malloc(sizeof(lista)); uj->kov = eleje; uj->adat = adat; eleje = uj; return eleje;

Beszúrás a lista végére Amit tudnia kell a függvénynek: a lista elejére mutató pointert az új, eltárolandó adatot Az algoritmus: az új elemnek memóriát allokálni, adatait beállítani, a "kov" értéke most NULL lesz üres lista esetén az új elem egymaga lesz a lista végigiterálunk a listán és megkeressük az utolsó elemet az utolsó elem "kov" mutatóját beállítjuk az új elem címére Lista *lisv = NULL; lisv = listavegere(lisv, 5); lisv = listavegere(lisv, 10);

Beszúrás a lista végére //lista végére tesz számokat Lista *listavegere(lista *eleje, int adat) { Lista *mozgo, *uj; uj=(lista*)malloc(sizeof(lista)); uj->adat = adat; uj->kov = NULL; if (eleje == NULL)//üres lista? return uj; for(mozgo = eleje; mozgo->kov!=null; mozgo=mozgo->kov) ; //üres ciklus, megkeresi az utolsó elemet mozgo->kov = uj; return eleje;

Feladat - törlés láncolt listából Írjon programot, amely a beolvasott karakterláncokat (stringeket) láncolt listában tárolja el. Törölje ki belőle azokat, amelyek pontosan öt betűből állnak. Figyeljünk, arra, ha az első elemet szeretnénk törölni, a kezdőcím is megváltozik (sőt ha az első N darabot, akkor is). Gondoljuk át, hogy nézne ki az algoritmus láncolt listák helyett, többdimenziós tömbökkel. Megoldás: lancolt01torol.c

Feladat - láncolt lista megfordítás Fordítsunk meg egy listát az elemei átláncolása által. Írjon programot, mely számokat olvas be, és kiírja a keletkező listát eredeti sorrendjében (és ezáltal a számokat eredeti sorrendjükben), továbbá kiírja a megfordítottat is. Mindig a lista elejéről veszünk el egy elemet, majd a megfordított lista elejére betesszük azt, így a lista megfordul. Végül az eredeti lista elfogy, amint ez megtörténik, a megfordított lista kész. Megoldás: lancolt02megfordit.c Forrás: A programozás alapjai - Pohl László, Budapest, 2010

Láncolt lista megfordítása átrakott következő 3 Szam *listamegfordit(szam *lista) { Szam *eredeti=lista; Szam *megforditott=null; while (eredeti!=null) { Szam *atrakott=eredeti; Szam *kovetkezo=eredeti->kov; atrakott->kov=megforditott;//új elejére be megforditott=atrakott; eredeti=kovetkezo;//régiből kihagy return megforditott; 1 2 3 eredeti megfordított 2 1 Mindig a lista elejéről veszünk el egy elemet, majd a megfordított lista elejére betesszük azt, így a lista megfordul. Végül az eredeti lista elfogy, amint ez megtörténik, a megfordított lista kész.

Helyi beállítások locale.h fejfájl ANSI/ISO szabványos típusok, szimbolikus állandók és függvények használatához. Ország, nyelv, dátum formátuma, pénznem, stb. Ezeket az összetevőket helyi kategóriáknak nevezzük. Szimbolikus állandók, a program helyi információjának mely részéről van szó. A hely bizonyos vonatkozásait a könyvtári rutinok automatikusan kezelik. Például: strcoll, strxfrm. Más vonatkozások viszont kívül esnek a rutinok hatáskörén. Például a (hiba)üzenetek nyelve. Alapértelmezés a "C" hely, és programindításkor. char *setlocale(int kategoria, const char *locale);

Helyi beállítások Francia Kanadához ANSI alapértelmezett kódlapot állít. setlocale(lc_all, "French_Canada.ACP"); Francia Kanadához OEM alapértelmezett kódlapot állít. setlocale(lc_all, "French_Canada.OCP"); Alapértelmezés: setlocale(lc_all, "C"); A következő, két setlocale hívás funkcionálisan ekvivalens: setlocale(lc_all, "English"); setlocale(lc_all, "English_United States.1252");

Helyi beállítások //Alapbeállítások printf("\nhely: %s\n", setlocale(lc_all, NULL)); printf("szam: %.2f\n\n", atof("3.14")); //Tizedespont //Alapértelmezett hely beállítása strcpy(puff, setlocale(lc_all, "")); printf("\nhely: %s\n", puff); printf("szam: %.2f\n\n", atof("3,14")); //Tizedesvessző // Tizedespont és pénznem karakter: plconv = localeconv(); printf("nem penzugyi decimalis pont: %s\n", plconv->decimal_point); printf("penznem szimbolum: %s\n", plconv->currency_symbol); // A hely visszaállítása C környezetre: setlocale(lc_all, "C"); Megoldás: helyi01.c

Magas szintű bemenet, kimenet Absztrakt módon, fájlok és eszközök (billentyűzet, képernyő, nyomtató, stb.) rugalmas, hasonló módon történő független kezelése ún. folyamok (stream) segítségével.

Fájlkezelés Az stdio.h-ban megadott FILE* típusú pointerrel és függvényekkel. FILE *fp; Megnyitás módja: írás (w) v. olvasás (r), szöveges (t) v. bináris (b), hozzáfűzés (a) írás és olvasás (w+) fp=fopen("t.txt", "wt"); Az fopen() visszatérési értéke: hivatkozás a nyitott fájlra. Sikertelen megnyitásnál értéke: NULL pointer ezt ellenőrizni kell. if (fp == NULL) printf("nem sikerült megnyitni!");

fopen - fclose FILE *fopen(const char *fajlazon, const char *mod); A függvény megnyitja a fajlazonnal megnevezett fájlt, és folyamot kapcsol hozzá. Visszaadja a fájlinformációt tartalmazó FILE struktúrára mutató pointert, mely a rákövetkező műveletekben azonosítani fogja a folyamot, ill. NULL mutatót kapunk tőle, ha a megnyitási kísérlet sikertelen volt. Az első paraméter legfeljebb FILENAME_MAX méretű karakter lehet. Lezáráshoz: int fclose(file *fp) - 0-t ad vissza sikeresetén EOF-ot, ha nem sikerült lezárni

Fájlok kezelése Szöveges 48 65 6c 6c 6f 2c 20 76 69 6c 61 67 21 0d 0a 30 0d 0a 31 0d 0a Hello, vilag! 0 1 fgets, fgetc, fscanf... Bináris 6c cc cc cc 55 8b ec 8b 45 0c 83 f8 04 77 23 8b 0c 85 00 80 c5 lìììu;>ì-ƒø.w#å4â Å fread, fwrite...

Szöveges fájlok A szövegfájlokat az fprintf()-fel és az fscanf()-fel lehet kezelni. Ezeknek első paramétere a megnyitott fájl, a folytatás pedig ugyanúgy van, mint printf()-nél és az scanf()-nél. Egyes rendszerek máshogy jelzik a szövegfájlokban a sorok végét ('\n'). Windowson két bájt, CR LF (0x0D 0x0A), Unixokon csak LF (0x0A), a fájlvég karakter pedig 0x1A. 48 65 6C 6C 6F 2C 20 76 69 6C 61 67 21 0D 0A 30 0D 0A 31 0D 0A 1A Hello, vilag!x0dx0a 0x0Dx0A 1x0Dx0Ax1A

Bináris fájlok fp=fopen(nev, " b") fread(void *ptr, size_t elem_meret, size_t elem_szam, FILE *a_file); fwrite(const void *ptr, size_t elem_meret, size_t elem_szam, FILE *a_file); Lemezre történő kimenet esetén a folyam a sorlezáró '\n' karaktert "\r\n" karakter párral (CR-LF) helyettesíti. Megfordítva: lemezes bemenetnél a CR-LF karakter párból ismét LF karakter lesz. Ezt nevezzük transzlációnak. Ez csak szöveges fájloknál megy végbe binárisnál nem.

Pozícionálás A folyamokat rendszerint szekvenciális fájlok olvasására, írására használják. A magas szintű bemenet, kimenet a fájlt bájtfolyamnak tekinti, mely a fájl elejétől (0 pozíció) indul és a fájl végéig tart. A fájl utolsó pozíciója a fájlméret-1. Az adatátvitel mindig az aktuális fájlpozíciótól kezdődik, megtörténte után a fájlpozíció a fájlban következő, át nem vitt bájtra mozdul. A fájlpozíciót fájlmutatónak is szokás nevezni.

Fájlkezelő függvények fseek(fp, pozíció, honnan) Ugrás a bájtban megadott pozícióra. A honnan értékei: SEEK_SET=elejétől, SEEK_END=végétől, SEEK_CUR=aktuális pozíciótól számolva, a számozás itt is 0-tól kezdődik. ftell(fp) Az aktuális pozíció lekérdezése (bájtokban). fputc(c, fp), fgetc(fp) A putchar() és getchar() párja. fputs(str, fp), fgets(str, méret, fp) A puts() és a gets() párja. errno Globális változó, ami a legutolsó hiba kódját tartalmazza.

Fájlméret Írjunk fájlméretet megállapító függvényt! A fajlmeret elteszi a pillanatnyi pozíciót az aktpoz változóba, hogy a fájl végére állítás után helyre tudja hozni a fájlmutatót. A lekérdezett fájlvég pozíció éppen a fájlméret. #include <stdio.h> long fajlmeret(file *stream) { long aktpoz, hossz; aktpoz = ftell(stream); fseek(stream, 0L, SEEK_END); hossz = ftell(stream); fseek(stream, aktpoz, SEEK_SET); return(hossz);

Getline és scanf megfelelői fájlokra char *fgets(char *s, int n, FILE *stream); Vegyük észre, hogy a jegyzet eleje óta használt getline függvény csak annyiban tér el az fgets től, hogy: A beolvasott karakterlánc méretét adja vissza. A szabvány bemenetről (stdin) olvas, s nem más folyamból, így eggyel kevesebb a paramétere. n karaktert hoz be legfeljebb, vagy '\n'-ig, de magát a soremelés karaktert nem teszi be az eredmény karakterláncba. int fscanf(file *stream, const char *format<, cim,...>); Az fscanf minden mezőt a format karakterláncnak megfelelően konvertál, es letárol rendre a paraméter címeken. A format karakterláncban ugyanannyi konverziót okozó formátumspecifikációnak kell lennie, mint ahány bemeneti mező van

Fájlolvasás - szöveges fájlok #include <stdio.h> #include <stdlib.h> void main() { FILE *f; char c; f=fopen("c:\\temp\\szoveg.txt","rt"); if(f!= NULL){ while((c=fgetc(f))!=eof){ printf("%c ",c); fclose(f); getchar(); #include <stdio.h> #include <stdlib.h> void main() { FILE *f; char szoveg[100]; f=fopen("c:\\temp\\szoveg.txt","rt"); if(f!= NULL){ while((fscanf(f, "%s", szoveg))!=eof){ printf("%s\n", szoveg); fclose(f); getchar();

Fájlolvasás - szöveges fájlok #include <stdio.h> #include <stdlib.h> #include SORHOSSZ 200 void main() { FILE *f; char sor[sorhossz + 1]; f=fopen("c:\\temp\\szoveg.txt","rt"); if(f!= NULL){ while(fgets(sor,sorhossz,f)){ printf("%s ",sor); fclose(f); getchar(); Karakter beolvasása: c=fgetc(f); Sor beolvasása: fgets(sor, HOSSZ, f); Szöveg beolvasása formázottan: fscanf(f,"%s", szoveg); fscanf(f,"%s %s %d",s1,s2,&szam);

Abszolút/relatív útvonal A fájlok elérési útvonala (path) megadható abszolút vagy relatív módon is. Pl: C:\Solution\Debug\Project.exe FILE *relative1; FILE *relative2; FILE *absolute; relative1 = fopen("myfile.txt","r"); relative2 = fopen("data\\myfile.txt","r"); absolute = fopen("c:\\tmp\\myfile.txt","r");

Feladat - fájlolvasás Adott egy szöveges állomány, amelyben angol szavak vannak, minden szó után egy szóköz áll. Írjunk eljárást, amely képernyőre írja azokat a sorokat (több ilyen is lehet), amelyekben a legkevesebb szó van! Feltételezhetjük, hogy a feldolgozandó állomány neve és helye c:\temp\szoveg.txt, és az állomány egyetlen sora sem tartalmaz 2000-nél több karaktert. Megoldás: fajlolvasas06kevesebbszo.c

Feladat fájlolvasás csv Adott egy szöveges csv állomány, pontosvesszővel tagolva. Keresse meg a Jani nevű felhasználót és írja ki a hozzá tartozó email címet. Valósítsa meg ezt egy char* searchname(char *filename, char *stringtofind) prototípusú függvénnyel. Feltételezhetjük, hogy a Jani létezik, további feladatként viszont készüljön fel minél több lehetséges hibára. (hosszú sorok, hibás fájl, stb.) Megoldás: nevek02.c nevek01.c

Feladat - szöveges fájl1 írás #include <stdio.h> #include <stdlib.h> void main(){ FILE *f = fopen("c:\\temp\\szoveg.txt", "w"); if (f == NULL){ printf("hiba\n"); getchar(); else { fprintf(f, "Szoveg.\nEs meg tobb szoveg."); fclose(f);

CSV fájlformátum Notepad szinusz1;szinusz2;koszinusz1 0,0500;0,1100;0,9988 0,0998;0,2598;0,9950 0,1494;0,2494;0,9888 0,1987;0,2587;0,9801 0,2474;0,3074;0,9689 0,2955;0,3155;0,9553 0,3429;0,4429;0,9394 0,3894;0,5000;0,9211 0,4350;0,5350;0,9004 0,4794;0,5194;0,8776 0,5227;0,5827;0,8525 Excel szinusz1 szinusz2 koszinusz1 0,05 0,11 0,9988 0,0998 0,2598 0,995 0,1494 0,2494 0,9888 0,1987 0,2587 0,9801 0,2474 0,3074 0,9689 0,2955 0,3155 0,9553 0,3429 0,4429 0,9394 0,3894 0,5 0,9211 0,435 0,535 0,9004 0,4794 0,5194 0,8776 0,5227 0,5827 0,8525 Coma Separated Values, szöveg alapú fájl

Feladat - szöveges fájl2 Írjon CSV fájlba szinusz, véletlenszámmal módosított szinusz és koszinusz értékeket. Figyeljen a helyi beállítások használatára (tizedes vessző!) szinusz1 szinusz2 koszinusz1 0,05 0,11 0,9988 0,0998 0,2598 0,995 0,1494 0,2494 0,9888 0,1987 0,2587 0,9801 0,2474 0,3074 0,9689 0,2955 0,3155 0,9553 0,3429 0,4429 0,9394 0,3894 0,5 0,9211 0,435 0,535 0,9004 0,4794 0,5194 0,8776 0,5227 0,5827 0,8525 1,5 1 0,5 0-0,5-1 -1,5 1 9 17 25 33 41 49 57 65 73 81 89 97105113121129137145153161169177185193 szinusz1 szinusz2 koszinusz1 Megoldás: fajliras02csv.c

Feladat szöveges fájl3 Hozzon létre a felhasználó által megadatott nevű fájlt, majd írjon bele egy sakktábla mintázatot a felhasználó által megadott mérettel. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Megoldás: fajliras03csillag.c

Feladat - szövegfájl egyesítés Készítsen programot, mely az indító parancssorban megadott szövegfájlokat egyesíti a megadás sorrendjében a parancssorban utolsóként előírt azonosítójú szövegfájlba! Ha parancssori paraméter nélkül indítják a programot, akkor ismertesse a képernyőn, hogyan kell használni! Ha csak egy fájlazonosító van a parancssorban, akkor a szabvány bemenet másolandó bele. A fájlok egyesítése során a folyamat előrehaladásáról tájékoztatni kell a képernyőn! A szabvány bemenet másolása esetén végül közlendő az eredményfájl mérete!

Feladat - szövegfájl Készítsen programot, mely eldönti az indító parancssorban megadott azonosítójú fájlról, hogy ASCII kódú szövegfájl-e, vagy bináris fájl-e! Ha parancssori paraméter nélkül futtatják a programot, akkor ismertesse a képernyőn a használatát!

Feladat - függvénymutató Írjunk függvényt, amely paraméterként kap egy double elemekből álló tömböt, és rendezi azt! A rendezés szempontja (növekvő, csökkenő, abszolútérték szerint növekvő stb.) is legyen a függvény paramétere! void doublerendez(double tomb[], int meret, int (*kisebb_e)(double a, double b))

Időkezelés ANSI/ISO szabványos függvények lekérdezik, tárolják, konvertálják, stb. az aktuális (rendszer) időt. Két típusuk:» Az időzónának megfelelő helyi idő.» Egyezményes (UTC) naptári idő, amit korábban greenwichi közép időnek (GMT) neveztek. time.h fejfájl. Típusok és típusok közti konverziók.

Időkezelés Több fv. osztozik két statikus élettartamú pufferen. Ezek: Az idő karakterlánc char * típusú, statikus karaktertömbben. Pontosan 26 karakteres: "Tue Jan 05 12:03:55 1999\n\0" formájú. 24-órás az időszámítás. Minden mező konstans szélességű. Az új sor és a lezáró null karakter mindig a vég. Az idő struktúra struct tm típusú struktúra, melynek tagjai int ek. A tagok:» tm_sec: Másodperc (0 59).» tm_min: Perc (0 59).» tm_hour: Óra (0 23).» tm_mday: Nap a hónapon belül (1 31).

Időkezelés Az idő struktúra tagjai még:» tm_mon: Hónap az éven belül (0 11, a január a 0).» tm_year: Év - 1900.» tm_wday: A hét napja (0 6, a vasárnap a 0).» tm_yday: Napszám az éven belül (0 365, a január 1 a zérus).» tm_isdst: Nyári időszámítás jelző, mely pozitív, ha a nyári időszámítás hatályban van, és 0, ha nincs. Negatív a jelző, ha a nyári időszámítás állapota ismeretlen.

Időkezelés #include <stdio.h> #include <time.h> void main(){ int yy, mm, dd; struct tm when = {0; char buffer[100] = ""; // dátum beolvasása sscanf_s("2015.12.31", "%d.%d.%d", &yy, &mm, &dd); when.tm_year = yy - 1900; when.tm_mon = mm - 1; when.tm_mday = dd; mktime(&when); // kiíratás v1 strftime(buffer,80,"%y %b %d %I:%M%p -- %c\n", &when); printf(buffer); // kiíratás v2 printf("%d.%d.%d (%d. nap)\n", 1900 + when.tm_year, when.tm_mon + 1, when.tm_mday, when.tm_yday + 1); // nap növelése when.tm_mday+=1; mktime(&when); //kiíratás újra printf("%d.%d.%d (%d. nap)\n", 1900 + when.tm_year, when.tm_mon + 1, when.tm_mday, when.tm_yday + 1); getchar(); 2015 Dec 31 12:00AM -- 12/31/14 00:00:00 2015.12.31 (365. nap) 2016.1.1 (1. nap)

Várakozás [ms] #include <Windows.h> //így OS függő lesz Sleep(900); //900 ms = 0,9 másodperc #include <stdlib.h> _sleep(900); //obsolete elavult Más nyelveken általában delay, wait vagy sleep

Könyvtárak listázása #include <stdio.h> #include <io.h> #include <direct.h> #include <conio.h> #include <ctype.h> #include <string.h> void main(){ char path[50] = "C:\\temp"; struct _finddata_t fajllista; long hfile; if(mkdir("c:\\temp\\ujmappa")) fprintf(stderr, "Nem hozhato letre a mappa\n"); printf("listazzuk a %s tartalamt\n\n", path); if(_chdir(path)) fprintf(stderr, "Nem talalom: %s\n", path); else{ hfile = _findfirst("*.*", &fajllista); while(_findnext(hfile, &fajllista) == 0){ if(!strcmp(fajllista.name, "Program Files")!strcmp(fajlLista.name, "ujmappa")) printf("- %s\n", fajllista.name); else printf(" %s\n", fajllista.name); _findclose(hfile); getchar();

Változó paraméterlista Néhány fv. hívásonként eltérő számú paramétert fogad, pl.: int printf(const char *format,...); stdarg.h typedef char *va_list; #define _INTSIZEOF(x) ((sizeof(x)+sizeof(int)-1)&~(sizeof(int) -1)) #define va_start(ap, utsofix) (ap=(va_list)&utsofix+_intsizeof(utsofix)) #define va_arg(ap, tipus) (*(tipus *)((ap+=_intsizeof(tipus)) - _INTSIZEOF(tipus))) #define va_end(ap) ap = (va_list)0

Változó paraméterlista #include <stdio.h> #include <stdarg.h> void sum(char *uzen,...) { int osszeg = 0, tag; va_list param; va_start(param, uzen); while(tag = va_arg(param, int)) osszeg += tag; va_end(param); printf(uzen, osszeg); void main() { sum("1+2+3+4 = %d\n", 1, 2, 3, 4, 0); getchar();

Feladat változó paraméterlista 1 Írjunk egy változó paraméterszámú függvényt, amely összefűz tetszőleges számú sztringet, és az így kapott új sztringgel tér vissza! A függvény első paramétere az összefűzendő sztringek darabszáma, további paraméterei pedig maguk a sztringek. konkat(5, "Ez ", "egy ", "jó ", "hosszú ", "sztring!"); Megoldás: valtozoparam01.c

Feladat változó paraméterlista 2 Írjunk egy változó paraméterszámú függvényt, amely összefűz tetszőleges számú sztringet, és az így kapott új sztringgel tér vissza! A függvény legalább egy sztringet vár paraméterként, utolsó paraméterének a NULL pointernek kell lennie, ezzel jelezzük a paraméterlista végét. konkat("ez ", "egy ", "jó ", "hosszú ", "sztring", NULL); Megoldás: valtozoparam02.c

Feladat szöveges fájl 8 Írjunk programot, amely egy létező szöveges állomány minden sorát 80 karakter hosszúságúra egészíti ki szóközökkel, ha a sorok 80 karakternél rövidebbek, és csonkítja őket a végükön, ha 80 karakternél hosszabbak! Az új sorokat egy új szöveges állományba kell írni. Megoldás: fajlolvasas08.c

Numerikus integrálás húrtrapézformulával A trapéz szabály egy közelítő numerikus eljárás a határozott integrál meghatározására a b f x dx (b a) f b + f(a) 2

Numerikus integrálás húrtrapézformulával i i+1 f x dx T x[i] + x[i + 1] 2 dt * (x[i] + x[i+1]) / 2.0

Numerikus integrálás húrtrapézformulával i i+1 f x dx T x[i] + x[i + 1] 2 // x - az integrálandó tömb // xsize - x mérete // dt - delta T a mintavételezés időköze double numintegraltrapez(double *x, int xsize, double dt){ int i; double result = 0; for(i = 0; i < xsize - 1; i++) result += (dt * (x[i] + x[i+1]) / 2.0); return result;

Feladat - Szenergy A csatolt szenergy_2014_10_18_17_18_murcia.csv és szenergy_2014_10_17_16_06_rotterdam.csv táblázatos formában tartalmazza egyetemünk Szenergy hallgatói csapatának telemetriás adatait egy spanyol és egy holland versenyről. Feladatunk a rendelkezésekre álló adatokból a körönként megtett távolság kiszámítása. Mivel a fájl tartalmazza a körök számát is az értékekhez, így nem csak a verseny, de a körönkénti távolság is kiszámítható. Ezek közel azonos érték kellenek, hogy legyenek, de előzések és a pályán belüli eltérő nyomvonalak okozhatnak némi eltérést. Figyeljünk rá, hogy csak m/s-ből tudunk métert számolni. for (i = 0; i < recordnumber; i++) pspeedmps[i] = pspeedkmph[i] / 3.6; Megoldás: szenergy00.c szenergy01.c szenergy02.c

Lineáris és Lagrange interpoláció 35 Lineáris 30 25 20 15 10 5 interpolált alappontok 0 1 1,2 1,4 1,6 1,8 2 2,2 2,4 2,6 2,8 3 3,2 3,4 3,6 3,8 4 4,2 4,4 4,6 4,8 5 30 Lagrange 25 20 15 10 interpolált alappontok 5 0 1 1,2 1,4 1,6 1,8 2 2,2 2,4 2,6 2,8 3 3,2 3,4 3,6 3,8 4 4,2 4,4 4,6 4,8 5

Feladat - interpoláció Vegyük a példaként is említett alappont-érték párosokat. x 0 = 1; y 0 = 10,3 x 1 = 2; y 1 = 18,956 x 2 = 3,3; y 2 = 12 x 3 = 5; y 3 = 30 Írjunk programot, amely a standard kimenetre kiírja 0,1-es lépésközzel az interpoláció értékeit mind Lagrange, mind lineáris módszerrel. Plusz feladatként írjuk csv fájlba az eredményt. Megoldás: interpolacio01.c

Lineáris és Lagrange interpoláció // *x - az interpolációs alappontok helye // *y - az interpolációs alappontok értéke // n - az interpolációs alappontok darabszáma (*y és *y tömb elemszáma) // x1 - a hely, ahol meg szeretnek kapni *y1 érteket int lininterp(double *x, double *y, int n, double x1, double *y1){ int i; for (i = 0; i < n - 1; i++){ if ((x[i] <= x1) && (x[i + 1] >= x1)){ *y1 = y[i] + (y[i + 1] - y[i]) / (x[i + 1] - x[i])*(x1 - x[i]); return 0; return 1; int lagrangeinterp(double *x, double *y, int n, double x1, double *y1){ double p = 0.0, s; int i, j; for (i = 0; i < n; i++){ s = 1.0; for (j = 0; j < n; j++){ if (i!= j){ if (x[i] == x[j]) return 1; else s = s*(x1 - x[j]) / (x[i] - x[j]); p += y[i] * s; *y1 = p; return 0;

Feladat - autószerviz Egy autószerviz számítógépe minden megbízásról egy-egy sort ír a SZERVIZ.TXT fájlba. Egy sor a következő adatokat tartalmazza pontosvesszővel elválasztva: RENDSZÁM : 6 karakter TULAJDONOS NEVE : 40 karakter (legfeljebb 40) FORG. ENG. SZÁMA : 8 karakter DÁTUM : 11 karakter (2013.02.19.) ÖSSZEG : 6 karakter (legfeljebb 6 karakter, egész szám) Írjon C programot, amely a SZERVIZ.TXT fájl alapján névsorban kiírja azoknak az autótulajdonosoknak a nevét, akik az átlagosnál többször javíttatták 2013 februárjában autójukat. A fájlt csak egyszer olvashatja be! Használjon dinamikus adat szerkezetet! Megoldás: szerviz.c

Feladat - email címek Írjon egy olyan szabványos ANSI C programot, amely parancssori paraméterként kapja két szövegfájl nevet! Az első fájl egy weboldalt leíró html szöveg. A program gyűjtse ki a fájlban található e-mail címeket, melyeket aztán lista adatszerkezetben taroljon (egy címet elég egyszer eltarolni)! Az e-mail címek olyan karaktersorozatok, melyek az angol ABC kis- es nagybetűiből, számokból, pontokból (.), kötőjelekből(-) es aláhúzás (_) jelekből állnak, es kötelezően tartalmaznak pontosan egy @ karaktert. Az email címben nem állhat egymás mellett két pont, valamint nem állhat egymás mellett egy pont es egy @. Minden egyéb, itt fel nem sorolt karakter elválasztó karakternek minősül. Egy e-mail cím hossza maximum 100 karakter. Ha ennél hosszabb, amúgy érvényes karaktersorozatra bukkanunk, azt ne tekintsük e- mail címnek! A nem e-mail cím karaktersorozatok hossza bármekkora lehet, ezek fix hosszúságú tömbben való eltarolása súlyos hibának minősül. A második parancssori paraméterként kapott szövegfájl minden sora egy-egy, korábban kigyűjtött e-mail címet tartalmaz. A program olvassa be az e-mail címeket, es fésülje össze a most talált címekkel, majd mentse el ugyanebbe a fájlba az összes címet abc sorrendben, minden címet csak egyszer taroljon!

Felhasznált irodalom A C programozási nyelv - Az ANSI szerinti változat. B. W. Kernighan - D. M. Ritchie; Műszaki Könyvkiadó, 1995 Programozás C nyelven - Pere László, Kiskapu 2003 Programozási feladatok és algoritmusok Turbo C és C++ nyelven Benkő Tiborné, Benkő László, ComputerBooks 1997 A programozás alapjai - Pohl László, Budapest, 2010 Programozás I-II. C programnyelv - Bauer Péter, Universitas- Győr Kht., 2005